Traefik
Traefik is a reverse proxy encrypting traffic with Let's Encrypt certificates and is used to dispatch incoming requests to the right services in a secure and SSL-encrypted way.
Installation
The relevant installation steps comprise setting
environment variables in a .env
file. Thus, you need to create a hidden
file with the name .env
(including the '.') containing the following
environment variables:
ACME_EMAIL=your@mail.com
TRAEFIK_DOMAIN=your.dashboard.domain
BASIC_AUTH=your_dashboard_user:your_htpasswd_password
Additionally, we need the ACME configuration in the acme.json
file
The JSON file in which Traefik stores all relevant certificate information
needs to be secured with exactly the following user rights:
cd config
chmod 600 acme.json
Configuration
The docker-compose
file defines the Traefik service including all
relevant labels for proper configuration of our setup and connects it to
the internet-facing traefik_proxy network (no backend connectivity required).
Application
The first part of the Traefik configuration is pretty straightforward:
- defines the docker image to be downloaded from docker hub
- provides a name for our service (for easier recognition of the container and navigation e.g. in Portainer)
Then it gets a little more interesting:
- First, two entry points are defined for unencrypted http requests on port 80
(
web
) and for encrypted https requests on port 443 (web-secure
). - The
web
entrypoint is always re-directed toweb-secure
which is in the labels section below. Here, all requests matching all hosts coming in on port 80 are caught and redirected to theredirect-to-https
middleware. This middleware then redirects all traffic to https. - The we enable to provide the services via Docker at all and shares the
Docker sock on the local file system with the container. The Docker sock
is mapped into the container as a volume (see
volume
section). - Then we state that none of the services are proxied by default, but only those that we explicitly want to make visible on the internet (for example internal monitoring containers or databases, we do not want to expose to the internet by default) and define the network to be used for the proxied services.
Most important for the encryption is the configuration of the certificate
resolvers. We are using Let's Encrypt which is configured using the
config/acme.json
(see above). Additionally, we only need the e-mail
address for Let's Encrypt which is
read from the .env
file and set the TLS challenge to true.
All the rest of the configuration deals with enabling system logs and access logs and make them readable and persistent in the local file system of the host (realized via volumes).
---
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
command:
- --entrypoints.web.address=:80
- --entrypoints.web-secure.address=:443
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=traefik_proxy
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --api.dashboard=true
# for test purposes this is the let's encrypt staging server
# - --certificatesresolvers.default.acme.caserver=
# https://acme-staging-v02.api.letsencrypt.org/directory
- --certificatesresolvers.default.acme.email=${ACME_EMAIL}
- --certificatesresolvers.default.acme.storage=/config/acme.json
- --certificatesresolvers.default.acme.tlschallenge=true
- --log.filePath=/srv/docker/traefik/traefik.log
- --log.format=json
- --accesslog=true
- --accesslog.filePath=/srv/docker/traefik/access.log
- --accesslog.format=json
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime
- ./config:/config
- /srv/docker/traefik/access.log:/srv/docker/traefik/access.log
- /srv/docker/traefik/traefik.log:/srv/docker/traefik/traefik.log
labels:
- "traefik.enable=true"
# global redirect to https
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
# middleware redirect
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
# loadbalancer service
- "traefik.http.services.traefik.loadbalancer.server.port=80"
networks:
- traefik_proxy
ports:
- "80:80"
- "443:443"
restart: always
Dashboard
If you want to access the Traefik dashboard, then this can be configured as follows:
- We define the web-secure entrypoint for encrypted traffic (there is no need to do that for the unencrypted web entrypoint on port 80, since our Traefik configuration catches and redirects all unencrypted traffic to web-secure on port 443... see above).
- The router configuration tells Traefiki which domains shall be
routed to the container to display the dashboard content: here all
requests directed to the domain as configured in the environment
variable
TRAEFIK_DOMAIN
(e.g.dashboard.example.org
). - The encryption via Let's Encrypt is enabled via the corresponding labels with the default resolver. This is being handled via Traefik as defined in the certificate resolver configuration above (via ACME).
- The service needs to be enabled with
api@internal
for the dashboard. - Last, but not least, I would not want to publicly display the dashboard
data. Thus, I configure a basic HTTP authentication requiring to log in
with the user credentials as outlined in the
BASIC_AUTH
environment variable (this can be created on the command line withhtpasswd
).
# enable dashboard
# - "traefik.http.routers.api.entrypoints=web-secure"
# - "traefik.http.routers.api.rule=Host(`${TRAEFIK_DOMAIN}`)"
# - "traefik.http.routers.api.tls=true"
# - "traefik.http.routers.api.tls.certresolver=default"
# - "traefik.http.routers.api.service=api@internal"
# - "traefik.http.routers.api.middlewares=api-auth"
# - "traefik.http.middlewares.api-auth.basicauth.users=${BASIC_AUTH}"
Network
Last, but not least, we refer to the existing external networks... they need to exist as outlined here.
networks:
traefik_proxy:
external:
name: traefik_proxy