Docker - Traefik - Wildcard Cert
Page content
Intro
TLS is must, but do you wanna generate a own Certificate for each Service you Provide ? Specially, when you have a *.domain.tld Record set ?
Trafik is able to handle that for you. Let’s Encrypt offers the possibility to use DNS Validation for Wildcard Domains. Here is a list of Providers that can automate DNS Verfication.
Helpful URL
- https://doc.traefik.io/traefik/user-guides/docker-compose/acme-dns/
- https://www.digitalocean.com/community/tutorials/how-to-use-traefik-v2-as-a-reverse-proxy-for-docker-containers-on-ubuntu-20-04
- https://www.carluccio.de/reverse-proxy-traefik-mit-wildcard-zertifikaten/
- https://linuxblog.xyz/posts/traefik-2-docker-compose/
- https://medium.com/@KagundaJM/proxy-buffalo-app-with-traefik-and-lets-encrypt-on-digitalocean-505060edef4c
Fully Example with Docker Compose, Traefik, Digital Ocean
Prepare Env
cd /where/ever/you/want
mkdir data
touch data/acme.json
Variables
we need a few Variables. Let’s put them in a .env file and docker-compose will use them when called.
- DOMAIN: the domain where you wanna provide/test the service
- LE_DNS_EMAIL: for registration with let’s encrypt. must be a valid email address
- DO_AUTH_TOKEN: the API token you generated at DO (https://cloud.digitalocean.com/account/api/tokens)
- AUTH_USER: Username & Password for Authentication on the Website/Services you generate)
cat << 'EOF' > .env
DOMAIN="yourdomain.tld"
LE_DNS_EMAIL="[email protected]"
DO_AUTH_TOKEN=dop_v1_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
EOF
AUTH_USER=$(echo $(htpasswd -nb CHANGEUSER CHANGEPASSWORD) | sed -e s/\\$/\\$\\$/g)
echo "AUTH_USER=${AUTH_USER}" >> .env
traefik.yml
cat << 'EOF' > data/traefik.yml
log:
# DEBUG, PANIC, FATAL, ERROR, WARN, and INFO.
level: DEBUG
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
watch: true
file:
filename: "/dynamic_conf.yml"
watch: true
certificatesResolvers:
dns:
acme:
email: ${LE_DNS_EMAIL}
storage: acme.json
keyType: RSA4096
# Staging
#caServer: https://acme-staging-v02.api.letsencrypt.org/directory
# Production
caServer: https://acme-v02.api.letsencrypt.org/directory
dnschallenge:
provider: digitalocean
delaybeforecheck: 60
resolvers:
- ns1.digitalocean.com:53
- ns2.digitalocean.com:53
- ns3.digitalocean.com:53
EOF
dynamic_conf.yml
cat << 'EOF' > data/dynamic_conf.yml
tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
http:
middlewares:
# secHeaders@file
# - Set Sameorigin
# - Set HSTS
# - enforce HTTPS
secHeaders:
headers:
browserXssFilter: true
contentTypeNosniff: true
customFrameOptionsValue: "SAMEORIGIN"
sslRedirect: true
#HSTS Configuration
#stsIncludeSubdomains: true
#stsPreload: true
#stsSeconds: 15552000
# redirect@file: Redirect HTTP -> HTTPS
redirect:
redirectScheme:
scheme: "https"
EOF
docker-compose
cat << 'EOF' > docker-compose.yml
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/acme.json:/acme.json
- ./data/traefik.yml:/traefik.yml:ro
- ./data/dynamic_conf.yml:/dynamic_conf.yml
environment:
- DO_AUTH_TOKEN=${DO_AUTH_TOKEN}
command:
- --certificatesresolvers.le.acme.dnschallenge=true
- --certificatesresolvers.le.acme.dnschallenge.provider=digitalocean
- --certificatesresolvers.le.acme.email=${LE_DNS_EMAIL}
- --certificatesresolvers.le.acme.storage=/acme.json
labels:
- "traefik.enable=true"
# – ------------------------------------------------------
# INCLUDE: dynamic_conf.yml
# - redirect@file
# - secHeaders@file
- "providers.file.filename=/dynamic_conf.yml"
# – ------------------------------------------------------
# Middleware: traefik-auth
- "traefik.http.middlewares.traefik-auth.basicauth.users=${AUTH_USER}"
# – ------------------------------------------------------
# Router "traefik": http://traefik.nodnsapi.com -> Redirect
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.${DOMAIN}`)"
- "traefik.http.routers.traefik.middlewares=redirect@file"
# – ---------------------------------------------------- –
# Router "traefiks": https://traefik.nodnsapi.com -> Traefik Dashboard
- "traefik.http.routers.traefiks.entrypoints=https"
- "traefik.http.routers.traefiks.middlewares=traefik-auth,secHeaders@file"
- "traefik.http.routers.traefiks.rule=Host(`traefik.${DOMAIN}`)"
- "traefik.http.routers.traefiks.service=api@internal"
- "traefik.http.routers.traefiks.tls=true"
# ?~@~S ------------------------------------------------------
# Router "whoami-secure": To get Wildcard-Certs, no Service
- "traefik.http.routers.whoami-secure.service=noop@internal"
- "traefik.http.routers.whoami-secure.tls.certResolver=dns"
- "traefik.http.routers.whoami-secure.tls.domains[0].main=*.${DOMAIN}"
# ?~@~S ------------------------------------------------------
dozzle:
image: amir20/dozzle:latest
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data/acme.json:/acme.json
- ./data/traefik.yml:/traefik.yml:ro
- ./data/dynamic_conf.yml:/dynamic_conf.yml
labels:
- "traefik.enable=true"
# Redirect to HTTPS
- "traefik.http.routers.dozzle.entrypoints=http"
- "traefik.http.routers.dozzle.rule=Host(`dozzle.${DOMAIN}`)"
- "traefik.http.routers.dozzle.middlewares=redirect@file"
# Real Service
- "traefik.http.routers.dozzles.entrypoints=https"
- "traefik.http.routers.dozzles.middlewares=traefik-auth"
- "traefik.http.routers.dozzles.rule=Host(`dozzle.${DOMAIN}`)"
- "traefik.http.routers.dozzles.tls.certresolver=dns"
- "traefik.http.routers.dozzles.tls=true"
whoami:
image: "traefik/whoami"
scale: 3
networks:
- proxy
labels:
- "traefik.enable=true"
# Redirect to HTTPS
- "traefik.http.routers.whoami.entrypoints=http"
- "traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)"
- "traefik.http.routers.whoami.middlewares=redirect@file"
# Real Service
- "traefik.http.routers.whoamis.entrypoints=https"
- "traefik.http.routers.whoamis.middlewares=traefik-auth"
- "traefik.http.routers.whoamis.rule=Host(`whoami.${DOMAIN}`)"
- "traefik.http.routers.whoamis.tls.certResolver=dns"
- "traefik.http.routers.whoamis.tls=true"
networks:
proxy:
external: true
EOF
finally, we need to create the network
docker network create proxy
and we are ready to go.
Check Config
you can build the config and confirm that your variables from the .env file got applied
docker compose convert
docker compose up
docker compose up
Browse to
Any Comments ?
sha256: 623236f3c227b30d0355adb7a990520536fa67eb48ff77d0262336da9822e5a4