UniFi Network Application with Docker Compose

The UniFi Network Application is the software controller for Ubiquiti access points, switches, and gateways. Running it self-hosted (instead of UniFi Cloud) keeps all network data local and removes the account dependency for AP management.

Compose

The linuxserver image requires a separate MongoDB container:

services:
  unifi-network-application:
    image: lscr.io/linuxserver/unifi-network-application:latest
    container_name: unifi-network-application
    restart: unless-stopped
    depends_on:
      - unifi-db
    ports:
      - '8443:8443' # Web UI (HTTPS)
      - '8080:8080' # AP inform/adoption (must be reachable by APs)
      - '3478:3478/udp' # STUN
      - '10001:10001/udp' # AP discovery (optional)
    volumes:
      - ./config:/config
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - MONGO_USER=unifi
      - MONGO_PASS=<your_mongo_password>
      - MONGO_HOST=unifi-db
      - MONGO_PORT=27017
      - MONGO_DBNAME=unifi

  unifi-db:
    image: mongo:7
    container_name: unifi-db
    restart: unless-stopped
    volumes:
      - ./mongodb:/data/db
      - ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=<your_root_password>

MongoDB init script

Create init-mongo.js alongside the compose file. MongoDB runs it once on first start to create the UniFi database user:

db.getSiblingDB('unifi').createUser({
  user: 'unifi',
  pwd: '<your_mongo_password>', // must match MONGO_PASS above
  roles: [{ role: 'dbOwner', db: 'unifi' }],
});
db.getSiblingDB('unifi_stat').createUser({
  user: 'unifi',
  pwd: '<your_mongo_password>',
  roles: [{ role: 'dbOwner', db: 'unifi_stat' }],
});

First run

docker compose up -d

Access the UI at https://<HOST>:8443 (self-signed cert on first access — accept the warning). Complete the setup wizard. Do not create a Ubiquiti account if you want fully local operation — choose “Advanced Setup” to skip cloud login.

Adopting access points

APs must reach the controller on port 8080. When adopting an unconfigured AP:

  1. The AP should appear under Devices if it’s on the same subnet
  2. If it doesn’t auto-discover, SSH into the AP and run:
    set-inform http://<CONTROLLER_IP>:8080/inform
  3. Click Adopt in the UI

Network architecture

UniFi manages WiFi configuration — SSIDs, radio settings, VLAN tagging on wireless networks. The router (OPNsense, pfSense, etc.) handles DHCP, firewall rules, and VLANs on the wired side.

Key gotcha: switch trunk ports must carry tagged VLAN traffic to AP ports before adding VLAN-tagged SSIDs in UniFi. If the switch port only passes untagged traffic, clients on VLAN SSIDs will associate but won’t get an IP.

In UniFi, each WiFi network maps to a Network object with a VLAN ID. Leave DHCP off in the UniFi network object — let your router handle it.

Ports

PortProtocolPurpose
8443TCPWeb UI (HTTPS)
8080TCPAP inform — APs call home on this port
3478UDPSTUN
10001UDPAP discovery (L2, same subnet only)

Port 8080 must be reachable from all managed APs. If APs are on a different VLAN than the controller, ensure your firewall allows this.

Running in a Proxmox LXC

UniFi runs well as Docker Compose inside a Debian LXC. The main constraint is networking: AP discovery (10001/udp) is L2 broadcast — it only works if the LXC’s network interface is bridged directly onto the same subnet as your APs, not behind NAT.

LXC requirements

The LXC must be privileged (or have nesting=1 + keyctl=1 features set for unprivileged Docker):

# /etc/pve/lxc/<VMID>.conf
features: keyctl=1,nesting=1

Or create as privileged from the start — simpler for a network management service that doesn’t handle untrusted input.

Network interface

Set the LXC’s network interface to bridge directly onto your AP VLAN (or main LAN if APs are untagged). In Proxmox, this means the LXC’s net0 should use the same bridge (vmbr0 or a tagged sub-interface) that your APs sit on.

If APs are on a separate VLAN, AP discovery won’t cross the L3 boundary — use set-inform to manually point APs at the controller instead of relying on auto-discovery:

# SSH into the AP
set-inform http://<CONTROLLER_IP>:8080/inform

Port 8080 firewall rule

If your controller LXC is on a management VLAN and APs are on an IoT or WiFi VLAN, add a firewall rule allowing TCP 8080 from the AP subnet to the controller IP. APs must reach this port to check in — without it, adopted APs will show as disconnected after a reboot.

Backup

Settings → System → Backup → Download backup (.unf file). Schedule auto-backups to a local path or network share. Restore: Settings → System → Backup → Restore.

Volumes

PathContents
./configUniFi application data, site configs, provisioning state
./mongodbMongoDB data directory

Back up both. Losing ./config means re-adopting all devices. Losing ./mongodb corrupts the database.