Traefik as a proxy

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: Cloudflare policy