Files
vps/docs/unifi-network.md

11 KiB

UniFi network configuration

Controller

Item Value
Host ubnt
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:

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.

Inter-VLAN reachability

The AP management networks are routed by gw, 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:

docker exec -it unifi-controller bash
mongo --port 27117
use ace
db.device.find(
  { type: "uap" },
  { name: 1, ip: 1, model: 1, inform_url: 1 }
).pretty()

IPv6 status (verified 2026-08-20)

IPv6 is enabled and live on the main Wi-Fi networks. Read-only verification, no changes made.

Controller (networkconf in the ace DB): the Default LAN network has ipv6_enabled: true, ipv6_client_address_assignment: slaac, ipv6_ra_enabled: true, ipv6_ra_priority: high, and dhcpdv6_allow_slaac: true. ipv6_interface_type: "none" is expected: the network's gateway is the third-party EdgeRouter (gw), so the controller does not manage WAN-side IPv6 — RA/SLAAC is served by the router.

All active SSIDs map to the Default network: ubnt-windy (5G), ubnt-windy-2 (2.4G), ubnt-haas (2.4G) — clients on them receive SLAAC IPv6.

Exception: the dormant ubnt-upg VLAN 10 network (and its ubnt-upg SSID) has no IPv6 configuration (default off). See Dedicated Wi-Fi through a third-party gateway.

APs (live): both managed APs hold global SLAAC addresses on br0 with a default route learned via RA from gw:

AP Global IPv6 on br0 (at check time) Default route
U6 Lite (192.168.66.6) 240e:3bd:235:1fb1:.../64 default via fe80::... dev br0 proto ra
UAP-AC-Lite (192.168.55.5) 240e:3bd:235:1fb2:.../64 default via fe80::... dev br0 proto ra

The delegated prefixes are dynamic ISP allocations (PPPoE PD /60) and rotate on redial; only the structure is stable.

Gateway (gw): the IPv6 routing table shows connected /64s on eth0 (LAN66) and switch0 (LAN55) plus ::/0 via pppoe0.

Re-verify:

ssh -4 -o BatchMode=yes zhiqiangf@192.168.66.6 'ip -6 addr show br0; ip -6 route show'
ssh -4 -o BatchMode=yes zhiqiangf@192.168.55.5 'ip -6 addr show br0; ip -6 route show'

2026-08-21 (W1N-207): SmartThings Element/vWire provisioning SSIDs (element-8a0d5133c9438f12, vwire-8b2d67469e455785, vport-F09FC22004E9) were removed (element_adopt setting disabled + element wlanconf deleted + device vwire fields cleared) and confirmed off on both APs (normal SSIDs unchanged: ubnt-windy, ubnt-windy-2, ubnt-haas, ubnt-upg). Root cause of Matter onboarding failure that day: HA's matter-server advertised a stale IPv6 GUA (two prefix generations old) in mDNS; fixed by restarting the add-on — see hosts/hass.windy.lan.md.

SSID ↔ subnet split (Matter-relevant): ubnt-windy (5G) is served only by the U6 Lite on LAN66; ubnt-haas / ubnt-windy-2 (2.4G) only by the UAP-AC-Lite on LAN55. mDNS is link-local multicast and does not cross the routed 55/66 boundary (no mDNS reflector). Matter commissioning therefore requires phone and device on the same subnet (LAN55); a phone on 5G (LAN66) cannot discover a LAN55 Matter device.

Cleanup side-effects (left as-is, harmless): after the direct-DB cleanup, db.device.cfgversion holds placeholder values (0000000000000000 / 1111111111111111) and UAP-AC-Lite has mesh_sta_vap_enabled=false; the controller has not reverted them and no functional impact was observed.

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

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:

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.

Key-only IPv4 SSH was verified for both managed APs using the zhiqiangf account on 2026-08-06 and re-verified 2026-08-20 (BatchMode with password and keyboard-interactive disabled; both APs still log in key-only). Verify future access without permitting password or keyboard-interactive fallback:

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:

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:

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:

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.