Docker + Unifi Controller

Ich habe ein neues Projekt: Unifi Controller mit Docker und Traefik. Seit Jahren fahre ich mit Unifi Hardware, beruflich wie auch privat und das durchwegs gut. Den Controller habe ich dabei bisher (fast) immer auf eigener Hardware laufen lassen: Cloud Key, MacBookPro, Windows Server, Linux Server. Schwierig bei (m)einer Heiminstallation ist dabei immer, dass die Hardware des Controllers, auf die eine oder andere Weise schlapp macht. Diese Anleitung geht daher einen (für mich) neuen Weg: Unifi Controller mit Docker und Traefik.

Die Grundlage ist der Docker-Traefik Artikel, der sich mit der Einrichtung von docker auf Ubuntu und dem Zusammenschluss mit traefik kümmert.

Vorbereitungen

Die Vorbereitungen gehen schnell von der Hand, wenn die Infrastruktur steht, heißt bereits einen docker mit traefik existiert und läuft. Wenn Du diese Anleitung nachspielst, aber nicht weißt ob das gut gehen wird, kannst Du hier noch einmal nachlesen was die Voraussetzungen sind.

Verzeichnisse anlegen

Wie in allen Anleitungen lege ich das/die notwendige/n Verzeichnis/se, eine docker-compose.yml und eine .env an. Die .env ist vielleicht neu und falls ich diese hier zum ersten Mal verwende, die Vorteile sind die Verwendung von Variablen (Werte die sich in der Konfiguration wiederholen) und einer Reduzierung von potentiellen Fehlern. Dazu kann die Konfiguration (docker-compose.yml) damit auch in ein Repository (zB git) eingecheckt werden, ohne dass Kennwörter kompromittiert werden. Natürlich nur, wenn die .env beim commit ignoriert wird.

mkdir -p /opt/containers/unifi/config
touch /opt/containers/unifi/docker-compose.yml
Zsh

Den Inhalt der docker-compose.yml kopieren wir aus dem Listing unten. Das Image kommt von linuxserver.io. Das bedeutet, Du musst Dir selbst ein Bild machen, inwieweit Du dieser Seite Dein Vertrauen aussprichst und das Image nutzen willst, kannst, darfst!

Konfiguration docker-compose.yml

Ich gehe auf einen Teil der Einstellungen ein. Die die mir wichtig erscheinen und die Du eventuell an Deine Bedürfnisse anpassen musst oder willst.

.env

In dieser Datei, die durch den . am Anfang als “unsichtbar” im System erscheint, werden einige Variablen gespeichert. Hier sind Deinen Bedürfnissen kaum Grenzen gesetzt. Idealerweise stehen hier auch Kennwörter, oder die Domain drin und werden dann, durch die entsprechenden Variablen zur Laufzeit ersetzt. Beispielhaft siehst Du hier die Zeitzone, oder die Benutzer-ID etc.

Den Variablen (zB PUID) werden in der .env Werte zugewiesen und in der docker-compose.yml mit ${PUID} referenziert.

PUID=1000
PGID=1000
TZ="Europe/Berlin"
Zsh

Achte darauf, dass die Werte richtig ausgelesen werden. Ein Problem könnten Zeichen sein, die escaped werden müssen.

Ports

Ein Augenmerk liegt auf ports:. Der Controller nutzt verschiedene Ports um verschiedene Aufgaben und Dienste zu erledigen und bereitzustellen. Die unmittelbar Wichtigsten sind angegeben, bei anderen muss Du bei Bedarf nur das Kommentarzeichen entfernen.

Auf den ports: liegt noch ein weiterer Augenmerk:
Wird vor oder auf dem Server ein Firewall betrieben, muss die Kommunikation entsprechend abgestimmt werden. traefik kann nur reagieren, wenn die Anfrage auch tatsächlich ankommt. Verwendest Du zB einen Server bei Hetzner, dann hast Du vielleicht einen Firewall konfiguriert. Lässt dieser (default) nur die Ports 22 ssh, 80 http und 443 https zu, dann kommen die Anfragen der Devices nicht bis zum Controller.

version: '3.9'

services:

  unifi:
    image: lscr.io/linuxserver/unifi-controller:latest
    hostname: unifi
    restart: unless-stopped
    container_name: unifi
    volumes:
      - ./config:/config
    ports:
      # Unifi STUN port
      - 3478:3478/udp
      # AP Disovery
      - 10001:10001/udp
      # Device communication
      - 8080:8080
      # Web Admin Port
      - 8443:8443
      # Required for the "make controller discoverable on L2 network" option
      #- 1900:1900/udp # optional
      # Unifi guest portal HTTP redirect
      #- 8880:8880 # optional
      # Mobile throughput test port
      #- 6789:6789 # optional
      # Unifi guest portal HTTPS redirect
      #- 8843:8843 # optional
      # Remote syslog Port
      #- 5514:5514/udp
    networks:
      - proxy
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - MEM_LIMIT=1024 # optional
      - MEM_STARTUP=1024 # optional
    labels:
      - "traefik.enabled=true"
      # traefik.routers: https://doc.traefik.io/traefik/routing/providers/docker/
      - "traefik.http.routers.unifi.entrypoints=http"
      # die passende Domain einsetzen / enter the correct domain
      - "traefik.http.routers.unifi.rule=Host(`unifi.DeineTolleDomain.tld`)"
      - "traefik.http.routers.unifi.middlewares=unifi-https-redirect"
      - "traefik.http.routers.unifi-secure.entrypoints=https"
      # die passende Domain einsetzen / enter the correct domain
      - "traefik.http.routers.unifi-secure.rule=Host(`unifi.DeineTolleDomain.tld`)"
      - "traefik.http.routers.unifi-secure.tls=true"
      - "traefik.http.routers.unifi-secure.tls.certresolver=http"
      - "traefik.http.routers.unifi-secure.service=unifi"      
      - "traefik.http.routers.unifi-secure.middlewares=secHeaders@file"
      #
      - "traefik.http.middlewares.unifi-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.services.unifi.loadbalancer.server.port=80"
      #
      - "traefik.tags=frontend"
      - "traefik.admin.backend=unifi"
      # die passende Domain einsetzen / enter the correct domain
      - "traefik.admin.frontend.rule=Host:unifi.DeineTolleDomain.tld"
      - "traefik.admin.port=8443"
      - "traefik.admin.protocol=https"
      # Sicherheitseinstellungen /security options
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.browserXSSFilter=true"
      - "traefik.frontend.headers.contentTypeNosniff=true"
      - "traefik.frontend.headers.forceSTSHeader=true"
      # die passende Domain einsetzen / enter the correct domain
      - "traefik.frontend.headers.SSLHost=unifi.DeineTolleDomain.tld"
      - "traefik.frontend.headers.STSIncludeSubdomains=true"
      - "traefik.frontend.headers.STSPreload=true"
      - "traefik.frontend.headers.frameDeny=true"
      #
      - "traefik.docker.network=proxy"
networks:
  proxy:
    external: true
YAML

Labels

Die Sektion mit den frontend.headers ist wichtig. Wenngleich ein Teil dieser Parameter bereits in der allgemeinen Konfiguration von traefik gesetzt worden sein könnten, werden diese bestenfalls damit nur überschrieben. Fehlen diese aber, kann sich das u.a. auf die Erreichbarkeit auswirken.

Die Header Middleware verwaltet darüber die Header eingehender Anfragen und Antworten. Den sicherheitsrelevanten Headern (HSTS headers, Browser XSS filter, etc) kommt dabei eine besondere Bedeutung zu, denn sind diese nicht gesetzt (nicht richtig gesetzt), dann kann es zB vorkommen, dass Chrome die Verbindung gar nicht aufbauen will und dich stattdessen warnt, dass Dir eventuell jemand was vorgaukelt. Dafür sind diese Einstellungen wichtig.

labels:
  - "traefik.frontend.headers.framedeny=true"
  - "traefik.frontend.headers.browserxssfilter=true"
Zsh

Ansonsten liefert die traefik Knowledgebase eine überzeugende Hilfe.

Unifi Controller starten

Mit der Vorbereitung zum Start bist Du durch. Jetzt lassen wir den Ballon steigen. Ich habe es mir hier zur Angewohnheit gemacht, docker compose ohne -d Parameter zu starten. Damit habe ich die Ausgabe und Fehlerausgabe direkt an der Kommandozeile und muss nicht mit screen durch verschiedene Fenster springen (was auch seinen Scharm hat).

docker compose -f /opt/containers/unifi/docker-compose.yml up
Zsh

Die Ausgabe entspricht der in der Abbildung weiter unten, wenn alles richtig eingestellt ist. Oder aber flutet den Bildschirm mit Fehlern. Aus dem laufenden Prozess kommst Du dann mit CTRL+C (STRG+C) und wenn alles bis hierhin durchgelaufen ist, kannst Du -d anhängen.

Auf alle Fälle musst Du diesem Container Zeit zum Starten einräumen, denn es wird ein JAVA-App-Server (Tomcat od. Catalina) hochgefahren.

Logging

Nach dem Start des Containers mit -d kannst Du Dir die Logs des Containers ausgeben lassen um zu checken, ob alles geklappt hat.

docker logs -f unifi
Zsh
Logausgabe in Docker

Zusammenfassung

Mit der Installation als Docker Container habe ich Dir gezeigt, wie Du Deinen Unifi Controller einfach selbst kosten kannst. Mit wenigen Schritten kannst Du somit unter https://unifi.DeineTolleDomain.tld:8443/ auf diesen zugreifen. Die ersten Schritte bei der Einrichtung sind dabei durch einen Wizard begleitet. Was Du (optional) brauchst ist ein UI-Konto, dass Du unter https://account.ui.com anlegen kannst. Damit kannst Du den Controller von überall aus steuern.

Achtung: Sei Dir bewusst, dass Du damit auch potentielle Angriffsvektoren auf die Unifi-Struktur hast. Es empfiehlt sich auf jeden Fall zusätzliche Absicherungsmaßnahmen zu treffen.

Unifi Controller Aufruf im Browser
Start » Docker + Unifi Controller

Quellen

traefik routers
linuxserver.io
ui.com

Ein Gedanke zu „Docker + Unifi Controller

Schreibe einen Kommentar