UniFi Controller – self-hosted – from scratch

UniFi Local Controller – complete control over your network

UniFi is one of those solutions that quickly gains the trust of network administrators—especially where data control, security, and ease of management are important. The key advantage of this ecosystem is the ability to run the controller locally, within your own infrastructure, without sending network information to external clouds or foreign servers. This allows us to retain full sovereignty over the configuration, traffic, and logs of our network, which is of great importance, especially in corporate and infrastructure environments.

The material shows a practical way to run UniFi on a Debian server using Docker and Docker Compose. The controller is based on the MongoDB database, and the entire configuration has been reduced to a readable docker-compose.yml file, which allows you to quickly set up, recreate, or move the environment to another location. Thanks to this, even a server failure does not mean the loss of the network – all you need is a backup and a few minutes to get everything back up and running.

A lot of attention has been paid to ports and security. It turns out that for the infrastructure to work properly, you don't need to expose "everything to the world" – in practice, only two key ports are needed: one for managing the administration panel and the other for communication between devices and the controller. The rest are optional features that should only be enabled when they are really needed.

A very interesting feature is the way devices are adopted. UniFi access points can automatically find the controller on the same network, they can also be added manually via SSH, and the most elegant solution is to use local DNS. All you need is for the router to resolve the name unifi to the IP address of the controller – then every new device connected to the power supply will report itself for adoption, without clicking, applications, or manual configuration.

After adding the first access point, a Wi-Fi network is created, which automatically broadcasts to all subsequent devices. UniFi shows the full network topology, connected clients, bandwidth usage, and allows you to manage each element from a single panel. Importantly, you can even access the device console from the controller and perform diagnostic operations on them, which shows how much power the administrator has over the infrastructure.

Finally, backups – one of the most important elements of the entire system. UniFi can perform automatic backups of configurations, statistics, and databases, and all key files are located in clearly defined directories. This makes it easy to secure them with an additional backup and ensure that in the event of a failure, the network can be quickly restored in another location.

All this makes UniFi a solution that combines simplicity, high functionality, and real control over data security—without compromises and without handing over key infrastructure to third parties.

Project GitHub Link  https://github.com/linuxserver/docker-unifi-network-application

Plik konfiguracyjny docker compose

docker-compose.yaml:

				
					---
services:

  unifi-db:
    image: mongo:${MONGO_TAG_VERSION}
    container_name: unifi-db
    env_file: .env
    volumes:
      - ./mongodb:/data/db
      - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh:ro
    restart: unless-stopped

  unifi-network-application:
    image: linuxserver/unifi-network-application:${UNIFI_TAG_VERSION}
    container_name: unifi-app
    env_file: .env
    volumes:
      - ./config:/config
    ports:
      - 8443:8443
      - 3478:3478/udp
      - 10001:10001/udp
      - 8080:8080
      - 1900:1900/udp #optional
      - 8843:8843 #optional
      - 8880:8880 #optional
      - 6789:6789 #optional
      - 5514:5514/udp #optional
    restart: unless-stopped 

				
			

Plik ze zmiennymi (koniecznie dostosuj hasła) .env

				
					PGID=1000
TZ=Etc/UTC
MONGO_USER=unifi
MONGO_PASS=unifi-pass
MONGO_HOST=unifi-db
MONGO_PORT=27017
MONGO_DBNAME=unifi
MONGO_AUTHSOURCE=admin
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=root-pass
MEM_LIMIT=1024
MEM_STARTUP=1024
MONGO_TLS=24 #optional
MONGO_TLS= #optional
MONGO_TAG_VERSION=8.0-noble
UNIFI_TAG_VERSION=10.0.162-ls111 

				
			

Skrypt inicjujący bazę danych MongoDB dla aplikacji

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" },
    { db: "${MONGO_DBNAME}_audit", role: "dbOwner" }
  ]
})
EOF 

				
			

Skrypt inicjujący bazę danych MongoDB dla aplikacji

init-mongo.sh

				
					arp -a | grep 6a:ec:48 
				
			

Logowanie do urządzenia

				
					ssh ubnt@$AP-IP
pass: ubnt 

				
			

Przekierwoanie urządzenia dl naszego kontrolera

				
					set-inform http://$address:8080/inform 
				
			

Resetowanie urządzenia z CLI

				
					syswrapper.sh restore-default 
				
			

Struktura katalogów

unifi/

├─┬─ config – application

│ ├─┬ data – unifi data 

│ │ └─┬ backup

│ │   └─ autobackup – unify backup

│ └── logs – unifi logs

├── mongodb – database folder

├── .env – variables of the entire installation

├── docker-compose.yaml – ddocker compose configuration

└── init-mongo.sh – mongodb initial script