Traefik Container mit https und Let's Encrypt
Ich bin mir noch nicht sicher, ob ich im Strahl kotzen möchte oder die Möglichkeiten des Modules bewundern soll. Es geht um den Docker Container Traefik🖹 zusammen mit Let's Encrypt🖹.
Es läuft so ziemlich direkt wenn man es einfach einbindet und da hinter ein paar normale Port 80 Webserver hat. Aber das ist wohl nichts, was man wirklich wollen sollte.
Die Doku vom Traefik selbst ist - naja sagen wir - unfangreich, kompakt und kompliziert. Und die Quellen für Lösungen sind alle unterschiedlich.
Eigens traefik.yml
Im ersten Schritt ersetze ich deshalb das globale Konfig File durch mein eigenes:
1global:
2 checkNewVersion: true
3 sendAnonymousUsage: false
4
5providers:
6 docker:
7 endpoint: "unix:///var/run/docker.sock"
8 exposedByDefault: false
9 swarmMode: false
10 network: web
11
12api:
13 insecure: false
14
15entryPoints:
16 web:
17 address: :80
18
19 websecure:
20 address: :443
21
22certificatesResolvers:
23 leresolver-prod:
24 acme:
25 email: XXXXXXXXXXXXXX
26 storage: /etc/traefik/acme/acme.json
27 tlsChallenge: {}
28
29 leresolver-dev:
30 acme:
31 email: XXXXXXXXXXXXXX
32 storage: /etc/traefik/acme/acme-stage.json
33 tlsChallenge: {}
34 caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
Wichtig war mir dabei:
exposedByDefault
auffalse
- 2 unterschiedliche Let's Encrypt Resolver
leresolver-prod
undleresolver-dev
- der Storage Pfad zum acme.json, so dass dieses auf ein Volume kann
Jetzt wird es sogar einfach, hier der Ausschnitt aus dem Docker Compose zum Start des Traefik Proxies:
1service:
2 proxy:
3 image: traefik:latest
4 restart: always
5 ports:
6 - "80:80"
7 - "443:443"
8 networks:
9 - web
10 volumes:
11 - type: bind
12 source: /var/run/docker.sock
13 target: /var/run/docker.sock
14 - acme:/etc/traefik/acme
15 - /root/traefik.yml:/etc/traefik/traefik.yml
16volumes:
17 acme:
Web-Server einbinden
Und zuletzt der komplizierte Teil mit dem Web-Server, https und sogar redirect von http auf https:
1service:
2 www:
3 image: mywww:latest
4 restart: always
5 networks:
6 - web
7 labels:
8 - traefik.enable=true
9 - traefik.http.routers.www.rule=Host(`www.js-home.org`)
10 - traefik.http.routers.wwws.rule=Host(`www.js-home.org`)
11 - traefik.http.services.wwws.loadbalancer.server.port=80
12 - traefik.http.routers.www.entrypoints=web
13 - traefik.http.routers.wwws.entrypoints=websecure
14 - traefik.http.routers.wwws.tls=true
15 - traefik.http.routers.wwws.tls.certresolver=leresolver-prod
16 - "traefik.http.routers.wwws.tls.domains[0].main=www.js-home.org"
17 - traefik.http.routers.www.middlewares=redirect-to-https
18 - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
19 - traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true
20 volumes:
21 - apache-logs:/logs
22volumes:
23 apache-logs:
Gehen wir die Labels zeilenweise durch, denn die sind hier relevant:
1traefik.enable = true
Da im traefik.yml
Konfigfile global exposedByDefault
abgeschaltet ist, muss nun explizit
jeder Service/Container für Traefik aktiviert werden. Das ist sauberer und bringt nicht aus
Versehen einen Service online.
1traefik.http.routers.www.rule = Host(`www.js-home.org`)
2traefik.http.routers.wwws.rule = Host(`www.js-home.org`)
3traefik.http.services.wwws.loadbalancer.server.port = 80
Wird wegen der http nach https Umleitungsmagie benötigt. Es wird für einen Router "www" und einen Router "wwws" die Rule zum Hostname gesetzt. Einen Port sollte man auch setzen, Port 80. Würde zwar automatisch gesetzt, aber falls mal ein anderer Port benötigt wird, dann steht das schonmal dort.
Der Servicename "wwws" ist passend zum Router "wwws" gesetzt.
Grundsätzlich sind aber die Namen frei zu vergeben, solange sie zusammen passen und (vermutlich) eindeutig für die eine Traefik Instanz sind.
1traefik.http.routers.www.entrypoints = web
2traefik.http.routers.wwws.entrypoints = websecure
So weiß Traefik, welche Entrypoints es auf traefik.yml
für die beiden Router "www" und "wwws" nutzen
soll, eben "web" (Port 80) und "websecure" (Port 443). Hat man nur
einen Router kann man sich diese Angabe sparen, dann macht das Traefik
selbst.
1traefik.http.routers.wwws.tls = true
2traefik.http.routers.wwws.tls.certresolver = leresolver-prod
3traefik.http.routers.wwws.tls.domains[0].main = www.js-home.org
Jetzt wird es spannend für HTTPS/TSL: Das wird für den Router "wwws" aktiviert und
der certresolver
leresolver-prod
aus traefik.yml
gewählt. Ich habe in dem Konfigfile
2 Stück definiert, leresolver-prod
und leresolver-dev
. Let's Encrypt bietet das Staging API 1 um
seinen Server zu testen bevor es ein echtes Zertifikat gibt. D.h. zu Anfang, bis alles läuft, sollte man hier
leresolver-dev
setzen um nicht in ein Rate-Limit zu laufen und dadurch
Fehler beim Testen zu bekommen.
Anführungszeichen sind bei solche Labelnamen wohl nötig, fehlen hier aber absichtlich.
1traefik.http.middlewares.redirect-to-https.redirectscheme.scheme = https
2traefik.http.middlewares.redirect-to-https.redirectscheme.permanent = true
3traefik.http.routers.www.middlewares = redirect-to-https
Und hier liegt die Magie des Redirect von http auf https und was keine Doku so richtig erklären wollte (die Reihenfolge ist übrigens egal, deshalb hier jetzt anders als oben):
Es wird eine Middleware "redirect-to-https" definiert (das ist erstmal nur ein Name, völlig
egal welcher). Wichtig ist das scheme
und permanent
2. Es besagt so,
dass alles zu https umgeleitet werden soll.
Es wird im Router "www" die Liste der Middlewares festgelegt, also "redirect-to-https".
Fertig!
(wäre es einfach, könnte es jeder!)
-
Let's Encrypt Staging: https://letsencrypt.org/docs/staging-environment/🖹 ↩︎
-
Traefik Redirect Scheme: https://doc.traefik.io/traefik/middlewares/http/redirectscheme/🖹 ↩︎