How to Configure Traefik v3 as a Docker Reverse Proxy with Automatic Let’s Encrypt on Ubuntu 24.04

Overview

This tutorial shows how to deploy Traefik v3 as a modern Docker reverse proxy with automatic Let’s Encrypt TLS certificates on Ubuntu 24.04. You will set up secure HTTPS for any containerized web app using Docker Compose, with zero manual certificate handling. The guide uses the HTTP-01 challenge for public A-record domains and includes a note on switching to the DNS-01 challenge for wildcard certificates.

Prerequisites

- A fresh Ubuntu 24.04 server with sudo access.

- A domain name with an A record pointing to your server’s public IP (for example, whoami.example.com).

- Ports 80 and 443 open on the server firewall and any upstream firewall or cloud security group.

Step 1: Install Docker Engine and the Compose plugin

Install Docker using the official repository to get current packages. This also installs the docker compose plugin.

sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu noble stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker

Step 2: Prepare directories, permissions, and a Docker network

Create a project folder for Traefik and a persistent location to store ACME data. The acme.json file must be readable only by the Traefik process to keep private keys safe.

sudo mkdir -p /opt/traefik/letsencrypt
sudo touch /opt/traefik/letsencrypt/acme.json
sudo chmod 600 /opt/traefik/letsencrypt/acme.json
sudo chown -R $USER:$USER /opt/traefik
docker network create proxy
cd /opt/traefik

Step 3: Create an .env file

Store reusable variables in a .env file. Replace the placeholders with your real email and domain. The email is used by Let’s Encrypt for certificate notices.

cat > .env << 'EOF'
[email protected]
DOMAIN=example.com
EOF

Step 4: Write the Docker Compose file

The Compose file below pulls Traefik v3, configures HTTP-to-HTTPS redirection, enables the Docker provider, and uses the HTTP-01 challenge on port 80 to issue certificates. It also deploys a sample “whoami” app behind TLS at whoami.your-domain.

cat > docker-compose.yml << 'EOF'
version: "3.9"

networks:
  proxy:
    external: true

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    command:
      - --api.dashboard=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.le.acme.httpchallenge=true
      - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./letsencrypt:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - proxy
    restart: unless-stopped

  whoami:
    image: traefik/whoami:v1.10
    labels:
      - traefik.enable=true
      - traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)
      - traefik.http.routers.whoami.entrypoints=websecure
      - traefik.http.routers.whoami.tls.certresolver=le
      - traefik.http.services.whoami.loadbalancer.server.port=80
    networks:
      - proxy
    restart: unless-stopped
EOF

Step 5: Start the stack and verify HTTPS

Bring the services online and watch Traefik’s first-run logs. The proxy will request and store certificates in acme.json. Ensure your DNS A record for whoami.example.com points to this server before you start.

docker compose up -d
docker logs -f traefik

When the logs show that certificates were obtained, browse to https://whoami.example.com. You should see a simple page from the whoami container over HTTPS. You can also test from the terminal:

curl -I https://whoami.example.com

Optional: Use DNS-01 for wildcard certificates

If you need a wildcard like *.example.com, switch to the DNS-01 challenge. This requires a DNS provider API token. As an example, for Cloudflare you would add two flags and an environment variable. Consult Traefik’s documentation for the exact variable names supported by your DNS provider.

# In docker-compose.yml, replace the HTTP-01 lines with:
      - --certificatesresolvers.le.acme.dnschallenge=true
      - --certificatesresolvers.le.acme.dnschallenge.provider=cloudflare

# And add, under the traefik service:
    environment:
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}

# Then define it in .env (use a least-privilege token scoped to DNS edit):
CF_DNS_API_TOKEN=your_cloudflare_dns_token

After changing the challenge type, remove the old acme.json or start with a fresh file, then redeploy so Traefik can issue new certificates using DNS-01.

Security and maintenance tips

- Keep the Docker socket mount read-only, as shown, to reduce risk. Consider using a socket proxy if you expose Traefik to untrusted networks.

- Do not expose the Traefik dashboard publicly without authentication. If needed, put the dashboard behind a router with basic auth middleware and IP allowlists.

- Back up /opt/traefik/letsencrypt/acme.json. It contains your issued certificates and keys.

- Use a process manager (Compose restart policy is already set) and keep Traefik updated to the latest v3 patch release.

Troubleshooting

- If Let’s Encrypt fails, confirm that ports 80 and 443 are reachable from the internet and that your DNS A record is correct. The HTTP-01 challenge requires port 80 to reach the server.

- Check logs with docker logs -f traefik for clear error messages (rate limiting, challenge timeouts, or permission issues).

- Ensure acme.json permissions remain 600. Incorrect permissions can prevent Traefik from writing certificates.

- If labels do not seem to apply, verify that the whoami container is on the same Docker network named proxy and that exposedbydefault is false (which requires explicit traefik.enable=true).

You now have a production-ready reverse proxy on Ubuntu 24.04 with automatic HTTPS, simple app onboarding via labels, and a clean path to wildcard certificates when needed.

Comments