Skip to content

Self-host Traefik

updated Jul 2026prices checked · Jul 2026Install verified on Ubuntu 26.04 · Sep 2026 · how we test
We earn commissions when you shop through the links below. Full disclosure →

A cloud-native reverse proxy that auto-discovers your Docker containers via labels and provisions TLS for them automatically. More setup than a UI proxy, but unbeatable once your stack grows.

Key facts

LicenseMIT
StackGo
Min RAM256 MB
Official imageyes
Measured idle RAM14 MB
Difficulty
Our recommendation

Pick Traefik when your services live in Docker and you want routes and TLS to appear from container labels: the MIT-licensed Go binary watches the Docker socket, provisions Let's Encrypt certificates (wildcards too, but only via a DNS-01 challenge — our snippet uses HTTP-01) and reloads without restarts, with a dashboard, metrics and access logs built in. The README's release cycle is three or four minor versions a year, each supported only until the next ships; v3 is the current major (3.7.13 as of September 2026). Our snippet is the safe starting point — it disables `exposedByDefault`, so nothing is routed until you label it.

Follow the Traefik deploy guide →

What you need

  • Any VPS with at least 256 MB of RAM
  • A domain you control — most self-hosted setups need HTTPS in front of them
  • About an afternoon — budget time for troubleshooting
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
From $23.59/mo · 2 vCPU / 4 GB / 80 GB · EU + US
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
From $4/mo · 1 vCPU / 1 GB / 20 GB · US + EU + Asia
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
From $6/mo · 1 vCPU / 1 GB / 25 GB · US + EU + Asia
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install with Docker Compose

Save this as compose.yml and run docker compose up -d:

# Traefik — reverse proxy; reads Docker labels, ACME via Let's Encrypt
services:
  traefik:
    image: traefik:v3
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.le.acme.email=you@example.com
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
    ports: ["80:80", "443:443"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
# docker compose up -d — then label each app: traefik.http.routers.<n>.rule=Host(`app.example.com`)

What you take on

Traefik's power is the socket and the labels; its docs are direct about the responsibility both carry:

non-negotiableMounting /var/run/docker.sock hands Traefik the Docker API, and the docs' Security Note says "If Traefik is attacked, then the attacker might get access to the underlying host." Their remedies are a TCP or SSH endpoint with client certificates, or Tecnativa's docker-socket-proxy in between. Our snippet mounts the socket read-only, which is a mitigation, not a fix.
non-negotiableSupport is short-lived: "Each version is supported until the next one is released", and there are 3/4 releases a year. The traefik:v3 tag follows minors automatically; pin v3.7 if you want to control when the jump happens, and treat a major (v2 → v3) as a migration-guide exercise.
non-negotiableproviders.docker.exposedByDefault defaults to true — every container on the socket gets a route unless you set it false and opt in with traefik.enable=true. Our snippet sets it false; keep it that way.
non-negotiableThe dashboard and API expose "sensitive data" and "should be at least secured by authentication and authorizations"; api.insecure defaults to false, and the documented pattern is a router on your TLS entrypoint with a basicAuth middleware, never a publicly exposed port.
non-negotiableACME state lives in acme.json: persist it (our snippet mounts ./letsencrypt) or every restart re-issues certificates. HTTP-01 needs port 80 reachable by Let's Encrypt, TLS-ALPN-01 needs 443, and acme.caServer can point at the staging CA while you test. The 256 MB floor is our estimate; upstream publishes no RAM figure.

Head-to-head

More self-hosted tools

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.