There are several solutions for Docker to simplify letsencrypt usage on your sites, for example docker-letsencrypt-proxy-companion, but I wanted to find something easier and newer than another one Nginx, using as a proxy.
Many posts, for example this one, are dedicated to proxying HTTPS traffic through Traefik, and Traefik looks more interesting and fresh. So, here I’ll describe how do I use it on my servers.
So, open the console, cd to your docker-compose app directory and run the following
mkdir traefik && cd traefik
touch {traefik.toml,acme.json} && chmod 600 acme.json
traefik.toml file content
Before running, you have to edit traefik.toml file, for example, like this:
logLevel = "ERROR"
defaultEntryPoints = ["http","https"]
[accessLog]
filePath = "/dev/stdout"
[traefikLog]
filePath = "/dev/stdout"
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "mszuyev.xyz"
watch = true
exposedbydefault = false
[acme]
email = "[email protected]"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
Note, that we don’t use [entryPoints.http.redirect] section here, below I’ll explain this moment.
docker-compose.yaml entry for Traefik
traefik:
image: traefik:alpine
container_name: traefik
command: --configFile=/traefik.toml
restart: unless-stopped
networks:
- main
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/traefik.toml:/traefik.toml
- ./traefik/acme.json:/acme.json
labels:
- "traefik.enable=false"
docker-compose.yaml part for proxied services
I use Hugo as the platform of this very site and Nginx to serve some sites on my subdomains, so there were two services, that needed proxying. And, the docker-compose.yaml configuration is like this:
server:
image: nginx:alpine
container_name: nginx
restart: on-failure
working_dir: /etc/nginx/conf.d/
volumes:
- ./roots/www:/var/www_root:rw
- ./conf/nginx:/etc/nginx/conf.d:ro
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z0-9]+}.mszuyev.xyz"
- "traefik.port=80"
- "traefik.docker.network=main"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.headers.SSLForceHost=true"
- "traefik.frontend.priority=5"
entrypoint: [nginx-debug, '-g', 'daemon off;']
depends_on:
- php
networks:
- main
hugo:
build: conf/hugo
image: hugo
container_name: hugo
user: 1000:1000 # $(id -u):$(id -g)
restart: on-failure
working_dir: /hugo_sites/mszuyev
volumes:
- ./roots/www/hugo:/hugo_sites:rw
labels:
- "traefik.enable=true"
- "traefik.port=1313"
- "traefik.docker.network=main"
- "traefik.frontend.rule=Host:mszuyev.xyz, www.mszuyev.xyz"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.headers.SSLForceHost=true"
- "traefik.frontend.priority=10"
networks:
- main
Note that traefik.frontend.headers.SSLRedirect=true label is used to redirect any requests from HTTP to HTTPS. It is the alternative of using [entryPoints.http.redirect], but here we can decide on such redirects for each container separately.
In some cases we can get an infinite redirection loop HTTPS->HTTPS. I’ve got it on Cloudflare, and the only way to solve that problem was in changing SSL policy like this: