Auf der Seite https://goneuland.de/traefik-v2-3-reverse-proxy-mit-crowdsec-im-stack-einrichten bin ich auf eine Anleitung zum Thema Letsencrypt-Zertifikate für einen eigenen Webserver unter Ubuntu gekommen.
Hierzu wurde Traefik als Docker-Container verwendet. Dabei wird zur Sperrung von unwerwünschten IP-Adressen auf den Datenbestand von https://www.crowdsec.net/ zugegriffen. Wenn die aktuelle zugreifende IP darin enthalten ist, wird die Abfrage nicht von Traefik an den Webserver weitergeleitet.
Informationen zu Traefik sind auf der offiziellen Projektseite https://traefik.io/traefik zu finden.
Am Ende dieses Beitrages finden Sie Downloads mit Textdateien mit den zusammgefassten Befehlen.
Zum besseren Verständnis würde ich Ihnen für die erste Einrichtung aber empfehlen, die Schritte manuell einzeln wie unten ausgeführt durchzuführen.
Nachfolgend die Beschreibung meiner Vorgehensweise auf einem Raspberry Pi 4:
Voraussetzungen
- Domain die beim Aufruf auf unseren Proxy weiterleitet
Wir benötigen eine Domain, die auf unseren Router per DynDNS weitergeleitet wird.
Ich bekomme von meinem Provider eine feste IP-Adresse zugewiesen und konnte bei www.netbeat.de meinen Domainnamen direkt dieser IP-Adresse zuweisen.
Falls Sie keine feste IP-Adresse erhalten, müssen Sie mit der Methode DynDNS arbeiten. Ein kostenloser Weg wäre folgende Vorgehensweise:
Ich habe hierzu auf den kostenlosen Dienst von IPv64.net zugegriffen und mir auf der Seite
https://ipv64.net/account.php die Domäne demo.ipv64.net angelegt.
Wie man den Router DNS-fähig bekommt, erhält man auf der Seite https://ipv64.net/dyndns_helper gleich zur soeben erstellten Domain angezeigt. - Rechner auf dem ein Linux als Betriebssystem läuft
Ich habe hierzu einen Rasperry Pi 4 verwendet. Das passende Betriebssystem kann auf der Seite https://www.raspberrypi.com/software/operating-systems/ heruntergeladen werden. Bitte beachten, dass derzeit von Docker nur die 32-Bit-Variante unterstützt wird. Es genügt, die OS-Light-Version. Da ich mich manchmal auch direkt an meinem Raspi 4 anmelde um ihn als PC-Ersatz zu verwenden, läuft bei mir die Desktop-Variante. - Dockerinstallation auf dem Raspberry
Zur Installation von Docker habe ich die Anleitung auf der Seite
https://docs.docker.com/engine/install/raspberry-pi-os/#install-using-the-repository verwendet und in der Kommandozeile folgende Befehle ausgeführt:
(Das für Version 1 benötigte docker-compose habe ich weggelassen, da es veraltet ist.
Bei Bedarf kann es mit sudo apt install docker-compose-plugin installiert werden.)
Ablauf der Installation von Docker
Das offizielle Docker-Repository zu den Paketquellen hinzufügen
(die mit dem #-Zeichen markierten Zeilen stellen nur Kommentare dar und müssen nicht in der Konsole eingegeben werden !)
# Inhalt von docker_install.txt
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/raspbian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Set up Docker's APT repository:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/raspbian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
Damit Docker auch ohne root-Rechte gestartet werden kann, müssen wir dem aktuellen Benutzer der Gruppe docker zuweisen.
sudo usermod -aG docker $USERfalls die Gruppe docker noch nicht vorhanden ist, kann diese mit folgendem Aufruf erzeugt werden:
sudo groupadd dockerDamit die Zuordnung wirksam wird, muss der aktuelle Benutzer einmal ab- und wieder angemeldet werden. Auch ein reboot bewirkt den gleichen Effekt.
Anschließend sollten wir uns problemlos die installierte Docker-Version anzeigen können:
docker versionEinrichtung des Linux-Kommandos „tree“
Dieser Befehl ist zum Ablauf von Docker nicht notwendig. Er dient nur dem Zweck, die Verzeichnisse übersichtlich darzustellen damit Sie Ihren Installationsstand mit meiner Anleitung vergleichen können
sudo apt install treeAnlegen der Verzeichnisstruktur
Ich möchte die Installation auf dem Raspi in das Verzeichnis /srv/web legen.
Nun melden wir uns mittels ssh auf dem Raspberry Pi an und führen folgende Befehle auf der Eingabezeile durch:
# Hauptverzeichnis erstellen und zusätzliche Unterordner in 'crowdsec' erstellen
#Mein Benutzername lautet pi - ggf. mmüssen Sie natürlich Ihren abweichenden Benutzernamen verwenden
sudo mkdir /srv
sudo chown pi:root /srv
mkdir -p /srv/web/{traefik,html/demo,var/log,php,crowdsec/{config,data},config}
# .env Datei im Hauptverzeichnis erstellen
touch /srv/web/.env
# Umgebungsspezifische .env Dateien in 'config' erstellen
touch /srv/web/config/{crowdsec.env,traefik.env,traefik-crowdsec-bouncer.env}
# Zusätzliche Dateien in 'traefik' erstellen und Zugriffsrechte für bestimmte Dateien festlegen
touch /srv/web/traefik/{acme_letsencrypt.json,traefik.yml,dynamic_conf.yml,tls_letsencrypt.json}
#Zugriffsrechte aus json-Datei passend setzen, damit die Letsencrypt-Zertifikate erstellt werden
sudo chmod 600 /srv/web/traefik/{acme_letsencrypt.json,tls_letsencrypt.json}
#Verzeichnisstruktur anzeigen lassen und prüfen
tree -L 2 -a /srv/web/
Das Ergebnis sollte folgende Struktur ergeben:

Exkurs: Minimalversion von Traefik
Um Traefik als Reversproxy einzurichten genügt für eine Minimalversion eine docker-compose.yaml mit folgendem Inhalt:
services:
traefik:
image: "traefik:v3.0"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=test@gmx.de"
#Um Sperre duch Fehlversuche zu vermeiden, anfangs den Testserver von LetsEncrypt eintragen
#- "--certificatesresolvers.myresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
expose:
# traefik dashboard port
- 8080
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.demo.ipv64.net`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=myresolver"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$fMgwWnWq$$9lSqU1k0nWhLE0NF.eFIS0"
# Erzeugung Kennwort mit echo $(htpasswd -nb admin 'traefik!admin!2024')
# vorher das Paket apache2-util installieren: apt update && apt install apache2-utils
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
restart: "always"
networks:
default:
name: webproxyBeachten Sie den Hinweis zur Verwendung des Testservers von Letsencrypt. Nachdem der Bezug vom Testserver funktioniert, können Sie auf den Echt-Server umschalten. Dieser sperrt nämlich aus Sicherheitsgründen die Kommunikation nach einer bestimmten Anzahl von Fehlversuchen für eine gewissen Zeitspanne. Zum Test als Zeile 17 aktivieren und Zeile 18 auskommentieren.

Die Angabe zur Domain und E-Mail-Adresse sowie die Zugangsdaten bitte auf Ihre Verhältnisse anpassen.
Nach dem Start mittels docker compose up dauert es ein paar Minuten, bis im Unterverzeichnis letsencrypt die json-Datei gefüllt wird.
Nun kann im Browser durch Aufruf der angegeben Domain das Traefik-Dashboard aufgerufen werden und die Übertragung wird mittels HTTPS-Verschlüsselung gesichert.
Nun kommen wir aber zur etwas ausführlicheren Variante:
Anlegen der Konfigurationsdateien
Variablen zur Verwendung in der docker-compose.yaml
Hier werden die einzelnen Container und Services benannt
nano /srv/web/.env
# Service Crowdsec
SERVICES_CROWDSEC_CONTAINER_NAME=crowdsec
SERVICES_CROWDSEC_HOSTNAME=crowdsec
SERVICES_CROWDSEC_IMAGE=crowdsecurity/crowdsec
SERVICES_CROWDSEC_IMAGE_VERSION=latest
SERVICES_CROWDSEC_NETWORKS_CROWDSEC_IPV4=172.31.254.254
# Service Traefik
SERVICES_TRAEFIK_CONTAINER_NAME=traefik
SERVICES_TRAEFIK_HOSTNAME=traefik
SERVICES_TRAEFIK_IMAGE=traefik
#SERVICES_TRAEFIK_IMAGE_VERSION=2.10
SERVICES_TRAEFIK_IMAGE_VERSION=v3.0
SERVICES_TRAEFIK_LABELS_TRAEFIK_HOST=`demo.ipv64.net`
SERVICES_TRAEFIK_NETWORKS_CROWDSEC_IPV4=172.31.254.253
SERVICES_TRAEFIK_NETWORKS_PROXY_IPV4=172.30.255.254
# Service Traefik Crowdsec Bouncer
SERVICES_TRAEFIK_CROWDSEC_BOUNCER_CONTAINER_NAME=traefik_crowdsec_bouncer
SERVICES_TRAEFIK_CROWDSEC_BOUNCER_HOSTNAME=traefik-crowdsec-bouncer
SERVICES_TRAEFIK_CROWDSEC_BOUNCER_IMAGE=fbonalair/traefik-crowdsec-bouncer
SERVICES_TRAEFIK_CROWDSEC_BOUNCER_IMAGE_VERSION=latest
SERVICES_TRAEFIK_CROWDSEC_BOUNCER_NETWORKS_CROWDSEC_IPV4=172.31.254.252
# Netzwerkeinstellungen
NETWORKS_PROXY_NAME=proxy
NETWORKS_PROXY_SUBNET_IPV4=172.30.0.0/16
NETWORKS_CROWDSEC_NAME=crowdsec
NETWORKS_CROWDSEC_SUBNET_IPV4=172.31.0.0/16
# Service ip64.net
SERVICES_IPV64_CONTAINER_NAME= ip64
SERVICES_IPV64_HOSTNAME=demo-ipv64-net
SERVICES_IPV64_DOMAIN_DEMO="`demo.ipv64.net`"
SERVICES_IPV64_NETWORKS_CROWDSEC_IPV4=172.31.254.251
Definiton der Dienste, Netzwerke und Verzeichnisse
nano /srv/web/docker-compose.yaml
# Die Version der Docker Compose-Datei. Hier verwenden wir Version 3.9.
version: "3.9"
# Der Beginn des 'services' Abschnitts.
services:
# Name des Services.
crowdsec:
# Der Name des Containers, der aus diesem Service erzeugt wird
container_name: ${SERVICES_CROWDSEC_CONTAINER_NAME}
# Umgebungsvariablen für den Container.
env_file: ./config/crowdsec.env
# Hostname des CrowdSec-Containers, kann über eine Umgebungsvariable angepasst werden.
hostname: ${SERVICES_CROWDSEC_HOSTNAME}
# Gesundheitsüberprüfung für den CrowdSec-Service
healthcheck:
test: ["CMD", "cscli", "version"]
interval: 10s
timeout: 2s
retries: 5
start_period: 10s
# Docker-Image, das für den Container verwendet wird.
image: ${SERVICES_CROWDSEC_IMAGE}:${SERVICES_CROWDSEC_IMAGE_VERSION}
# Netzwerke, zu denen der Container gehört.
networks:
crowdsec:
# Feste IPv4-Adresse vergeben.
ipv4_address: ${SERVICES_CROWDSEC_NETWORKS_CROWDSEC_IPV4}
# Restart-Strategie für den Container.
restart: unless-stopped
# Sicherheitsoptionen für den Container.
security_opt:
- no-new-privileges=true
# Volumes, die vom Container verwendet werden.
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/log/auth.log:/var/log/auth.log:ro
- ./var/log/traefik:/var/log/traefik:ro
- ./crowdsec/config:/etc/crowdsec
- ./crowdsec/data:/var/lib/crowdsec/data
- ./var/log/crowdsec/:/var/log/
- ./var/log/ip64net/:/var/log/ip64net
# Der Name des Service
traefik:
# Der Name des Containers, der aus diesem Service erzeugt wird
container_name: ${SERVICES_TRAEFIK_CONTAINER_NAME}
# Diese Option sorgt dafür, dass der Traefik-Service erst gestartet wird,
# nachdem der Crowdsec-Service healthy ist
depends_on:
crowdsec:
condition: service_healthy
# Umgebungsvariablen für den Container.
env_file: ./config/traefik.env
# Hostname des Traefik-Containers, kann über eine Umgebungsvariable angepasst werden.
hostname: ${SERVICES_TRAEFIK_HOSTNAME}
# Gesundheitsüberprüfung für den Traefik-Service
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
# Das Docker-Image, das für diesen Service verwendet wird
# Version kann über eine Umgebungsvariable angepasst werden.
image: ${SERVICES_TRAEFIK_IMAGE}:${SERVICES_TRAEFIK_IMAGE_VERSION}
# Docker Labels für den Traefik-Service. Diese werden für die Traefik-Konfiguration verwendet
labels:
traefik.docker.network: proxy
traefik.enable: "true"
traefik.http.routers.traefik.entrypoints: websecure
traefik.http.routers.traefik.middlewares: default@file,traefikAuth@file
traefik.http.routers.traefik.rule: Host(${SERVICES_TRAEFIK_LABELS_TRAEFIK_HOST})
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.tls: "true"
traefik.http.routers.traefik.tls.certresolver: http_resolver
traefik.http.services.traefik.loadbalancer.sticky.cookie.httpOnly: "true"
traefik.http.services.traefik.loadbalancer.sticky.cookie.secure: "true"
traefik.http.routers.pingweb.rule: PathPrefix(`/ping`)
traefik.http.routers.pingweb.service: ping@internal
traefik.http.routers.pingweb.entrypoints: websecure
# Die Netzwerke, zu denen dieser Service gehört
networks:
crowdsec:
# IPv4-Adresse des CrowdSec Containers im Traefik-Netwerk: crowdsec
ipv4_address: ${SERVICES_TRAEFIK_NETWORKS_CROWDSEC_IPV4}
proxy:
# IPv4-Adresse des Traefik Containers im Traefik-Netwerk: proxy
ipv4_address: ${SERVICES_TRAEFIK_NETWORKS_PROXY_IPV4}
# Die Ports, die diesem Service zugeordnet sind
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
# Der Restart-Policy dieses Service
restart: unless-stopped
# Sicherheitsoptionen für diesen Service
security_opt:
- no-new-privileges:true
# Die Volumes, die diesem Service zugeordnet sind
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./var/log/traefik/:/var/log/traefik/
- ./traefik/traefik.yml:/traefik.yml:ro
- ./traefik/acme_letsencrypt.json:/acme_letsencrypt.json
- ./traefik/tls_letsencrypt.json:/tls_letsencrypt.json
- ./traefik/dynamic_conf.yml:/dynamic_conf.yml
# Definition des Traefik CrowdSec Bouncer-Dienstes
traefik_crowdsec_bouncer:
# Der Name des Containers, der aus diesem Service erzeugt wird
container_name: ${SERVICES_TRAEFIK_CROWDSEC_BOUNCER_CONTAINER_NAME}
# Abhängigkeitsdefinition: Dieser Service wird erst gestartet, wenn der Crowdsec-Service als "healthy" gekennzeichnet ist
depends_on:
crowdsec:
condition: service_healthy
# Pfad zur .env-Datei für den Traefik CrowdSec Bouncer-Dienst
env_file: ./config/traefik-crowdsec-bouncer.env
# Der Hostname des Containers, kann über eine Umgebungsvariable angepasst werden
hostname: ${SERVICES_TRAEFIK_CROWDSEC_BOUNCER_HOSTNAME}
# Docker-Image, das für den Container verwendet wird. Die Version kann über eine Umgebungsvariable angepasst werden
image: ${SERVICES_TRAEFIK_CROWDSEC_BOUNCER_IMAGE}:${SERVICES_TRAEFIK_CROWDSEC_BOUNCER_IMAGE_VERSION}
# Netzwerke, zu denen der Container gehört
networks:
crowdsec:
# Feste IPv4-Adresse für den Container in diesem Netzwerk
ipv4_address: ${SERVICES_TRAEFIK_CROWDSEC_BOUNCER_NETWORKS_CROWDSEC_IPV4}
# Restart-Strategie für den Container. 'unless-stopped' bedeutet, dass der Container immer neu gestartet wird, es sei denn, er wird manuell gestoppt
restart: unless-stopped
volumes:
- ./var/log/crowdsec_bouncer:/var/log
ipv64:
build:
dockerfile: dockerfile_php8
context: php
hostname: ${SERVICES_IPV64_HOSTNAME}
container_name: ${SERVICES_IPV64_CONTAINER_NAME}
restart: unless-stopped
depends_on:
traefik:
condition: service_healthy
networks:
crowdsec:
# Feste IPv4-Adresse für den Container in diesem Netzwerk
ipv4_address: ${SERVICES_IPV64_NETWORKS_CROWDSEC_IPV4}
labels:
traefik.enable: "true"
traefik.docker.network: $NETWORKS_CROWDSEC_NAME
traefik.http.routers.ipv64.entrypoints: websecure
traefik.http.routers.ipv64.rule: "HOST($SERVICES_IPV64_DOMAIN_DEMO)"
traefik.http.routers.ipv64.tls.certresolver: http_resolver
traefik.http.routers.ipv64.tls: "true"
volumes:
- ./html/demo:/var/www/html
- ./var/log/ip64net:/var/log #log-files
# Definition der Netzwerke, die von den Services verwendet werden
networks:
# Definition des 'proxy' Netzwerks
proxy:
# Der Name des Netzwerks, kann über eine Umgebungsvariable angepasst werden
name: ${NETWORKS_PROXY_NAME}
# Der Treiber, der für das Netzwerk verwendet wird, hier ist es 'bridge'
driver: bridge
# IP-Adress-Management-Konfiguration (IPAM)
ipam:
# Konfiguration des IP-Adress-Subnetzes für das Netzwerk
config:
- subnet: ${NETWORKS_PROXY_SUBNET_IPV4}
# Wenn 'attachable' auf 'true' gesetzt ist, können Standalone-Container an dieses Netzwerk angehängt werden
attachable: true
# Definition des 'crowdsec' Netzwerks
crowdsec:
# Der Name des Netzwerks, kann über eine Umgebungsvariable angepasst werden
name: ${NETWORKS_CROWDSEC_NAME}
# Der Treiber, der für das Netzwerk verwendet wird, hier ist es 'bridge'
driver: bridge
# IP-Adress-Management-Konfiguration (IPAM)
ipam:
# Konfiguration des IP-Adress-Subnetzes für das Netzwerk
config:
- subnet: ${NETWORKS_CROWDSEC_SUBNET_IPV4}
# Wenn 'attachable' auf 'true' gesetzt ist, können Standalone-Container an dieses Netzwerk angehängt werden
attachable: true
Konfiguration des Containers crowdsec
nano /srv/web/config/crowdsec.env
PGID="1000"
COLLECTIONS="crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/whitelist-good-actors crowdsecurity/apache2"Konfiguration des Containers crowdsec-bouncer
sudo nano /srv/web/config/traefik-crowdsec-bouncer.env
# Access-Token damit Bouncer und CrowdSec kommunizieren können
CROWDSEC_BOUNCER_API_KEY=lXIL3TtsLzypyp3Vdpclszh7iVj4KjkZGUlKhFAhR4E
# Hostname mit richtigem Port von CrowdSec
#CROWDSEC_AGENT_HOST=${SERVICES_CROWDSEC_HOSTNAME}:8080
# Bei Debian funktioniert ${SERVICES_CROWDSEC_HOSTNAME} nicht
# In Debian müssen wir ${SERVICES_CROWDSEC_HOSTNAME} durch einen Wert ersetzen:
CROWDSEC_AGENT_HOST=crowdsec:8080
# alternativ:
# CROWDSEC_AGENT_HOST=172.31.254.254:8080Leere Datei erzeugen, welche für die Erzeugung des Containers benötigt wird
touch /srv/werb/config/traefik.envDefinition der Logdateien, deren Ereignisse mit Crowdsec ausgewertet werden
nano /srv/web/crowdsec/config/acquis.yaml
#filenames:
# - /var/log/nginx/*.log
# - ./tests/nginx/nginx.log
#this is not a syslog log, indicate which kind of logs it is
#labels:
# type: nginx
#----
filenames:
- /var/log/auth.log
- /var/log/syslog
labels:
type: syslog
---
filenames:
- /var/log/ip64net/apache2/*.log
labels:
type: apache2
---
filenames:
- /var/log/traefik/*.log
labels:
type: traefik
---
filenames:
- /var/log/crowdsec/*.log
labels:
type: crowdsec
---
Fixe Einstellungen für den Betrieb von Traefik
Bitte an zwei Stellen die E-Mail-Adresse Testmail@gmx.de durch Ihre E-Mail-Adresse ersetzen. Diese wird von Letsencrypt verwendet, um notfalls wichtige Informationen an den Zertifikatsinahber zu senden.
nano /srv/web/traefik/traefik.yml
api:
dashboard: true
metrics:
prometheus:
addRoutersLabels: true
certificatesResolvers:
http_resolver:
acme:
email: "Testmail@gmx.de"
storage: "acme_letsencrypt.json"
#Testserver:
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
#Normaler Server
#caServer: "https://acme-v02.api.letsencrypt.org/directory"
httpChallenge:
entryPoint: web
tls_resolver:
acme:
email: "Testmail@gmx.de"
storage: "tls_letsencrypt.json"
#Testserver:
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
#Normaler Server
#caServer: "https://acme-v02.api.letsencrypt.org/directory"
tlsChallenge: {}
entryPoints:
ping:
address: ':88'
web:
address: ':80'
http:
redirections:
entryPoint:
to: websecure
scheme: https
middlewares:
- traefik-crowdsec-bouncer@file
websecure:
address: ':443'
http:
middlewares:
- traefik-crowdsec-bouncer@file
proxyProtocol:
#insecure: true
trustedIPs:
- 10.0.0.0/8
- 172.30.0.0/16
- 172.31.0.0/16
- 192.168.178.0/16
forwardedHeaders:
#insecure: true
trustedIPs:
- 10.0.0.0/8
- 172.30.0.0/16
- 172.31.0.0/16
- 192.168.178.0/16
ping:
entryPoint: "ping"
global:
checknewversion: true
sendanonymoususage: false
experimental:
plugins:
real-ip:
moduleName: github.com/Paxxs/traefik-get-real-ip
version: "v1.0.2"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: proxy
file:
filename: "./dynamic_conf.yml"
watch: true
providersThrottleDuration: 10s
log:
level: "INFO"
filePath: "/var/log/traefik/traefik.log"
#Logrotate-Einstellungen
maxAge: 30
maxBackups: 12
accessLog:
filePath: "/var/log/traefik/access.log"
bufferingSize: 100
Dynamische Einstellungen für den Betrieb von Traefik
Ddiese werden im laufenden Betrieb regelmäßig neu eingelesen.
Dadurch können also Konfigurationen ohne Neustart des Containers erfolgen.
sudo nano /werv/web/traefik/dynamic_conf.yml
tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
http:
middlewares:
default:
chain:
middlewares:
- default-security-headers
- gzip
default-security-headers:
headers:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
customFrameOptionsValue: "SAMEORIGIN"
gzip:
compress: {}
traefik-crowdsec-bouncer:
forwardauth:
address: http://traefik-crowdsec-bouncer:8080/api/v1/forwardAuth
trustForwardHeader: true
real-ip-cf:
plugin:
real-ip:
Proxy:
- proxyHeadername: "*"
realIP: Cf-Connecting-Ip
OverwriteXFF: true
# A basic authentification middleware, to protect the Traefik dashboard to anyone except myself
# Use with traefik.http.routers.myRouter.middlewares: "traefikAuth@file"
traefikAuth:
basicAuth:
users:
- "admin:$apr1$fMgwWnWq$9lSqU1k0nWhLE0NF.eFIS0"
# Erzeugung mit echo $(htpasswd -nb admin 'traefik!admin!2024')
# vorher das Paket apache2-util installieren: apt update && apt install apache2-utils
Icon für die Test-Webseite. Bitte im Verzeichnis
/srv/web/html/demo/favicon.ico
speichern
Icons können am einfachsten kostenlos auf der Seite
https://www.ionos.de/tools/favicon-generator
erzeugt werden.
Definition zur Erzeugung eines Containers mit Apache und PHP 7
sudo nano /srv/web/php/dockerfile_php7
FROM php:7.2-apache
#RUN docker-php-ext-install mysqli pdo pdo_mysql
#RUN a2enmod userdir
#RUN a2enmod rewrite
#ADD userdir.conf /etc/apache2/mods-enabled/
RUN echo "ServerName intranet" >> /etc/apache2/apache2.confDefinition zur Erzeugung eines zweiten Containers mit Apache und PHP 8
sudo nano /srv/web/php/dockerfile_php8
FROM php:8.3-apache
#RUN docker-php-ext-install mysqli pdo pdo_mysql
#RUN a2enmod userdir
#RUN a2enmod rewrite
#ADD userdir.conf /etc/apache2/mods-enabled/
RUN echo "ServerName web8" >> /etc/apache2/apache2.confNach Ausführung der genannten Schritte sollte sich folgende Datei- und Verzeichnisstruktur ergeben:

In nachstehender ZIP-Datei finden Sie eine Sicherung des gezeigten Verzeichnisses. Die Angaben in den Konfigurationsdateien müssen natürlich noch auf Ihre Bedürfnisse umgestellt werden.
Dateirechte korrekt setzen
Nun setzen wir sicherheitshalber nochmal die Dateizugriffsrechte in unserem Verzeichnis auf den lokalen User (bei mir pi) und der Gruppe root:
sudo chown pi:root /srv/web -RContainer erstmalig erzeugen
Wir gehen in unser Verzeichnis und testen die Definitionsdatei für docker compose:
cd /srv/web
docker compose configWenn uns jetzt der vollständige Dateiinhalt ohne Fehlermeldung angezeigt wird, können wir mit dem ersten Start fortfahren
docker compose up -d
Nun werden die Container erzeugt und im Hintergrund gestartet. Beim ersten Aufruf dauert der Vorgang etwas länger, da die Images vom Docker-Hub heruntergeladen und daraus die Container gebaut werden. Die Ergebnisse der dabei angewandten Zwischenschritte werden von Docker lokal gespeichert und müssen erst nach Änderungen an den Images oder den dockkerfiles erneut gebaut werden.
Wenn der Vorgang erfolgreich war, werden die Container mit „gestarted“ oder „healthy“ markiert. Die gerade aktiven Container können Sie sich anzeigen lassen mit dem Kommando:
docker psWie müssen aber erst noch diverse Einstellungen vornehmen und beenden deshalb alle Container mit der Anweisung:
docker compose downAPI-Key für Crowdsec-bouncer erzeugen
Um von Crowdsec aktuelle Datenbanken zu lesen, benötigen wir einen API-Key. Hieru starten wir manuell nur den Crowdsec-Container und lassen eine bestimmte Anweisung darin laufen:
# Den Container im Hintergrund laufen lassen
docker compose up crowdsec -d
# Generierung des API-Key
docker compose exec -t crowdsec cscli bouncers add traefik-crowdsec-bouncer
# danach den Crowdsec-Container wieder beenden
docker compose downEs erscheint eine Anzeige mit dem generierten API-Key:

Diesen API-Key übernehmen wir in die Zwischenablage und um ihn in die Konfigurationsdatei einzutragen. Um Probleme beim Speichern zu vermeiden, gleich nochmal die Dateirechte auch für die neu erzeugten Dateien aktualisieren.
sudo chown pi:root /srv/web/ -R
sudo nano /srv/web/config/traefik-crouwdsec-bouncer.envund in die erste Zeile bei CROWDSEC_BOUNCER_API_KEY= den API-Key hinzufügen

Jetzt können Sie die Logging-Funktion des crowdsec-sontainers festlegen. Wenn er in eine Log-Datei schreiben soll die Datei /srv/web/crowdsec/config/config.yaml öffen und im Abschnitt common den Eintrag log_media von stdout auf file ändern:

Jetzt sollte nochmal die Datei /srv/crowdsec/config/acquis.yaml auf Übereinstimmung mit oben gezeigten Inhalt überprüft werden.
Letsencrypt-Zertifikat für den Traefik-Server erzeugen
Nun erzeugen wir ein durch Letsencrypt erzeugtes Zertifikat für unseren Server.
Hierzu muss der Aufruf unserer Domain auf unserem Raspi weitergeiletet werden. Dies haben wir ja weiter oben durch die Einrichtung der Verbindung zu IP64.net auf unserem Router erledigt. Weiterhin haben wir zur Speicherung der LetsEncrypt-Daten die beiden json-Datein zur Verfügung gestellt und mit der Zugriffstufe 0600 versehen.
sudo chmod 0600 /srv/web/traefik/*letsencrypt.jsonZuvor müssen Sie in der Datei /srv/web/traefik/traefik.yaml in den zwei Resolvern jeweils im Abschnitt acme die Angaben der E-Mail-Adresse auf eine gültige E-Mail-Adresse ändern.
Starten Sie die Container im Hintergund mit dem Kommando:
cd /srv/web
docker compose up -d&Nach einer kurzen Zeitspanne von wenigen Minuten sollten alle Container als „Healthy“ oder „gestartet“ erscheinen. Die können Sie auch mit dem Befehldocker ps kontrollieren.
Im Fehlerfall stoppen Sie durch Eingabe von docker compose down alle Container.
Ob der Bezug des Zertifikates funkionierte, können Sie z. B. in der Datei /srv/web/var/log/traefik/traefik.log erkennen.
sudo cat /srv/werb/var/log/traefik/traefig.logBei Erfolg finden Sie Angaben zum Zertifikat in der Datei /srv/web/traefik/acme_letsencrypt.json .
sudo cat /srv/web/traefik/acme_letsencrypt.json