Hvad er Traefik, og hvornår giver det mening?

Traefik er en reverse proxy skrevet i Go og udgivet i 2015 af Emile Vauge. Det er ikke det eneste valg. Nginx Proxy Manager er mere klikvenligt, Caddy er enklere at konfigurere i tekst. Men Traefik er det der fungerer bedst med Docker. Det læser dine container-labels og konfigurerer sig selv automatisk, hver gang du starter en ny service.

Alternativet er at holde styr på porte manuelt. Port 8080 til Pi-hole, 8181 til Nextcloud, 9000 til noget du oprettede for seks måneder siden og ikke kan huske hvad er. Traefik giver dig pihole.dit-domæne.dk, nextcloud.dit-domæne.dk og HTTPS på begge uden at du gør noget ekstra.

Denne guide bruger Cloudflare som DNS-udbyder, fordi det er det mest udbredte setup i homelab-miljøer og fordi Cloudflare DNS-challenge giver dig wildcard-certifikater der dækker alle subdomæner på én gang. Har du en anden DNS-udbyder understøtter Traefik over 60 udbydere.

Du skal bruge
  • Raspberry Pi (3B+, 4 eller 5) med Raspberry Pi OS Lite 64-bit
  • Docker og Docker Compose installeret (se Cloudflare Tunnel-guiden for Docker-installation)
  • Et domæne med DNS hos Cloudflare
  • Et Cloudflare API-token med Zone:DNS:Edit-tilladelse
  • Port 80 og 443 forwarded i din router til Pi'ens IP (eller brug Cloudflare Tunnel — se neden for)
📝 Cloudflare Tunnel som alternativ til port-forwarding. Har du allerede Cloudflare Tunnel sat op, kan du sende trafik igennem tunnelen til Traefik i stedet for at åbne porte. Sæt Traefik til at lytte på port 80 internt, og konfigurér Cloudflare Tunnel til at sende til http://localhost:80. HTTPS termineres så i Cloudflare, ikke i Traefik — men du slipper for åbne porte.

Projektstruktur

Opret en mappe til Traefik og lav de filer du skal bruge:

mkdir -p ~/traefik/data
cd ~/traefik

# Opret tom acme.json til certifikater — SKAL have rettighed 600
touch data/acme.json
chmod 600 data/acme.json

Mappestrukturen ser sådan ud når du er færdig:

traefik/
├── docker-compose.yml
├── data/
│   ├── traefik.yml       # statisk konfiguration
│   └── acme.json         # Let's Encrypt certifikater (autogenereret)

Opret Docker-netværket

Traefik skal kunne nå dine andre containers. Det gøres via et delt Docker-netværk. Opret det én gang:

docker network create traefik-net

Alle services der skal have HTTPS via Traefik skal tilsluttes dette netværk.

Cloudflare API-token

Traefik skal kunne oprette DNS-records hos Cloudflare for at bevise over for Let's Encrypt at du ejer domænet. Det kræver et API-token — ikke din globale API-nøgle.

Gå til Cloudflare Dashboard → My Profile → API Tokens → Create Token. Brug skabelonen Edit zone DNS, begræns den til det specifikke domæne du bruger, og kopiér tokenet. Det vises kun én gang.

Opret en .env-fil i ~/traefik/ med tokenet:

# ~/traefik/.env
CF_DNS_API_TOKEN=dit_cloudflare_api_token_her
⚠️ Tilføj .env til .gitignore. Commit aldrig .env-filer til et repository. API-tokenet giver adgang til at ændre dine DNS-records.

traefik.yml — statisk konfiguration

Opret ~/traefik/data/traefik.yml. Det er den statiske konfiguration Traefik læser ved opstart:

# ~/traefik/data/traefik.yml

api:
  dashboard: true       # aktiver webdashboard
  insecure: false       # dashboard kun via HTTPS

log:
  level: INFO           # DEBUG giver meget output — brug kun ved fejlfinding

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure  # tving alt HTTP til HTTPS
          scheme: https

  websecure:
    address: ":443"

certificatesResolvers:
  cloudflare:
    acme:
      email: [email protected]               # din e-mail til Let's Encrypt advarsler
      storage: /etc/traefik/acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false  # services er ikke eksponeret medmindre de har labels
📝 exposedByDefault: false er vigtig. Med den slået fra skal du aktivt tilføje labels til de services du vil eksponere. Uden den ville alle containers automatisk få en route — herunder ting du ikke har tænkt over.

docker-compose.yml

Opret ~/traefik/docker-compose.yml:

# ~/traefik/docker-compose.yml

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    environment:
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./data/acme.json:/etc/traefik/acme.json
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"
      # Dashboard-route — erstat dit-domæne.dk med dit rigtige domæne
      - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.dit-domæne.dk`)"
      - "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
      - "traefik.http.routers.traefik-dashboard.tls.certresolver=cloudflare"
      - "traefik.http.routers.traefik-dashboard.service=api@internal"
      # Basic auth til dashboard — generer med: echo $(htpasswd -nb bruger kodeord) | sed -e s/\\$/\\$\\$/g
      - "traefik.http.routers.traefik-dashboard.middlewares=traefik-auth"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$xxxxxxxx$$xxxxxxxxxxxxxxxxxxxxxxxxx"

networks:
  traefik-net:
    external: true

Genér basic auth-password

Du skal generere en krypteret password-streng til dashboard-adgang. Installér apache2-utils og kør:

sudo apt install apache2-utils -y

# Generer hashet kodeord — erstat admin og dit_kodeord
echo $(htpasswd -nb admin dit_kodeord) | sed -e s/\\$/\\$\\$/g

Kopiér output og indsæt det i basicauth.users-labelen i docker-compose.yml. De dobbelte $$ er nødvendige fordi Docker Compose ellers fortolker $ som en variabel.

Start Traefik

cd ~/traefik
docker compose up -d

# Tjek at den kører
docker compose logs -f

Første gang Traefik starter henter den et certifikat fra Let's Encrypt via Cloudflare DNS-challenge. Det tager typisk 30–120 sekunder. Du ser noget i stil med Obtained certificate for domains i loggen når det lykkes.

📝 Let's Encrypt rate limits. Der er et limit på 5 certifikater per domæne per uge. Under opsætning og test kan du tilføje caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" under acme: i traefik.yml for at bruge staging-serveren. Staging-certifikater er ikke trusted af browsere, men du slipper for at ramme rate limits.

Tilslut en service — eksempel med Nextcloud

Tilføj Traefik-labels til din service og kobl den på traefik-net-netværket. Traefik opdager den og opretter routingen automatisk.

Har du allerede Nextcloud kørende, tilføjer du dette til din Nextcloud docker-compose.yml:

services:
  nextcloud:
    image: nextcloud:latest
    # ... dine eksisterende indstillinger ...
    networks:
      - traefik-net         # SKAL være med
      - nextcloud-internal  # dit interne netværk til database
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.rule=Host(`nextcloud.dit-domæne.dk`)"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.routers.nextcloud.tls.certresolver=cloudflare"
      - "traefik.http.services.nextcloud.loadbalancer.server.port=80"

networks:
  traefik-net:
    external: true
  nextcloud-internal:
    internal: true   # ingen adgang til internettet fra dette netværk

Genstart Nextcloud-stacken med docker compose up -d. Traefik opdager labelsene og Nextcloud er tilgængelig på https://nextcloud.dit-domæne.dk inden for 30 sekunder — med gyldigt certifikat.

Tilslut Pi-hole eller AdGuard Home

Samme princip. Tilføj labels og traefik-net til din Pi-hole eller AdGuard Home-service:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.pihole.rule=Host(`pihole.dit-domæne.dk`)"
  - "traefik.http.routers.pihole.entrypoints=websecure"
  - "traefik.http.routers.pihole.tls.certresolver=cloudflare"
  # Pi-hole webinterface kører på port 80 i containeren
  - "traefik.http.services.pihole.loadbalancer.server.port=80"

Wildcard-certifikat (valgfrit)

I stedet for et certifikat per subdomain kan du få ét wildcard-certifikat der dækker *.dit-domæne.dk. DNS-challenge er et krav for wildcards — og det bruger du allerede via Cloudflare. Ingen ændringer i traefik.yml. Tilføj kun disse labels til hver router:

- "traefik.http.routers.nextcloud.tls.domains[0].main=dit-domæne.dk"
- "traefik.http.routers.nextcloud.tls.domains[0].sans=*.dit-domæne.dk"

Fejlfinding

Certifikatet kommer ikke

Tjek Traefik-loggen med docker compose logs traefik | grep -i acme. De hyppigste årsager:

Service ikke tilgængelig

Kør docker network inspect traefik-net og bekræft at både Traefik-containeren og din service-container er i netværket. Mangler en af dem er routingen umulig, uanset hvad labels siger.

Dashboard viser "404 page not found"

Traefik-dashboardet kræver at du rammer den præcise host der er sat i label-reglen. Prøv at curie direkte: curl -H "Host: traefik.dit-domæne.dk" http://localhost. Virker det, er det et DNS-problem — domænet peger ikke på Pi'ens IP.

Redirect loop

Sker som regel hvis du kører Traefik bag Cloudflare med SSL-tilstand sat til "Flexible" i Cloudflare. Cloudflare sender HTTPS til Traefik, Traefik redirecter til HTTPS, og det gentages. Sæt Cloudflare SSL til "Full (strict)" eller "Full" hvis du kører Cloudflare Tunnel.

Næste skridt

Traefik kører. Nu kan du tilslutte resten af dine services:

Ofte stillede spørgsmål

Kan jeg bruge Traefik uden et domænenavn?

Nej. Traefik er bygget til hostbaseret routing og kræver et domæne. Til LAN-brug uden domæne er Nginx Proxy Manager et nemmere alternativ med GUI-konfiguration og direkte IP-support.

Hvad er forskellen på Traefik og Nginx Proxy Manager?

Nginx Proxy Manager har en GUI og er hurtigere at komme i gang med. Traefik konfigureres i kode via Docker labels, der giver bedre automatisering og ingen GUI-afhængighed. Traefik fornyer SSL-certifikater automatisk uden manuelt arbejde.

Virker Traefik på en Raspberry Pi Zero?

Pi Zero 2W kører det med knap margen. Den første Pi Zero har kun 512 MB RAM — for stramt til produktion med mere end én service. Brug Pi 3B+ eller nyere for stabil drift.

Skal jeg åbne porte i min router?

Kun port 80 og 443 hvis du vil tilgå services fra internettet. Bruger du Cloudflare Tunnel i stedet for direkte eksponering, behøver du ingen åbne porte overhovedet.

Kilder