Firefly III has a recurring transactions option. In order for that to work, you need to setup a cronjob. Without that, you get an error at the top of the page saying:

It seems the cron job that is necessary to support recurring transactions has never 
run. This is of course normal when you have just installed Firefly III, 
but this should be something to set up as soon as possible. Please check 
out the help-pages using the (?)-icon in the top right corner of the page.

Firefly III has an API to which you make a get request that triggers recurring transactions update. API call URL is:

http://FIREFLY_URL/api/v1/cron/TOKEN

To generate a token, go to your Firefly GUI -> Options -> Profile -> Command line token and copy token to URL.

Example:

http://firefly.example/api/v1/cron/6c57c098904f6f4765b52a4bc493687p

If you go to this URL now, your Firefly will run recurring transactions. Because we don’t want to do that manually, we will do it via cronjob that will run every day at 3 AM.

You can do it on any Linux box with normal cronjob:

crontab -e

and add this line:

0 3 * * * http://firefly.example/api/v1/cron/6c57c098904f6f4765b52a4bc493687p

Because we are running Firefly 3 in Docker, more neat option is to add Alpine linux image to our docker compose and run it along within stack:

version: '3.3'

services:
  app:
    image: fireflyiii/core:latest
    restart: always
    volumes:
      - firefly_iii_upload:/var/www/html/storage/upload
    env_file: stack.env
    ports:
      - 8080:8080
    depends_on:
      - db
  db:
    image: mariadb:10.8.2
    hostname: fireflyiiidb
    restart: always
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
      - MYSQL_USER=firefly
      - MYSQL_PASSWORD=secret_firefly_password
      - MYSQL_DATABASE=firefly
    volumes:
      - firefly_iii_db:/var/lib/mysql
  cron:
     image: alpine
     command: sh -c "echo \"0 3 * * * wget http://firefly.example/api/v1/cron/6c57c098904f6f4765b52a4bc493687p\" | crontab - && crond -f -L /dev/stdout"
volumes:
   firefly_iii_upload:
   firefly_iii_db:

After the stack is running, enter a shell of your Alpine container and check if cronjob is present:

crontab -l

Had some issues with Cisco DNAC and Stealthwatch. After settings up Stealthwatch server and Netflow collector, some of SDA devices were not compatible with Stealthwatch. The reason was: “NBAR is enabled on this device“. In DNA center, NBAR and CBAR was actually disabled, but the problem stil persisted. CBAR and NBAR were previously enabled, but after disabling it, it did not clean all devices. Guess this is a “cleanup” bug in DNA center. Solution was to manually remove ip flow from affected devices.

DNA center version: 2.3.3.4

Screenshot of affected devices:

Solution: Clear ip flow from all interfaces on affected device, and resync device in DNA center.

Example:

conf t
int range gi1/0/1-48,Te1/1/1-4,Gi1/1/1-4
no ip flow monitor dnacmonitor input
no ip flow monitor dnacmonitor output
end
wr

Go to DNA center, Inventory -> Select device -> Actions -> Inventory -> Resync device

Wait couple of minutes, and you should be able to enable Stealthwatch for this device.

There is a Python tool called pyang that can read yang files. To install it on Linux machine:

apt install git python3-pip
pip install pyang

Now, git clone yang data model to your linux machine:

cd ~;git clone https://github.com/YangModels/yang.git

Pyang by itself is capable of reading yang and present it as a tree. To get xpath, we need to install additional plugin from here: https://github.com/NSO-developer/pyang-xpath
Find your pyang installation, and put the the xpath plugin to the plugin folder:

find /usr/local/lib -iname pyang
/usr/local/lib/python3.10/dist-packages/pyang

Download plugin:

wget -O /usr/local/lib/python3.10/dist-packages/pyang/plugins/xpath.py https://raw.githubusercontent.com/NSO-developer/pyang-xpath/master/xpath.py

Go to Yang model you cloned a few steps back (in this example, we’ll find xpath for Cisco IOS-XE cpu usage:

cd ~/yang/vendor/cisco/xe/1781/

Use xpath module on yang file to get xpath:

pyang -f xpath Cisco-IOS-XE-process-cpu-oper.yang 
>>> module: Cisco-IOS-XE-process-cpu-oper
/cpu-usage
/cpu-usage/cpu-utilization
/cpu-usage/cpu-utilization/five-seconds
/cpu-usage/cpu-utilization/five-seconds-intr
/cpu-usage/cpu-utilization/one-minute
/cpu-usage/cpu-utilization/five-minutes
/cpu-usage/cpu-utilization/cpu-usage-processes
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/pid
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/name
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/tty
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/total-run-time
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/invocation-count
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/avg-run-time
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/five-seconds
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/one-minute
/cpu-usage/cpu-utilization/cpu-usage-processes/cpu-usage-process/five-minutes

This are all xpaths, but we still need a prefix to construct a full path. It’s written at the start of the file:

grep prefix Cisco-IOS-XE-process-cpu-oper.yang
  prefix process-cpu-ios-xe-oper;

The whole xpath (level 1 depth) would look like this:

process-cpu-ios-xe-oper:cpu-usage/cpu-utilization

Depends on the depth and data needed, you can use this xpath with Cisco IOS-XE switch. Example:

telemetry ietf subscription 3305
 encoding encode-kvgpb
 filter xpath /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization
 source-address 10.10.1.1
 stream yang-push
 update-policy periodic 3000
 receiver ip address 10.20.20.250 57000 protocol grpc-tcp

References:
https://community.cisco.com/t5/service-providers-knowledge-base/how-to-derive-exr-telemetry-yang-path-using-pyang/ta-p/3713864
https://github.com/NSO-developer/pyang-xpath
https://github.com/jeremycohoe/cisco-ios-xe-mdt
https://www.youtube.com/watch?v=p94yetSTXdc
https://github.com/YangModels/yang

Looks like the latest MariaDB is not playing nice with Docker. It keeps on restarting, that’s why Firefly app can’t access it. This are the errors:

firefly_app-1 error:

getaddrinfo for db failed: Temporary failure in name resolution

firefly_db-1 error:

[Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:10.9.2+maria~ubu2204 started.
[ERROR] [Entrypoint]: mariadbd failed while attempting to check config
        command was: mariadbd --verbose --help --log-bin-index=/tmp/tmp.UIQ7MFsJkX
        Can't initialize timers

Fix: use older version of Mariadb, in my example, 10.8.2

My docker-compose file:

version: '3.3'

services:
  app:
    image: fireflyiii/core:latest
    restart: always
    volumes:
      - firefly_iii_upload:/var/www/html/storage/upload
    env_file: stack.env
    ports:
      - 8080:8080
    depends_on:
      - db
  db:
    image: mariadb:10.8.2
    hostname: fireflyiiidb
    restart: always
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
      - MYSQL_USER=firefly
      - MYSQL_PASSWORD=secret_firefly_password
      - MYSQL_DATABASE=firefly
    volumes:
      - firefly_iii_db:/var/lib/mysql
volumes:
   firefly_iii_upload:
   firefly_iii_db:

My notes on converting Cisco Catalyst 9105, 9115, 9xxx series access points to autonomous AP with embedded wireless controller.

Connect to your AP with console cable.

User: Cisco
Pass: Cisco
Enable: Cisco

Setup connectivity betweeen TFTP (in my case running on windows PC – tftpd64) server and AP.

TFTP server IP: 192.168.1.1/24
AP IP: 192.168.1.2/24

capwap ap ip 192.168.1.2 255.255.255.0 192.168.1.1

#version <= 8.9:

ap-type mobility-express ap-type ewc-ap tftp://192.168.1.1/ap1g7 tftp://192.168.1.1/C9800-AP-iosxe-wlc.bin

#version > 8.9:

ap-type ewc-ap tftp://192.168.1.1/ap1g7 tftp://192.168.1.1/C9800-AP-iosxe-wlc.bin

The conversion begins …

Would you like to enter the initial configuration dialog? [yes/no]: enter no

 The enable secret is a password used to protect
  access to privileged EXEC and configuration modes.
  This password, after entered, becomes encrypted in
  the configuration.
  -------------------------------------------------
  secret should be of minimum 10 characters with
  at least 1 upper case, 1 lower case, 1 digit and
  should not contain [cisco]
  -------------------------------------------------
  Enter enable secret: 

[0] Go to the IOS command prompt without saving this config.
[1] Return back to the setup without saving this config.
[2] Save this configuration to nvram and exit.

Select 0

conf t
hostname C9800

Create admin user – also used for web GUI:

user-name admin
priv 15
password test123

Set ap profile:

ap profile ap-default

Configure management user for access points:

mgmtuser username admin password 0 test123 secret 0 test123

Configure management IP address (you will access it via SSH or web GUI):

interface gigabitEthernet 0
ip address 192.168.1.2 255.255.255.0
no shut
ip default-gateway 192.168.1.1

Enable web server and save config:

ip http secure-server
wr

Access EWLC via https://192.168.1.2

All commands together after conversion is done:

WLCA49B.FFFF.BEEF#configure terminal
WLCA49B.FFFF.BEEF(config)#hostname C9800
C9800(config)#user-name admin
C9800(config-user-name)#priv 15
C9800(config-user-name)#password test123
C9800(config-user-name)#ap profile ap-default
C9800(config-ap-profile)#$mgmtuser username admin password 0 test123 secret 0 test123
C9800(config-ap-profile)#interface gigabitEthernet 0
C9800(config-if)#ip address 192.168.1.2 255.255.255.0
C9800(config-if)#no shut
C9800(config-if)#ip default-gateway 192.168.1.1
C9800(config)#ip http secure-server
C9800(config)#do wr
Building configuration...
[OK]
C9800(config)#

reference: https://www.youtube.com/watch?v=NBt370eiQ3I

There seems to be some bug in the newest Cisco 5G cellular gateway (CG522-E), shipped with 17.05 firmware. When you insert a SIM card, Linux cwand subsystem crashes and it keeps cycling, not detecting the SIM card:

Subsystem stopped: cwand
CellularGateway# pid 4342's current affinity list: 0-3
pid 4342's new affinity list: 0
pid 4344's current affinity list: 0-3
pid 4344's new affinity list: 0
pid 4345's current affinity list: 0-3
pid 4345's new affinity list: 0
pid 4346's current affinity list: 0-3
pid 4346's new affinity list: 0
pid 4348's current affinity list: 0-3
pid 4348's new affinity list: 0
pid 4349's current affinity list: 0-3
pid 4349's new affinity list: 0

System message at 2022-07-28 07:35:27...
Subsystem started: cwand

Guessing this has something to do with congestion windows parameter settings in the Linux subsystem, in combination with our SIM card (mobile network) specifications.

The only solution was to downgrade to 17.04 firmware. That fixed the issue for now.

Note: scroll to bottom of the post for the final solution.

When you try to login to TPlink switch from pfSense console you get the following error:

ssh admin@10.10.10.1
Unable to negotiate with 10.10.10.1 port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

Next you try to enable diffie-hellman group, another error pops up:

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 admin@10.10.10.1
Unable to negotiate with 10.10.10.1 port 22: no matching host key type found. Their offer: ssh-dss

Now you also include ssh-dss, but you still get an error:

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oHostKeyAlgorithms=+ssh-dss admin@10.10.10.1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the DSA key sent by the remote host is
SHA256:h1gD8T017XJ19NjY3wD9Vob81jHYUJubf2M23KLU7OU.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending RSA key in /root/.ssh/known_hosts:1
DSA host key for 10.10.10.1 has changed and you have requested strict checking.
Host key verification failed.

Now you disable strict host checking and you get the following error:

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oHostKeyAlgorithms=+ssh-dss -o StrictHostKeyChecking=no admin@10.10.10.1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the DSA key sent by the remote host is
SHA256:h1gD8T017XJ19NjY3wD9Vob81jHYUJubf2M23KLU7OU.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending RSA key in /root/.ssh/known_hosts:1
Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
Permission denied (publickey,password).

The final working solution, enable diffie and ssh-dss, disable strict host checking and redirect known hosts file to /dev/null:

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oHostKeyAlgorithms=+ssh-dss -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=yes admin@10.10.10.1

When deploying paperless-ng stack with docker-compose file in Portainer you can’t login to paperless admin because superuser for login is missing (not created). You need to create it by going into container webserver CLI console and create it. Check screenshots for details.

python3 manage.py createsuperuser

For reference, this is my docker-compose.yml file with some additional services (Tika and Gotenberg – used for parsing and converting Office documents):

version: "3.4"
services:
  broker:
    image: redis:6.0
    restart: unless-stopped

  db:
    image: postgres:13
    restart: unless-stopped
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: paperless
      POSTGRES_USER: paperless
      POSTGRES_PASSWORD: paperless

  webserver:
    image: jonaswinkler/paperless-ng:latest
    restart: unless-stopped
    depends_on:
      - db
      - broker
      - gotenberg
      - tika
    ports:
      - 8010:8000
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000"]
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - data:/usr/src/paperless/data
      - media:/usr/src/paperless/media
      - ./export:/usr/src/paperless/export
      - ./consume:/usr/src/paperless/consume
    environment:
      PAPERLESS_REDIS: redis://broker:6379
      PAPERLESS_DBHOST: db
      PAPERLESS_TIKA_ENABLED: 1
      PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
      PAPERLESS_TIKA_ENDPOINT: http://tika:9998
      PAPERLESS_TIME_ZONE: Europe/Ljubljana
      PAPERLESS_OCR_LANGUAGES: slv
      # consumption directory.
      USERMAP_UID: 1000
      USERMAP_GID: 100

  gotenberg:
    image: thecodingmachine/gotenberg
    restart: unless-stopped
    environment:
      DISABLE_GOOGLE_CHROME: 1

  tika:
    image: apache/tika
    restart: unless-stopped

volumes:
  data:
  media:
  pgdata:

This is for Windows 10. You need supported bluetooth dongle, refer to cisco documentation. In my tests, I used ASUS BT-400 USB dongle.

Pair your switch to your Windows computer. Default pairing PIN is 9999. Now follow the screenshot bellow:

After the connection is completed, you can SSH to the device via default IP 172.16.0.1.

Bluetooth commands references – in enable mode:

staging config bluetooth on (this will turn on the bluetooth - it's on by default)
staging config bluetooth PIN OLD_PIN NEW_PIN (change default pairing PIN)

Default bluetooth interface is Bluetooth0

For Cisco C9000 series, you need different configuration as described here: https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst9500/software/release/16-12/configuration_guide/int_hw/b_1612_int_and_hw_9500_cg/configuring_an_external_usb_bluetooth_dongle.pdf

Docker by default uses networks from 172.17.0.0/16 private range. This can sometimes conflicts with network you already have in your network environment. This will cause routing problems when clients from the same network subnets will try to access Docker services. In this case, Docker will route packets to containers instead back to clients.

To solve this, you need to define unused subnets and assign it to Docker. You can do this with daemon.json file.

Edit file (it if doesn’t exist, create it):

nano /etc/docker/daemon.json

Add this and edit to your needs:

{
  "bip": "172.17.192.1/26",
  "default-address-pools": [
    {
      "base": "172.17.192.64/28",
      "size": 29
    }
  ]
}

“bip”: “172.17.192.1/26” – This will be used for docker0 interface
“base”: “172.17.192.64/28” – This will be used for container bridges
“size”: 29 – Subnet prefix, means how large is going to be each bridge

Save file and restart docker:

service docker restart

In case you used docker-compose, first delete networks and containers with:

docker-compose down

In case you have more old bridges, list them with:

docker network ls

and delete with:

docker network rm network_name

or delete all networks with:

docker network prune

Alternatively, use a portion ob public network that you’re never going to use, for example:

{
  "bip": "100.100.100.1/26",
  "default-address-pools": [
    {
      "base": "100.100.100.64/28",
      "size": 29
    }
  ]
}

Or use host networking, this will bind container network directly to host. But you will lose container isolation with this method: https://docs.docker.com/network/host/

New unboxed Cisco ISR4331, command configure terminal didn’t work. Looks like the router is booted in controller mode by default. To get back to “legacy” mode you need to disable controller mode.

Router#conf t
This command is not supported
Router# controller-mode disable
Disabling controller mode will erase the nvram filesystem, remove all configuration files, and reload the box!
Ensure the BOOT variable points to a valid image
Continue? [confirm]
% Warning: Bootstrap config file needed for Day-0 boot is missing
Do you want to abort? (yes/[no]): no
 Mode change success

Wait a few minutes, router will reload.

Router>en
Router#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
Router(config)#

Whenever you update Cisco DNA center, backups stop working. You need to re-apply NFS configuration in DNA center GUI which will restart the docker container and enable backups again.

For example, delete one slash in the Server Path option, write it back and apply. Wait a few minutes for the Docker process to restart. Backups should work now.

I added an extra network card to my Proxmox server (Mellanox Connect-X3) and some VLANs were not working. It turned out Mellanox Connect-X3 supports only about 128 VLANS in memory. Proxmox by default adds VLANs from 2-4094. You can see it in /etc/network/interfaces, line bridge-vids 2-4094.

When you try to reload networking from console, you get this error:

root@proxmox:~# ifreload -a
error: enp1s0: failed to set vid `{2,...4094}` (cmd '/sbin/bridge vlan add vid 2-4094 dev enp1s0' 
failed: returned 255 (RTNETLINK answers: No space left on device))

To fix this, open /etc/network/interfaces and add only VLANs you need. For example:

Original:

auto vmbr1
iface vmbr1 inet manual
        bridge-ports enp1s0
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094

Fixed:

auto vmbr1
iface vmbr1 inet manual
        bridge-ports enp1s0
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 20,21,30,40,50,60,90,200,210,254,600,664-668

Restart networking:

ifreload -a

Assign VLANs to your VMs now, it should work.

EDIT: they fixed their official documentation

Official Cisco documentation about setting up NFS server for DNA center is here. The problem is, this is for Ubuntu, and Ubuntu has different names for group “nobody” than CentOS.

So if you get an error saying:

BACKUP.ndp:elasticsearch
FAILURE
Exception
Task error description:
Error during _process_backup(): Internal server error: {"error":{"root_cause":[{"type":"snapshot_creation_exception",
"reason":"[ndp:e522e20b-69e3-45b0-b20c-20138ba1444c.000/AGvhN1eCRH6CtE60mNl3KA] failed to create snapshot"}],"type":"
snapshot_creation_exception","reason":"[ndp:e522e20b-69e3-45b0-b20c-20138ba1444c.000/AGvhN1eCRH6CtE60mNl3KA] failed to
create snapshot","caused_by":{"type":"access_denied_exception","reason":"/var/data/es/snapshots/meta-AGvhN1eCRH6CtE60mNl3KA.dat"}},"status":500}

That means you have the wrong user and group set up on server NFS directory.

For Ubuntu:

chown nobody:nogroup /dir/to/nfs/share

For CentOS:

chown nfsnobody:nfsnobody /dir/to/nfs/share

Prerequisites:

– raspbian OS
– CA cert, client cert and cert password, client key

You can use .p12 file and convert it to .pem, it will include client cert and client key in the same file. Let’s say you download .p12 file from PfSense cert manager. Convert it with:

openssl pkcs12 -in test.p12 -out test.pem
Enter Import Password: leave empty
Enter PEM pass phrase: testing1234
Verifying - Enter PEM pass phrase: testing1234

First, delete openresolv and dhcpcd5 because it’s conflicting with native network management:

apt purge openresolv dhcpcd5

Disable wpa_supplicant:

systemctl disable wpa_supplicant

Install nmcli:

apt install network-manager

Comment out everything in /etc/network/interfaces and in /etc/wpa_supplicant/wpa_supplicant.conf and then Reboot Pi

Create wifi connection:

nmcli c add type wifi ifname wlan0 con-name "My-Wifi" \
      802-11-wireless.ssid "WIFI-SSID" \
      802-11-wireless-security.key-mgmt wpa-eap \
      802-1x.eap tls \
      802-1x.identity test \
      802-1x.ca-cert /home/pi/CA.crt \
      802-1x.client-cert /home/pi/test.pem \
      802-1x.private-key /home/pi/test.pem \
      802-1x.private-key-password testing1234

Depending on the network-manager version, the commands above might not work, so just enter it manually line by line:

nmcli con add type wifi ifname wlan0 con-name My-Wifi ssid WIFI-SSID
nmcli con edit id wifi
nmcli> set 802-11-wireless.ssid WIFI-SSID
nmcli> set 802-11-wireless-security.key-mgmt wpa-eap
nmcli> set 802-1x.eap tls
nmcli> set 802-1x.identity test
nmcli> set 802-1x.ca-cert /home/pi/CA.crt
nmcli> set 802-1x.client-cert /home/pi/test.pem
nmcli> set 802-1x.private-key-password testing1234
nmcli> set 802-1x.private-key /home/pi/test.pem
nmcli> save
nmcli> quit

Check connection with:

nmcli connection
NAME                UUID                                  TYPE      DEVICE
My-Wifi             f0c28a28-934f-4dbc-823f-b3c1653bb047  wifi      wlan0

Start connection:

nmcli connection up My-Wifi

If you want to start over, you can delete connection with:

nmcli connection delete My-Wifi

You can also view and edit profile at /etc/NetworkManager/system-connections/My-Wifi.nmconnection

cat /etc/NetworkManager/system-connections/My-Wifi.nmconnection
[connection]
id=My-Wifi
uuid=f0c28a28-934f-4dbc-823f-b3c1653bb047
type=wifi
interface-name=wlan0
permissions=

[wifi]
mac-address-blacklist=
mode=infrastructure
ssid=WIFI-SSID

[wifi-security]
key-mgmt=wpa-eap

[802-1x]
ca-cert=/home/pi/CA.crt
client-cert=/home/pi/test.pem
eap=tls;
identity=test
private-key=/home/pi/test.pem
private-key-password=testing1234

[ipv4]
dns-search=
method=auto

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto

We are going to install Cisco wireless virtual controller on Proxmox hypervisor and connect it to pfSense router.

Prerequisites:

  • pfSense router with required VLANS created and tagged to Proxmox (I will not cover how to setup VLANs on pfSense)
  • VLAN capable switch
  • Cisco access point
  • Proxmox hypervisor
  • vWLC iso file (you can get it from Cisco support site if you have a service contract, otherwise search the internet, hint: torrents (CTVM)). Check your access points models and see which vWLC supports your access points. In my case, I want to support some older APs so I installed version 8.3.150. I recommend you to install 8.5.x.

1. Create a new virtual machine in Proxmox
vWLC requires two network interfaces, one for management and one for out of band (OOB) service port. Management interface has to be a trunk (tagged) port (carrying multiple vlans). Service port has to be an access port only (untagged). Let’s say we will use VLAN 20 for management, VLAN 200 for service ports and VLAN 21 for wifi users. Before creating interfaces in vWLC virtual machine, make sure your Proxmox bridges are VLAN aware.

2. Create a new VM and add two interfaces.
First interface should be tagged with service-port VLAN, in  my case VLAN 200. The second interface should have no tag, that means it’s a trunk port (it can carry multiple VLANS).

3. Start up newly created VM with loaded vWLC ISO and begin installation
You will be asked to enter:

– service port interface IP (you can use DHCP or static, this is a tagged/access port interface, with VLAN 200 in my case)
– management interface IP (this is a trunk interface, but it will ask you for a vlan tag that will become native vlan for this interface … Tag it, in my case VLAN 20, it needs to be static IP address, set it to IP address scheme that reflects your VLAN, in my case VLAN 20)
– NTP server
– credentials

After installation is complete, you should be able to access vWLC webGUI via https://management_interface_IP_on_VLAN20

4. Access point provisioning, DHCP option 43
It will happen on management interface vlan, in my case VLAN 20. APs will need to know the IP of the vWLC controller, so we need to setup option 43 in our DHCP server that’s running on pfSense. Option 43 will tell access point the IP of the vWLC controller. You can help yourself with an option 43 generator (https://shimi.net/services/opt43/). More detailed guide from Cisco concerning option 43 is here: https://community.cisco.com/t5/wireless-mobility-documents/configuring-dhcp-option-43-and-option-60/ta-p/3143572


Optionally, you can also add option 60 (VCI – Vendor Class Identifier). You can get APs VCIs here: https://www.cisco.com/c/en/us/support/docs/wireless-mobility/wireless-lan-wlan/97066-dhcp-option-43-00.html#anc5

Go to pfSense -> Services -> DHCP Server -> VLAN20 -> Additional BOOTP/DHCP Options -> Display Advanced


Save and apply changes.

EDIT: option 43 should be type string, not text!

5. Switch settings
vWLC supports only Flexconnect mode, that means you need to setup your switch ports (where APs will be connected to it) as a trunk port and setup a native VLAN. For non Cisco terms: untagged + tagged ports. Native VLAN should be the same as management interface, in my case VLAN 20. Trunk should also carry VLAN 21 for wifi clients.

Example for cisco:

interface GigabitEthernet1/0/1
switchport trunk native vlan 20
switchport trunk allowed vlan 20,21
switchport mode trunk

Other vendors have tagging and untagging, so VLAN 20 untagged, VLAN 21 tagged.

6. Connect AP to configured switch port
Connect AP to the switch and wait a few minutes to join the controller. If AP doesn’t join, check logs on WLC controller: MANAGEMENT -> Logs -> Message logs

If you get: (5246) Regulatory Domain Mismatch

Means you have to change country code to match the AP (usually US):

Shutdown radios first:

WLC GUI -> Wireless -> 802.11a/n/ac -> Network -> 802.11a Network Status (untick Enabled and apply)
WLC GUI -> Wireless -> 802.11b/g/n -> Network -> 802.11a Network Status (untick Enabled and apply)

Change country:

WLC GUI -> WIRELESS -> Country -> Tick US and apply

Reenable radios now.

Sometimes AP still won’t join, especially old ones. If you connect AP to a console cable and watch a console, you might get someting like:

*Oct 7 18:44:58.000: %CAPWAP-5-DTLSREQSEND: DTLS connection request sent peer_ip: 192.168.20.16 peer_port: 5246
*Oct 7 18:44:58.477: %DTLS-5-ALERT: Received FATAL : Certificate unknown alert from 192.168.20.16
*Oct 7 18:44:58.477: %DTLS-5-SEND_ALERT: Send FATAL : Close notify Alert to 192.168.20.16:5246

This means the certs on AP are expired. You can disable this by SSH into vWLC controller and enter the following commands:

config ap cert-expiry-ignore mic enable
config ap cert-expiry-ignore ssc enable

7. Enable SSID broadcasting
vWLC supports only Flexconnect, so we need to enable it:

Go to WLC GUI -> WIRELESS -> Access Points -> All APs -> select AP from the list -> AP Mode -> FlexConnect and apply

8. Create wireless network
First you need to create VLAN interface for wifi clients.

Go to WLC GUI -> Controller -> Interfaces -> New -> Interface name: vlan21 -> VLAN Id: 21 -> Apply

Now create WLAN network

Go to WLC GUI -> WLANs -> Create new -> Enter Profile Name and SSID -> tick Status enabled and select Interface/Interface Group(G) vlan21 -> go to Security -> Layer 2 -> scroll down -> tick PSK Enable and create a wifi password -> Apply

9. Enable VLANs on AP
You need to setup native VLAN (in my case VLAN 20) on APs and add WLAN-VLAN mappings.

Go to WLC GUI -> WIRELESS -> Access Points -> All APs -> select AP from the list -> FlexConnect, tick VLAN support and enter native VLAN:

Next click on VLAN Mappings. Tick SSID under WLAN id, enter wifi clients VLAN under VLAN ID (in my case VLAN 21) and click Go at section Make AP specific.

10. You wifi clients should be able to connect now

11. 60 days trial license

There is a 60 days trial license, but you can enable RTU (right to use) license that will not expire (note: this is against cisco TOS).

Go to WLC GUI -> MANAGEMENT -> Software Activation -> Licenses -> license count: custom number -> Set Count -> Accept EULA and you are done.

12. Quick topology drawing

Adding CIFS storage from GUI fails with error message:

create storage failed: error during cfs-locked 'file-storage_cfg' operation: mount error: Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) (500)

We will add share via CLI, because you need to include smbversion 2.1:

pvesm add cifs <PROXMOX_NEW_VOLUME_NAME> --server <QNAP_IP> --share <SHARED_FOLDER_ON_QNAP> --username <QNAP_CIFS_SHARE_USERNAME> --password <QNAP_CIFS_SHARE_PASSWORD> --smbversion 2.1

Example:

pvesm add cifs QNAP --server 10.10.1.1 --share Proxmox --username proxmox --password proxmox.pass --smbversion 2.1

Share is now mounted.

Go to the GUI:

Datacenter -> Storage -> QNAP -> Edit -> Content -> Select the content you want and click OK.

Bitwarden_rs will not work on Chrome without SSL, so we are going to create a self signed certificate. If you are going to host Bitwarden on the internet (outside your local network), use certbot instead.

Prerequisites: working Docker installation on Linux

As sudo or root, make persistent data directories for SSL and Bitwarden files on the Docker host machine:

mkdir -p /docker_data/bitwarden/ssl
cd /docker_data/bitwarden/ssl

Generate certificate and a key.
You will be asked to enter cert data, enter whatever you wan’t, it doesn’t really matter since it’s self signed:

openssl req -x509 -newkey rsa:4096 -keyout bitwarden.key \
-out bitwarden.crt -days 720 -nodes

Start the container, wait until container starts and then go to https://yourdockerhost

docker run -d --restart always --name bitwarden -e \
ROCKET_TLS='{certs="/ssl/bitwarden.crt",key="/ssl/bitwarden.key"}' \
-v /docker_data/bitwarden/ssl/:/ssl/ -v \
/docker_data/bitwarden/:/data/ -p 443:80 bitwardenrs/server:latest

You can check container status with “docker ps”:

docker ps

Output:

Login to Bitwarden wegbui via self signed SSL now.

Tested on 3702 AP.

Hold mode button and turn on the power. Release the mode button when the LED lights amber. Connect the console cable from PC to AP and connect to it via Putty or any other client that supports serial connections.

If necessary delete some old files first to free some space:

ap: dir flash:
ap: delete flash:ap3g2-k9w7-mx.153-3.JPJ3a/ap3g2-k9w7-mx.153-3.JPJ3a
ap: you sure you want to delete "flash:ap3g2-k9w7-mx.153-3.JPJ3a/ap3g2-k9w7-mx.153-3.JPJ3a" (y/n)?y
File "flash:ap3g2-k9w7-mx.153-3.JPJ3a/ap3g2-k9w7-mx.153-3.JPJ3a" deleted
ap: delete flash:private-multiple-fs
ap: you sure you want to delete "flash:private-multiple-fs" (y/n)?y
File "flash:private-multiple-fs" deleted

On AP, configure temporary network settings, so you can upload new firmware over network later.

ap: set IP_ADDR 192.168.0.1
ap: set NETMASK 255.255.255.0
ap: set DEFAULT_ROUTER 192.168.0.1
ap: tftp_init
tftp_init success: You can now use tftp file system!
ap: ether_init
Ethernet speed is 1000 Mb - FULL duplex

Set up your TFTP server (usually laptop or a PC) network address to the same subnet as the access point’s in the step above. For this example, set the network card address to:

IP address: 192.168.0.2
Subnet mask: 255.255.255.0

For quick access to network cards settings on Windows, go to start and type ncpa.cpl, press enter.

Connect UTP cable from TFTP server to access point and start your TFTP server with loaded firmware. You can use TFTPD32 on Windows – Download.

Go back to AP console and fetch the firmware from TFTP server:

ap: tar -xtract tftp://192.168.0.2/ap3g2-k9w7-tar.153-3.JPJ3a.tar flash:
extracting info (283 bytes)
ap3g2-k9w7-mx.153-3.JPJ3a/ (directory) 0 (bytes)
extracting ap3g2-k9w7-mx.153-3.JPJ3a/ap3g2-k9w7-mx.153-3.JPJ3a (119277 bytes).........................
ap3g2-k9w7-mx.153-3.JPJ3a/html/ (directory) 0 (bytes)
ap3g2-k9w7-mx.153-3.JPJ3a/html/level/ (directory) 0 (bytes)
ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/ (directory) 0 (bytes)
extracting ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/appsui.js (563 bytes)
extracting ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/back.shtml (512 bytes)
extracting ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/cookies.js (5032 bytes).
extracting ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/forms.js (20442 bytes)....
extracting ap3g2-k9w7-mx.153-3.JPJ3a/html/level/1/sitewide.js (17250 bytes)...

Wait a few minutes for the process to finish and set AP to boot from new firmware:

ap: set BOOT flash:/ap3g2-k9w7-mx.153-3.JPJ3a/ap3g2-k9w7-mx.153-3.JPJ3a
ap: boot

NOTE: This is not the only way to do it. Here is another way without going into recovery – rommon mode.