Overview
This tutorial shows how to deploy Traefik v3 as a modern reverse proxy with Docker Compose and automatic HTTPS certificates using Let’s Encrypt via the Cloudflare DNS-01 challenge. The DNS-01 method works even behind NAT, on residential ISPs, and with Cloudflare’s orange cloud (proxy) enabled. By the end, you will have a secure, production-ready reverse proxy and a sample container accessible over HTTPS.
Prerequisites
- A Linux server (Ubuntu 22.04/24.04 or similar) with Docker Engine and Docker Compose v2 installed.
- A domain managed by Cloudflare (nameservers pointing to Cloudflare).
- A Cloudflare API token with Zone.DNS:Edit and Zone:Read permissions for the zone you’ll use.
- Basic terminal access and a user with Docker privileges.
Step 1 — Verify Docker and Compose
Confirm your Docker setup is ready. Run: docker --version and docker compose version. If Compose v2 is not present, install the latest Docker Engine from the official repository. On Ubuntu, ensure the docker group exists and your user is a member: sudo usermod -aG docker $USER then re-log.
Step 2 — Create a Dedicated Docker Network
Create an external network so Traefik can share it with your app containers: docker network create proxy. Using a dedicated network helps isolate traffic and makes adding new services predictable.
Step 3 — Prepare Folders and Secrets
Make a working directory for Traefik and create a place to store ACME data (certificates):
mkdir -p ~/traefik/letsencryptcd ~/traefiktouch ./letsencrypt/acme.jsonchmod 600 ./letsencrypt/acme.json
Create an .env file to hold your Cloudflare token securely. This file will be read by Docker Compose:
echo "CF_DNS_API_TOKEN=<paste_your_cloudflare_api_token>" > .env
The API token should include Zone.DNS:Edit and Zone.Zone:Read permissions for the domain. Restrict the token to the specific zone for better security.
Step 4 — Create docker-compose.yml
Create a docker-compose.yml file in ~/traefik with the following content. Replace [email protected] with your email and whoami.example.com with a real subdomain in your zone.
services: traefik: image: traefik:v3.1 command: - --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 - [email protected] - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json - --certificatesresolvers.letsencrypt.acme.dnschallenge=true - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare - --api.dashboard=true ports: - "80:80" - "443:443" environment: - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt networks: - proxy whoami: image: traefik/whoami:v1.10 labels: - "traefik.enable=true" - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)" - "traefik.http.routers.whoami.entrypoints=websecure" - "traefik.http.routers.whoami.tls.certresolver=letsencrypt" networks: - proxynetworks: proxy: external: true
Create a DNS A/AAAA record for whoami.example.com pointing to your server’s public IP in Cloudflare. The orange cloud (proxy) can be ON or OFF; DNS-01 works either way.
Step 5 — Launch and Test
Start the stack from the ~/traefik directory: docker compose up -d. Traefik will request a certificate from Let’s Encrypt using the Cloudflare DNS-01 challenge. Check logs with docker compose logs -f traefik to confirm issuance (look for “Server responded with a certificate”).
Open https://whoami.example.com in your browser. You should see the whoami test service showing headers and IP details over HTTPS.
Optional: Secure the Traefik Dashboard
The dashboard is enabled but not published by default in this setup. To expose it safely, add labels to a new service or to Traefik itself using a distinct host like traefik.example.com, require basic auth middleware, and keep it behind TLS. Always disable --api.insecure=true in production.
Troubleshooting Tips
- If certificates do not issue, verify the API token has Zone.DNS:Edit and is scoped to the correct zone. Also confirm the .env is loaded and the environment variable name matches.
- If you see rate-limit errors, you may have requested too many certificates; wait and try again or use the Let’s Encrypt staging endpoint during testing (--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory).
- Ensure your firewall allows TCP 80 and 443 inbound to the server.
Maintaining and Adding Services
To add a new app behind Traefik, place it on the proxy network and attach labels for rule, entrypoint, and TLS resolver. Example labels: traefik.enable=true, traefik.http.routers.app.rule=Host(`app.example.com`), traefik.http.routers.app.entrypoints=websecure, and traefik.http.routers.app.tls.certresolver=letsencrypt. Restart only the new service; Traefik hot-reloads routes automatically.
Conclusion
With Traefik v3, Docker Compose, and Cloudflare’s DNS-01 challenge, you can ship secure containers with automatic HTTPS and minimal friction. This setup scales cleanly, keeps certificates current, and works in challenging network environments. Add your apps with labels, keep tokens scoped and secret, and enjoy a tidy, TLS-by-default container platform.
3.
Comments
Post a Comment