Setting up UniFi controller with Docker and Caddy

Last update: 2022-06-27

If you are having trouble finding a UniFi controller key or hardware, or simply want to use different hardware to manage your UniFi access points, you can use a Docker image. This tutorial also explains how to use Caddy if you want to host the controller on a public IP with a valid TLS certificate.

Installing Docker and Docker Compose ​

Google it; there are many tutorials online. The official links at the time of writing are:

Creating docker-compose.yml ​

We will use the image https://hub.docker.com/r/linuxserver/unifi-controller

I suggest creating a new folder so that all related files are kept together.

Make sure to use root/sudo for all commands

bash
useradd -r unifi
id unifi
# Take a note of the ids shown up, below an example
# uid=1000(unifi) gid=1000(unifi) groups=1000(unifi)
cd /home/unifi

Create a file called docker-compose.yml.

yml
# Create this file at /home/unifi/docker-compose.yml
# Check all options at the official repository:
# https://hub.docker.com/r/linuxserver/unifi-controller
version: "2.1"
services:
  unifi-controller:
    image: lscr.io/linuxserver/unifi-controller:latest
    container_name: unifi-controller
    environment:
      - PUID=1000 # Replace here the User ID from id Command
      - PGID=1000 # Replace here the Group ID from id Command
      - MEM_LIMIT=1024 #optional
      - MEM_STARTUP=1024 #optional
    volumes:
      # Persist all the configs at the folder below
      - ./config:/config
    ports:
      # If you are not using Caddy, use the ports below
      #- 8443:8443
      #- 8080:8080
      #- 3478:3478/udp
      #- 10001:10001/udp

      # If you are using Caddy, use the ports below
      - 7443:8443
      - 7080:8080
      #- 3478:3478/udp
      #- 10001:10001/udp

      # These ports are optional; check the repository for more details
      #- 1900:1900/udp #optional
      #- 8843:8843 #optional
      #- 8880:8880 #optional
      #- 6789:6789 #optional
      #- 5514:5514/udp #optional
    restart: unless-stopped

Starting up ​

Start the container and check the results:

bash
docker-compose up -d

You should be able to see the new container when running docker ps -a.

Configuring Caddy ​

You don't need to install Caddy if you are running within your local network. The automatic TLS will not work unless you have a public IP and your ports 80 and 443 are open so LetsEncrypt can verify your domain. Skip this step if you don't have a public IP/DNS set up.

Check how to install Caddy at their official docs https://caddyserver.com/docs/install.

After installation, configure /etc/caddy/Caddyfile (the default location for most distributions).

conf
# This configuration assumes that you have set up a DNS A record pointing to your server
# Replace the domain below
yourDomain.com:8443 {
    # Note the port 8443 is the port exposed and 7443 is the internal port, used at the docker-compose.yml
    reverse_proxy 127.0.0.1:7443 {
        transport http {
            tls
            tls_insecure_skip_verify
        }
    }
}

For a Debian-based system, reload the Caddy configuration using service caddy restart.

Linking your UniFi APs to the controller ​

Time to access https://yourDomain.com:8443.

If you are not using Caddy you will see a browser security error page, just continue since you do not have a certificate configured.

On your first visit, UniFi will ask you to enter your network details and create users. Finish those steps, then click the AP list icon in the left-side menu. It looks like a UniFi router.

For each AP, log in with the default username and password, ubnt:

bash
ssh ubnt@192.168.0.5 # Considering 192.168.0.5 is your AP IP
# Then point your AP to your controller
# Note the port here might be 8080 or 7080
set-inform http://yourDomain.com:7080/inform

Security notes ​

If you are exposing the UniFi controller to the internet, configure a firewall that allows only your network's APs to communicate with it. Otherwise, rogue APs or malicious users can abuse the open UniFi ports.