# UniFi network configuration ## Controller | Item | Value | |---|---| | Host | [ubnt](../hosts/ubnt.md) | | Address | `192.168.66.46` | | Deployment | Docker, `jacobalberty/unifi:v9.5.21`, host networking | | Inform endpoint | `http://192.168.66.46:9080/inform` | | MongoDB database / port | `ace` / `27117` | Although `8080` is a common UniFi inform port, this controller uses `9080`. All AP adoption and recovery procedures must use the endpoint above. ## Login and MFA On 2026-08-08, **"Sync Local Admin with Ubiquiti SSO"** was disabled (`super_sdn.sso_login_enabled: false`). Previously every login was forced through Ubiquiti SSO (sso.ui.com) and required MFA, which blocked programmatic access: the `unifi-network-mcp` write operations failed with `api.err.Ubic2faTokenRequired`. Now local accounts (`windy`, `zhiqiangf`) sign in with their local passwords and no MFA. The `unifi-network-mcp` tool uses the `zhiqiangf` local account and works for both read and write operations (verified 2026-08-08 with a reversible client rename). Impact: unifi.ui.com remote access (Site Manager) no longer works. Manage the setting idempotently via Ansible: ```bash cd ansible ansible-playbook playbooks/unifi-sso.yml --limit unifi --check # read-only ansible-playbook playbooks/unifi-sso.yml --limit unifi \ -e '{"unifi_sso_confirm": true, "unifi_sso_target_value": false}' # apply ``` See [runbooks/ansible-operations.md](../runbooks/ansible-operations.md). ## Inter-VLAN reachability The AP management networks are routed by [gw](../hosts/gw.md), `192.168.66.254`. On 2026-08-05, a probe sourced from the LAN55 gateway (`192.168.55.254`) reached the controller (`192.168.66.46`) with 3/3 ICMP replies. The UAP-AC-Lite is online through the `:9080/inform` endpoint, which also confirms the required application path in practice. `LAN_IN` contains explicit allow rules for `192.168.55.0/24 ↔ 192.168.66.0/24`, but the firewall set is currently inactive (not attached to an interface). Treat the networks as bidirectionally reachable by default; do not rely on those inactive rules as an access boundary. Recheck this after attaching any LAN firewall policy or changing VLAN routing. To inspect device records from the controller host: ```bash docker exec -it unifi-controller bash mongo --port 27117 ``` ```javascript use ace db.device.find( { type: "uap" }, { name: 1, ip: 1, model: 1, inform_url: 1 } ).pretty() ``` ## Dedicated Wi-Fi through a third-party gateway ### Architecture boundary discovered on 2026-08-08 `gfw` is a virtual machine connected only to the native LAN 66 network; the physical Wi-Fi uplink is also an ER-X LAN 66 path. The ER-X provides DHCP for that LAN. There is no verified 802.1Q-capable path from the U6 Lite to `gfw`. Consequently, the proposed `ubnt-upg` design is **not implementable on the current topology without an additional VLAN-capable L2 path**. Giving the VM an `eth0.10` interface alone does not create VLAN 10 on the physical switch or deliver tagged frames to it. UniFi APs associate clients and bridge an SSID into a selected 802.1Q VLAN; they do not allocate DHCP addresses. The controller configures that AP behavior, but it is not a DHCP service for a third-party-gateway VLAN. The gateway on the corresponding VLAN provides DHCP. In the existing topology, the ER-X DHCP service legitimately answers untagged LAN 66 requests. The observed `192.168.66.91` lease on `ubnt-upg` is therefore expected when traffic reaches the existing untagged LAN 66. It is not a failure that can be fixed by changing the controller or by adding another DHCP server to the same broadcast domain. ### Conditions for a future implementation The design becomes viable only after adding and proving one of these: 1. A VLAN-capable switch/trunk from the U6 Lite to a VLAN-10 interface on the actual gateway, with native LAN 66 retained for AP management; or 2. A hypervisor/vSwitch and physical uplink configured to pass VLAN 10 end to end to the `gfw` VM, plus the corresponding tagged port towards the U6. Then configure one UniFi virtual network with **Router: Third-party Gateway** and VLAN ID `10`, map only `ubnt-upg` to it, and have the VLAN 10 gateway be the sole DHCP server for `192.168.10.0/24`. A test client must obtain `192.168.10.x`, with traffic and its lease visible on that gateway, before the SSID is considered working. ### Protecting existing Wi-Fi `ubnt-windy` is the existing 5 GHz SSID and has been restored on the U6 Lite. Keep its network and broadcast/device assignment unchanged. If the dedicated SSID is ever retried, use the controller's normal **Specific -> U6 Lite** broadcast selection for `ubnt-upg` only; do not reuse, move, or manually edit an existing SSID's AP group. An AP configuration push can still briefly reassociate clients, so zero-impact work on the same AP cannot be guaranteed. ### References - [Feasibility and DHCP responsibility](unifi-third-party-vlan10-dhcp.md) - [Supported topology and implementation examples](unifi-openwrt-vlan10-implementation-examples.md) - Ubiquiti: [Creating Virtual Networks (VLANs)](https://help.ui.com/hc/en-us/articles/9761080275607-Creating-Virtual-Networks-VLANs), [Creating WiFi SSIDs](https://help.ui.com/hc/en-us/articles/26136823938583-Creating-UniFi-WiFi-SSIDs), and [Switch Port VLAN Assignment](https://help.ui.com/hc/en-us/articles/26136855808919-Switch-Port-VLAN-Assignment-Trunk-Access-Ports). ## Managed access points | Name | Model | Management IP | Firmware | Management network | Inform port | |---|---|---|---|---|---| | U6 Lite | U6 Lite (`UAL6`) | `192.168.66.6` | `6.7.54.15663` | LAN66 (`192.168.66.0/24`, gateway `192.168.66.254`) | `9080` | | UAP-AC-Lite | `U7LT` | `192.168.55.5` | `6.8.2.15592` | LAN55 (`192.168.55.0/24`, gateway `192.168.55.254`) | `9080` | AP MAC addresses are recorded only where operationally needed: U6 Lite `78:45:58:4d:cc:30`; UAP-AC-Lite `f0:9f:c2:20:04:e9`. ## SSH administration Adopted APs use the SSH account configured in the controller, rather than the factory `ubnt/ubnt` credential. The password is stored in the password manager and must not be added to this repository. In UniFi Network `9.5.21`, configure it at: ```text Devices → Device Updates and Settings → Device SSH Settings → Device SSH Authentication ``` Use `ssh zhiqiangf@AP_IP` for the adopted-device account. Do not query or copy the controller's `mgmt` database setting into logs or documentation: it can contain the managed SSH password. On 2026-08-06, key-only IPv4 SSH was verified for both managed APs using the `zhiqiangf` account. Verify future access without permitting password or keyboard-interactive fallback: ```bash ssh -4 -o BatchMode=yes -o PasswordAuthentication=no \ -o KbdInteractiveAuthentication=no -o StrictHostKeyChecking=yes \ zhiqiangf@192.168.66.6 'mca-cli-op info' ssh -4 -o BatchMode=yes -o PasswordAuthentication=no \ -o KbdInteractiveAuthentication=no -o StrictHostKeyChecking=yes \ zhiqiangf@192.168.55.5 'mca-cli-op info' ``` Both devices reported `Connected` to `http://192.168.66.46:9080/inform` during that verification. The AP shell maps this management account to UID 0, so treat it as administrative access. ## Offline AP recovery An AP can be reachable via ICMP and SSH but offline in the controller when its saved inform URL still points to port `8080`. This occurred for UAP-AC-Lite after its inform configuration had diverged from the controller endpoint. From the AP, inspect the active endpoint and test controller reachability: ```bash info nc 192.168.66.46 9080 ``` The AP's BusyBox `nc` may not support `-zv`; use the plain `nc` invocation above when testing the TCP path. If `info` reports `http://192.168.66.46:8080/inform` (or another obsolete endpoint), correct it. UniFi devices commonly require the command twice while adoption is completed: ```bash set-inform http://192.168.66.46:9080/inform set-inform http://192.168.66.46:9080/inform ``` Verify that the AP changes to connected/online in the controller. ## Controller migration check After a controller migration or restore, inspect stored device records for a stale default-port endpoint before treating an AP as faulty: ```javascript use ace db.device.find( { inform_url: /8080/ }, { name: 1, ip: 1, inform_url: 1 } ) ``` Do not include credentials or controller database dumps in incident notes.