Update January 2026: This post documents my early struggles with container networking. While I eventually mastered Traefik, my current architecture (The commander Swarm) now uses a custom Python-based Gateway with strict authorization for internal service discovery, moving beyond simple reverse proxies. Read about the Swarm Architecture.

The 4-Day Nightmare

It was supposed to be simple.

  1. Spin up Traefik.
  2. Add labels to my docker containers.
  3. Get nice HTTPS URLs like plex.Arcturus-Prime.com.

Reality: 4 Days. 488 AI Chat Messages. 0 Sleep.

The Setup

I was running a standard “Seedbox” stack: Sonarr, Radarr, Plex, etc. I wanted them accessible remotely securely.

My docker-compose.yml looked fine:

version: "3.8"

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=your-email@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
    networks:
      - traefik-public

  # The Service we want to expose
  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.Arcturus-Prime.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
    networks:
      - traefik-public

networks:
  traefik-public:
    external: true

Problem 1: The “Permission Denied” Cycle

Me: docker ps Linux: permission denied Me: sudo docker ps Linux: OK

I spent 24 hours typing sudo before realizing I just needed to add my user to the docker group: sudo usermod -aG docker $USER. Lesson 1: Linux permissions are not a suggestion.

Problem 2: The ACME Loop (Rate Limits)

Traefik tries to get a certificate from Let’s Encrypt. It fails because my DNS hadn’t propagated. It retries immediately. It fails.

After 5 attempts, Let’s Encrypt banned me for 1 hour. I fixed the DNS. Traefik tried again. BANNED.

Lesson 2: Use the Staging environment for ACME until it works. --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory

Problem 3: The Environment Variable from Hell

I had a .env file. DOMAIN=Arcturus-Prime.com

But Traefik kept looking for certificates for mydomain.com. Why? Because I had hardcoded Host(\traefik.mydomain.com`)` in one obscure label on the dashboard service, copying it blindly from a tutorial.

Lesson 3: Don’t copy-paste code you don’t read.

Problem 4: Docker Networks

I expected containers to just “see” each other. They don’t. If Traefik is on traefik-public network, and Sonarr is on default network, they are in parallel universes.

I had to manually attach every single service to the proxy network:

networks:
  - default
  - traefik-public

The Breakthrough

On Day 4, at 9:45 PM, I saw it in the logs: level=info msg="Certificate valid for domains [plex.Arcturus-Prime.com]"

I cried a little. I opened my browser. Green Lock. It was beautiful.

Was it worth it?

I now have 16 subdomains automagically secured. I rarely touch the config. Optimizing infrastructure is painful, but once it works, it feels like magic. Just … maybe don’t do it all in one weekend next time.