Linux
DIY Linux Router - Parte 5 - Wifi
This is the fifth part of this series, we will configure our wireless network using the Ubiquiti Unifi AP 6.
- Part 1: Initial Setup
- Part 2: Network and Internet
- Part 3: Users, Security and Firewall
- Part 4: Podman and Unbound
- Part 6: Nextcloud and Jellyfin
- Impermanence Storage
Já temos um roteador de internet funcional e confiável, mas ainda não configuramos nossa rede Wifi e este capítulo enderecerá isso.
Stephen Herber's old blogpost about DIY Linux as a router: Web archived link
Introduction
This Mac mini, like many machines, has a built-in wireless interface that could be used to create the intended wireless network. But, in most of cases, the card is not that reliable, and with a poor performance and low speed that does not worth using it. With this in mind, I choose touse a different approach. A proper Acess Point and this one provided by Unifi is reliable, cost-effective, and easy to use and setup.
Physical Connection
As mentioned in part 2 the Unifi AP needs to be connected to the Port 3 of the Switch, as this port was already configured the intended VLANs at this port.
Remember to install the PoE feeder to supply power for the AP. Check whether the LEDs lights up to confirm that everything is working.
┌─────► AP Unifi U6 Lite
│
┌───────────┴───────────────────────┐
| ┌───┬───┬───┬───┬───┬───┬───┬───┐ |
| │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ |
| └───┴───┴───┴───┴───┴───┴───┴───┘ |
└───────────┬───────────────────────┘
│
└─────► Untagged VLAN 1, Tagged VLAN 30, 90
Pod Setup
To manage this AP we need to install the Unifi Network Application. There's a Docker Image provided LinuxServer.io that fits this purpose. Let's then set a Pod with.
Run all the commands as podman
user:
ssh router-podman
1. Create the `unifi-secret.yaml` file
The Unifi Network Application uses a MongoDB Database to persist information, which demands setting up usernames and passwords. We could create a generic password as plain text, but this would be a security risk. It is better to use a complex password and store it securely. Podman offers a functionality of this which is the secrets repository
. I made a simple script that generates the intended passwords randomly and then creates the unifi-secret.yaml
file with it file for deployment.
cd /home/podman/deployments/
export MONGO_INITDB_PASSWORD="$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;)"
export MONGO_PASS="$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;)"
cat << EOF > unifi-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: unifi-secret
data:
mongoRootPassword: $(echo -n ${MONGO_INITDB_PASSWORD} | base64)
mongoPassword: $(echo -n ${MONGO_PASS} | base64)
EOF
echo "Secret file created with the name unifi-secret.yaml"
A file named unifi-secret.yaml
wil be created at the directory you are in. Deploy it on podman
:
podman kube play /home/podman/deployments/unifi-secret.yaml
If everything worked as intended. You had deployed a new secret into podman
. You can check it by:
podman secret list
ID NAME DRIVER CREATED UPDATED
8aca9476dd8846f979b3f9054 unifi-secret file 8 seconds ago 8 seconds ago
After deploying this secret, is a good practice to delete the secret.yaml
file. Be aware that by doing so, you will be unable to delete and recreate this secret using the same password previously created.
rm /home/podman/deployments/unifi-secret.yaml
3. Create the `unifi.yaml` pod file
As Podman being able to natively deploy Kubernetes deployment files, let's create a deployment file for Unifi Network Application.
/home/podman/deployments/unifi.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: unifi-initdb-mongo
data:
init-mongo.sh: |
#!/bin/bash
if which mongosh > /dev/null 2>&1; then
mongo_init_bin='mongosh'
else
mongo_init_bin='mongo'
fi
"${mongo_init_bin}" <<EOF
use ${MONGO_AUTHSOURCE}
db.auth("${MONGO_INITDB_ROOT_USERNAME}", "${MONGO_INITDB_ROOT_PASSWORD}")
db.createUser({
user: "${MONGO_USER}",
pwd: "${MONGO_PASS}",
roles: [
{ db: "${MONGO_DBNAME}", role: "dbOwner" },
{ db: "${MONGO_DBNAME}_stat", role: "dbOwner" }
]
})
EOF
---
apiVersion: v1
kind: Pod
metadata:
name: unifi
labels:
app: unifi
spec:
enableServiceLinks: false
restartPolicy: Always
containers:
# Application container
- name: application
image: lscr.io/linuxserver/unifi-network-application:8.5.6
resources:
limits:
memory: 1100Mi
ephemeral-storage: 100Mi
requests:
cpu: 1.0
memory: 600Mi
ephemeral-storage: 50Mi
volumeMounts:
- mountPath: /config
name: unifi-application-config-pvc
env:
- name: PGID
value: "1000"
- name: TZ
value: America/Sao_Paulo
- name: MONGO_USER
value: unifi
- name: MONGO_PASS
valueFrom:
secretKeyRef:
name: unifi-secret
key: mongoPassword
- name: MONGO_HOST
value: unifi-db
- name: MONGO_PORT
value: "27017"
- name: MONGO_DBNAME
value: unifi
- name: MONGO_AUTHSOURCE
value: admin
- name: MEM_LIMIT
value: "1024"
ports:
- containerPort: 3478
hostPort: 3478
protocol: UDP
- containerPort: 10001
hostPort: 10001
protocol: UDP
- containerPort: 8080
hostPort: 8080
protocol: TCP
- containerPort: 8443
hostPort: 8443
protocol: TCP
# MongoDB container
- name: db
image: docker.io/library/mongo:4.4
resources:
limits:
memory: 200Mi
ephemeral-storage: 100Mi
requests:
memory: 100Mi
ephemeral-storage: 200Mi
volumeMounts:
- mountPath: /docker-entrypoint-initdb.d
name: initdb-mongo-configmap
readOnly: true
- mountPath: /data/db
name: unifi-mongo-db-pvc
- mountPath: /data/configdb
name: unifi-mongo-configdb-pvc
env:
- name: MONGO_PASS
valueFrom:
secretKeyRef:
name: unifi-secret
key: mongoPassword
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: unifi-secret
key: mongoRootPassword
- name: MONGO_INITDB_ROOT_USERNAME
value: root
- name: MONGO_USER
value: unifi
- name: MONGO_DBNAME
value: unifi
- name: MONGO_AUTHSOURCE
value: admin
volumes:
- name: initdb-mongo-configmap
configMap:
name: unifi-initdb-mongo
- name: unifi-mongo-db-pvc
persistentVolumeClaim:
claimName: unifi-mongo-db
- name: unifi-mongo-configdb-pvc
persistentVolumeClaim:
claimName: unifi-mongo-configdb
- name: unifi-application-config-pvc
persistentVolumeClaim:
claimName: unifi-application-config
4. Start Pod and Enable its Systemd Unit
Start the pod and check if its working properly.
podman --log-level info kube play --replace /home/podman/deployments/unifi.yaml
Enable its systemd
unit.
systemctl --user enable --now [email protected]
5. Add an A entry to Unbound
To allow the AP to be adopted, it needs to reach the Unifi Network Painel by concatcting a host named unifi. Let's add an A entry to Unbound configuration
/mnt/zdata/containers/podman/storage/volumes/unbound-conf/_data/local.conf
server:
private-domain: "home.example.com."
local-zone: "home.example.com." static
local-data: "macmini.home.example.com. IN A 10.1.78.1"
local-data: "macmini.home.example.com. IN A 10.30.17.1"
local-data: "macmini.home.example.com. IN A 10.90.85.1"
local-data: "unifi.home.example.com. IN A 10.1.78.1"
local-data: "unifi. IN A 10.1.78.1"
Firewall
To make Unifi Network available to the network, it's necessary to open firwall ports. As all the ports are above the 1024
, it's just a matter of opening them. The ports are:
- 3478/UDP - Unifi STUN port.
- 10001/UDP - Unifi Discovery port.
- 8080/TCP - HTTP port for communication between Unifi devices.
- 8443/TCP - HTTPS Web port. Will keep it open temporarely.
Edit `nftables.nft`
Edit the file nftables.nft
as described. You have to switch from user podman
to user admin
and do the firewall changes with sudo
:
/etc/nixos/modules/nftables.nft
table inet filter {
...
chain unifi_network_input {
iifname "br0" udp dport 3478 ct state {new, established } counter accept comment "Unifi STUN"
iifname "br0" udp dport 10001 ct state {new, established } counter accept comment "Unifi Discovery"
iifname "br0" tcp dport 8080 ct state {new, established } counter accept comment "Unifi Communication"
iifname "br0" tcp dport 8443 ct state {new, established } counter accept comment "Unifi Webmanager"
}
chain input {
...
jump unbound_dns_input
jump unifi_network_input
# Allow returning traffic from ppp0 and drop everything else
iifname "ppp0" ct state { established, related } counter accept
iifname "ppp0" drop
}
...
}
Rebuild NixOS
nixos-rebuild switch
Configuration
- Access the Unifi Network Application on Web browser at 10.1.78.1:8443. This will placed under a NGINX proxy afterwards.
- Define your
Server Name
and yourCountry
. - Configure your username and password. You can create an account on account.ui.com or create an account locally.
Device Adoption
The Unifi Network needs to adopt your Unifi AP. Since the application is running on Podman under an IP Address which is not accessible by other devices. So far, everything what we did would allow new devices to be automatically adoptable by the application, but if not, try as described below:
Change the Inform IP Address. This is done by going to Settings > System > Advanced and setting the Inform Host to a hostname, in that case, macmini
or the IP address 10.1.78.1
. Additionally the checkbox "Override" has to be checked, so that devices can connect to the controller during adoption. More detailed information at the LinuxServer.io documentation.
Troubleshooting Adoption Problems
You you are having trouble with automatic adoption, you can double check if the settings are correct to made it work as intended:
- Ports
8080/tcp
and3478/udp
being open and accessible. - Changed the inform host mentioned above.
Manual Adotion
If all the adjustaments did not made your Unifi device being adopted, maybe your device was adopted by other painel and needs to be manually adopted. You can do this by doing the following:
ssh ubnt@$AP-IP
set-inform http://10.1.78.1:8080/inform
Check the IP address of AP by looking at the DHCP server
file at /var/lib/kea/dhcp4.leases
.
The default username and password is ubnt
. If the device was previously adopted, check on their previous panel what is the username
and password
set under Settings > System > Advanced. Generally, the username
and password
are the Unifi account's one. It's valuable to mention that every time you want to replace your Ubiquiti Network Application, is a good measure to remove your devices before decommissioning that panel. Making backups for your configuration is also a good measure to prevent headaches re-adopting devices—more details on LinuxServer.io documentation.
Conclusion
If you have this far, you successfully configured the main functionalities of your Linux Router and can use it as your main internet connection for your home. At the next chapter we will configure other services as Jellyfin, a private streaming service and Nextcloud, a private cloud solution.
- Part 6: Nextcloud and Jellyfin
keywords: macmini • roteador • linux • nixos • ubuquiti • unifi • podman • docker