Skip to content

Traefik Setup

Expose uses Traefik as a reverse proxy for TLS termination and routing. This guide covers setting up Traefik for use with Expose.

Why Traefik?

  • Automatic TLS certificate management with Let’s Encrypt
  • Docker-native service discovery
  • Wildcard certificate support via DNS challenge
  • WebSocket support out of the box

Directory Structure

/opt/traefik/
├── docker-compose.yml
├── traefik.yml
└── letsencrypt/
└── acme.json

Configuration Files

traefik.yml

# API and Dashboard
api:
dashboard: true
insecure: false
# Entry points
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
# Certificate resolvers
certificatesResolvers:
letsencrypt:
acme:
email: your@email.com
storage: /letsencrypt/acme.json
dnsChallenge:
provider: ovh # Your DNS provider
delayBeforeCheck: 30
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
# Docker provider
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: web

docker-compose.yml

services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./letsencrypt:/letsencrypt
environment:
# OVH credentials (change for your provider)
- OVH_ENDPOINT=ovh-eu
- OVH_APPLICATION_KEY=${OVH_APPLICATION_KEY}
- OVH_APPLICATION_SECRET=${OVH_APPLICATION_SECRET}
- OVH_CONSUMER_KEY=${OVH_CONSUMER_KEY}
networks:
- web
labels:
- "traefik.enable=true"
# Dashboard (optional)
- "traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xxx"
networks:
web:
external: true

DNS Provider Configuration

OVH

environment:
- OVH_ENDPOINT=ovh-eu
- OVH_APPLICATION_KEY=xxx
- OVH_APPLICATION_SECRET=xxx
- OVH_CONSUMER_KEY=xxx

Cloudflare

environment:
- CF_API_EMAIL=your@email.com
- CF_DNS_API_TOKEN=xxx

DigitalOcean

environment:
- DO_AUTH_TOKEN=xxx

See Traefik DNS Providers for more options.

Starting Traefik

Terminal window
# Create network
docker network create web
# Create acme.json with correct permissions
mkdir -p letsencrypt
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json
# Start Traefik
docker compose up -d
# Check logs
docker logs -f traefik

Verifying Setup

Terminal window
# Check Traefik is running
docker ps | grep traefik
# Test certificate generation (wait a few minutes)
curl -v https://api.yourdomain.com

Troubleshooting

Certificate Not Generated

  1. Check DNS is propagated: dig +short api.yourdomain.com
  2. Check Traefik logs: docker logs traefik | grep -i acme
  3. Verify DNS API credentials
  4. Ensure acme.json permissions are 600

502 Bad Gateway

  1. Check the backend service is running
  2. Verify network connectivity
  3. Check service labels are correct

WebSocket Issues

Ensure the backend service has proper WebSocket headers in Traefik labels if needed:

labels:
- "traefik.http.services.myservice.loadbalancer.server.scheme=ws"