Traefik with Docker
My initial configuration for web proxy of my self hosted websites consisted of an installation of NGINX and Certbot locally on the Docker server (not in containers) along with manual file updates or manual certificate requests/updates anytime I wanted to stand up another web container for self hosting. This worked just fine but I wanted to make this process fully automated. Recently, I stumbled onto Traefik when I was researching alternative solutions. Here is a brief description from their website:
Traefik is an open-source Edge Router that makes publishing your services a fun and easy experience. It receives requests on behalf of your system and finds out which components are responsible for handling them.
What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services.The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request.
Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and the list goes on; and can handle many at the same time. (It even works for legacy software running on bare metal.)
With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state..
The reason why I chose Traefik over other proxy services was due to the fact that, once properly configured, I would only need to add some flags to any docker container I currently had (or new ones to be created) for Traefik to automatically update itself - without exposing said containers externally or updating/restarting files and services. I highly recommend this setup if you have a domain (or multiple) that you want to use with containers on your network, securely. This configuration will be used throughout nearly all of my guides so I wanted to make sure there was a page dedicated to my Traefik configurations for easy reference.
Before starting this installation, you'll probably need to forward ports 80 (http) and 443 (https) to the host running your docker installation to ensure that Traefik receives all web traffic for proper routing. (Refer to your router's vendor documentation for this step)
For this setup, we will be creating a dedicated directory to store all of our docker-compose files as well as creating the files for editing
mkdir -p traefik/data traefik/data/configurations; cd traefik
touch docker-compose.yml
touch data/traefik.yml
touch data/acme.json
touch data/configurations/dynamic.yml
chmod 600 data/acme.json
Then create the "proxy" network for Traefik to communicate externally as well as use within any other docker-compose.yml files to automatically be detected by Traefik
docker network create proxy
Don't forget to alter these files with your email/domain!
docker-compose file
version: '3.7'
services:
traefik:
image: "traefik:latest"
container_name: traefik
restart: always
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
# Add folder with dynamic configuration yml
- ./data/configurations:/configurations
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.traefik-secure.entrypoints=websecure"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.mycooldomain.net`)"
- "traefik.http.routers.traefik-secure.middlewares=user-auth@file"
- "traefik.http.routers.traefik-secure.service=api@internal"
networks:
proxy:
external: true
traefik file
log:
level: DEBUG
api:
dashboard: true
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
websecure:
address: :443
http:
middlewares:
- secureHeaders@file
- nofloc@file
tls:
certResolver: letsencrypt
pilot:
dashboard: false
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /configurations/dynamic.yml
certificatesResolvers:
letsencrypt:
acme:
email: email@example.com
storage: acme.json
keyType: EC384
httpChallenge:
entryPoint: web
buypass:
acme:
email: email@example.com
storage: acme.json
caServer: https://api.buypass.com/acme/directory
keyType: EC256
httpChallenge:
entryPoint: web
dynamic configuration file
# Dynamic configuration
http:
middlewares:
nofloc:
headers:
customResponseHeaders:
Permissions-Policy: "interest-cohort=()"
secureHeaders:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
bw-stripPrefix:
stripPrefix:
prefixes:
- "/notifications/hub"
forceSlash: false
user-auth:
basicAuth:
users:
- "admin:$apr1$oTAsPbab$XasZ6DIlRHf.KTMzbd.Ig1"
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
minVersion: VersionTLS12
Now we're ready to start Traefik
docker-compose up -d
You'll need to allow some time for Traefik to start up, as well as generate your domain's SSL certificate. When it's ready, just go to https://traefik.yourdomain and login with the username and password you created. For our example, we'll navigate to https://traefik.mycooldomain.net
Notes
- This dynamic.yml configuration contains some settings I use to host my own BitWarden container (check out the guide here) so please remove or comment out the below section if you don't plan to use BitWarden
#bw-stripPrefix:
# stripPrefix:
# prefixes:
# - "/notifications/hub"
# forceSlash: false
- For the "user-auth" section of the dynamic.yml file you'll want to generate your own hashed login credentials so you don't store your admin portal login in plain text within the file
htpasswd -nb admin <username> <password>
Sample run:
$ htpasswd -nb admin thisisthepassword
admin:$apr1$oTAsPbab$XasZ6DIlRHf.KTMzbd.Ig1
Now that our traefik container is created, we can create containers with traefik flags to automatically have traefik detect and route to dynamically. For a full list of available features, check out traefik's documentation page.