Gonzalo
Gonzalo I'm Gonzalo, a young DevOps engineer. In my spare time, I like to have some fun with my home server which allows me to learn new concepts about Linux and microservices.

Setting up a remote Unifi Controller with Traefik — manage your APs over the internet

Setting up a remote Unifi Controller with Traefik — manage your APs over the internet

In this post, I will explain how to configure a Unifi Network Application on a docker container to control a Unifi AP based on a remote location.

Requirements

  • Docker and Traefik installed on your server
  • Public Domain name
  • Port 80 & 443 forwarded from your router to your server

Setup Unifi Controller with Docker

Unifi controller runs on a docker container, supported by a Mongo database to store the data. Let’s create a new directory to save our docker-compose file and its configurations.

mkdir unifi
vim docker-compose.yaml

docker-compose.yaml

services:
  unifi-network-application:
    image: lscr.io/linuxserver/unifi-network-application:latest
    container_name: unifi-network-application
    privileged: false
    security_opt:
      - no-new-privileges:true
    depends_on:
      unifi-db:
        condition: service_started
        required: true
    networks:
      - traefik-public
      - default
    env_file: .env
    environment:
      - MONGO_HOST=unifi-db
      - MONGO_PORT=27017
      - MONGO_DBNAME=unifi-db
      - MEM_LIMIT=1024 #optional
      - MEM_STARTUP=1024 #optional
    volumes:
      - ./<controller_data_dir>:/config
    ports:
      - 8443:8443
      - 3478:3478/udp
      - 10001:10001/udp
      - 8080:8080
    restart: unless-stopped
  unifi-db:
    image: docker.io/mongo:7.0
    container_name: unifi-db
    env_file: .env
    volumes:
      - ./<mongo_data_dir>:/data/db
      - ./<mongo_data_dir>/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
    restart: unless-stopped

networks:
  traefik-public:
    external: true

Then, we need to create our .env file and define some variables:

PUID=1000
PGID=1000
TZ=<your_timezone_here>
MONGO_USER=<put_random_user_here>
MONGO_PASS=<put_random_password_here>

Our Unifi controller and database are ready, let’s start and set them up:

docker-compose up -d

Access to the controller by typing https://server_ip:8443 in your browser and create your Unifi controller user. Once everything is set up, you will see the login page:

Enabling dashboard

This example includes traefik dashboard configuration, a UI that shows the status of our traefik resources as routers, services, middlewares, and so on. There are several ways to configure the dashboard, I chose to redirect port 8080 and create a traefik router (via labels) that provides its dashboard when accessing http://HOST_LOCAL_IP:8080/dashboard/

walking

Now your Unifi controller is up & running on your local network. Let’s configure Traefik to manage requests from the remote Access Point.

Unifi Access Point configuration

The Unifi controller handles device management and adoption via the 8080 port. We will configure the AP to send requests to unifi.mydomain.com by connecting to the AP via SSH and running the following command:

set-inform http://unifi.mydomain.com/inform

The AP now knows how to talk with our remote Unifi controller. Now, let’s configure our custom host on the controller and establish the appropriate routing via traefik.

Override inform host on the controller

Sign in to the unifi network application as previously and go to Settings > System > Advanced > Inform Host and override with unifi.mydomain.com

walking

Configure Traefik routing

The Traefik container retrieves its configuration from the static and dynamic config files (as shown in the documentation). This final step consists of routing the requests from unifi.mydomain.com to the unifi controller container and 8080 port. To achieve this, three new resources need to be defined: an entrypoint, a router and a service.

Entrypoint — static config

The entrypoint is going to be defined on the Traefik static configuration file.

entryPoints:
  web:
    address: :80

The entrypoint listens to the incoming trafic from port 80. It is important to listen on http (not https) due to unifi AP inform request does not support TLS encryption. This means that routing the requests over 443 port would not work.

HTTP router & service — dynamic config

The http router handles POST requests to the configured url on the AP (unifi.mydomain.com/inform) and redirects them to the unifi controller container and the 8080 port. This is defined on the dynamic configuration file:

traefik.yml

http:
  routers:
    Unifi:
      rule: Host(`unifi.mydomain.com`) && Path(`/inform`) && Method(`POST`)
      entrypoints:
      - web
      service: unifi
  services:
    unifi:
      loadBalancer:
        servers:
        - url: "http://unifi-network-application:8080"

Controller info & debugging

At this point and with the AP adopted, the controller recognizes that the AP is up and shows some statistics:

walking

If network issues are encountered, the access log on the unifi controller shows the incoming requests to the controller container. See these logs entering into the container:

_> docker exec -ti unifi-network-application /bin/bash
root@67cfb7f7b31c:/usr/lib/unifi# cd logs
root@67cfb7f7b31c:/usr/lib/unifi/logs# cat access.log
...
...
[2024-06-15 15:38:02,870] HTTP/1.1[172.18.0.3] 1ms 200 POST /inform
[2024-06-15 15:38:13,099] HTTP/1.1[172.18.0.3] 1ms 200 POST /inform
[2024-06-15 15:38:23,438] HTTP/1.1[172.18.0.3] 1ms 200 POST /inform
[2024-06-15 15:38:33,677] HTTP/1.1[172.18.0.3] 1ms 200 POST /inform
[2024-06-15 15:38:43,919] HTTP/1.1[172.18.0.3] 1ms 200 POST /inform
root@67cfb7f7b31c:/usr/lib/unifi/logs#

When everything is working as expected, the log contains inform POST requests that returns code 200 :)

comments powered by Disqus