Architecture technique actuelle
Porte d'entrée : Traefik, socket-proxy et CrowdSec
Traefik constitue le point d'entrée HTTP/HTTPS des services hébergés sur le
Homelab. Il termine les connexions TLS, obtient les certificats via ACME et
route les requêtes vers les applications raccordées au réseau Docker
traefik-public. CrowdSec complète cette porte d'entrée en
analysant les journaux et en fournissant les décisions de sécurité au
bouncer Traefik.
L'API Docker n'est pas montée directement dans Traefik : le service
socket-proxy sert d'intermédiaire et n'autorise que les
catégories d'API nécessaires à la découverte des conteneurs et des
événements. Les stacks restent séparées : ce fichier Compose déploie
Traefik et son proxy de socket ; CrowdSec dispose de son propre fichier
Compose.
Réseaux et ordre de déploiement
-
socket-proxyest un réseau interne à la stack Traefik ; seuls Traefik et le proxy de socket y sont raccordés. -
traefik-publicest créé par la stack Traefik et partagé avec les services web à publier. Les stacks applicatives le déclarent comme réseau externe. -
crowdsecest le réseau partagé entre Traefik et les composants CrowdSec concernés. La stack CrowdSec le crée ; ce réseau doit donc exister avant le démarrage de la stack Traefik ci-dessous. Les services concernés doivent tous y être raccordés explicitement.
Pour déployer Traefik avant CrowdSec, il faudrait créer préalablement le
réseau externe crowdsec de manière indépendante, puis faire
en sorte que les deux stacks le réutilisent. Avec la configuration
présentée ici, le déploiement de CrowdSec crée d'abord ce réseau.
Fichier Compose de Traefik et du socket-proxy
Créez /opt/srv/docker/traefik/docker-compose.yml. Les
autorisations du socket-proxy sont volontairement limitées ; n'activez
pas de catégories supplémentaires sans vérifier le besoin.
name: traefik
services:
socket-proxy:
image: ghcr.io/tecnativa/docker-socket-proxy:latest
container_name: socket-proxy
restart: unless-stopped
environment:
LOG_LEVEL: "info"
CONTAINERS: "1"
EVENTS: "1"
NETWORKS: "1"
PING: "1"
SERVICES: "1"
TASKS: "1"
VERSION: "1"
INFO: "1"
POST: "0"
AUTH: "0"
CONFIG: "0"
EXEC: "0"
IMAGES: "0"
SECRETS: "0"
NODES: "0"
PLUGINS: "0"
SESSION: "0"
SWARM: "0"
VOLUMES: "0"
SYSTEM: "0"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- socket-proxy
expose:
- "2375"
security_opt:
- label=disable
traefik:
image: traefik:v3.7.10
container_name: traefik
restart: unless-stopped
depends_on:
- socket-proxy
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
- "443:443/udp"
networks:
- socket-proxy
- traefik-public
- crowdsec
volumes:
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro,Z
- ./data/acme.json:/etc/traefik/acme.json
- ./dynamic:/etc/traefik/dynamic:ro,Z
- ./logs:/var/log/traefik:Z
- ./secrets:/etc/traefik/secrets:ro,Z
env_file:
- .env
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DASHBOARD_HOST}`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=${TRAEFIK_MIDDLEWARES}"
networks:
socket-proxy:
internal: true
traefik-public:
name: traefik-public
crowdsec:
external: true
Arborescence et variables
mkdir -p /opt/srv/docker/traefik/config
mkdir -p /opt/srv/docker/traefik/dynamic
mkdir -p /opt/srv/docker/traefik/logs
mkdir -p /opt/srv/docker/traefik/secrets
mkdir -p /opt/srv/docker/traefik/data
touch /opt/srv/docker/traefik/data/acme.json
touch /opt/srv/docker/traefik/logs/traefik.log
touch /opt/srv/docker/traefik/logs/access.log
chmod 600 /opt/srv/docker/traefik/data/acme.json
Créez ensuite /opt/srv/docker/traefik/.env et remplacez les
valeurs d'exemple. TRAEFIK_MIDDLEWARES doit désigner les
middlewares réellement définis par le provider fichier, par exemple le
middleware CrowdSec et, si configuré, celui qui protège le tableau de bord.
TRAEFIK_DASHBOARD_HOST=traefik.example.com
TRAEFIK_MIDDLEWARES=crowdsec-bouncer@file
CROWDSEC_BOUNCER_API_KEY=remplacer_par_la_cle_du_bouncer
TZ=Europe/Paris
La clé du bouncer doit être générée par CrowdSec et conservée comme un secret. Le fichier dynamique doit définir le middleware correspondant au plugin ; la valeur de la variable doit correspondre exactement à son nom et à son provider. Ne publiez pas le tableau de bord sans lui appliquer un middleware d'authentification adapté.
Configuration statique de Traefik
Créez /opt/srv/docker/traefik/config/traefik.yml et
remplacez l'adresse de courriel par une adresse valide.
global:
checkNewVersion: true
sendAnonymousUsage: false
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
providers:
docker:
endpoint: "tcp://socket-proxy:2375"
exposedByDefault: false
network: traefik-public
file:
directory: /etc/traefik/dynamic
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: votre_email_valide@example.com
storage: /etc/traefik/acme.json
httpChallenge:
entryPoint: web
log:
level: INFO
filePath: /var/log/traefik/traefik.log
format: json
accessLog:
filePath: /var/log/traefik/access.log
format: json
bufferingSize: 100
filters:
statusCodes:
- "400-599"
- "200-299"
fields:
headers:
defaultMode: drop
names:
User-Agent: keep
X-Forwarded-For: keep
X-Real-IP: keep
X-Forwarded-Proto: keep
experimental:
plugins:
bouncer:
moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
version: "v1.7.1"
Cette configuration redirige HTTP vers HTTPS, utilise le socket-proxy
pour découvrir les services Docker, et charge les middlewares depuis
dynamic. Seuls les conteneurs portant des labels Traefik
sont publiés. Le plugin CrowdSec est déclaré ici ; sa configuration et
son middleware doivent être définis côté provider fichier et raccordés
au réseau partagé.
Configuration de CrowdSec
CrowdSec est déployé dans une stack distincte, avec sa propre
configuration, ses journaux et ses données persistantes. Pour que le
bouncer Traefik fonctionne, raccordez le service CrowdSec au réseau
crowdsec, définissez le middleware dynamique du plugin avec
l'adresse de l'API CrowdSec et la clé du bouncer, puis référencez ce
middleware dans TRAEFIK_MIDDLEWARES. Les paramètres exacts
dépendent de la configuration retenue pour l'API CrowdSec ; ils doivent
être documentés avec le fichier Compose propre à CrowdSec.
Déployez les applications dans leurs propres stacks. Chaque service web
à exposer doit être connecté à traefik-public et déclaré
auprès de Traefik par ses labels. La base de données d'une application
reste sur un réseau interne à sa stack.