
Introduction #
Dans cet article, nous allons apprendre à déployer une stack frontend complète et sécurisée qui combine quatre composants essentiels :
- Traefik comme reverse proxy avec génération automatique de certificats SSL,
- Authelia pour l’authentification (2FA,SSO, Clés d’accès),
- CrowdSec pour la protection contre les attaques,
- Redis comme cache performant.
Nous allons couvrir la création d’un conteneur LXC Proxmox dédié, la configuration de chaque service, leurs interactions, le déploiement complet et les bonnes pratiques de sécurité.
Ce tutoriel suppose que vous avez déjà un serveur Proxmox VE opérationnel, des connaissances de base sur les conteneurs LXC et Docker, ainsi qu’un nom de domaine configuré.
Table des matières #
- 🌐 Architecture réseau
- 🖥️ Préparation du conteneur LXC Proxmox
- 🔭 Vue d’ensemble de l’architecture
- 📋 Prérequis techniques
- 📁 Structure du projet
- ⚙️ Configuration des services
- 🚀 Déploiement étape par étape
- ✅ Vérification et tests
- 🔧 Maintenance et monitoring
- 🔍 Troubleshooting
- ⚡ Optimisations et bonnes pratiques
- 🎯 Conclusion
🌐 Architecture réseau #
Ma configuration réseau est basée sur une segmentation VLAN pour isoler les différents composants :
Segmentation VLAN #
| VLAN | Sous-réseau | Description | Composants |
|---|---|---|---|
| VLAN 10 | 10.10.10.x/24 |
Infrastructure Proxmox | Hôtes Proxmox VE & PBS |
| VLAN 20 | 10.10.20.x/24 |
LXC et/ou VMs | LXC-Mediaserver, LXC-Elephant, LXC Storage |
| VLAN 99 | 10.99.99.x/24 |
Zone DMZ isolée (Frontend) | LXC-Frontend (Stack Traefik + Authelia + CrowdSec) |
Schéma réseau simplifié #
graph TB
Internet[Internet] --> Router[Routeur/Firewall]
Router --> SW[Switch managé]
SW --> VLAN10[VLAN 10
10.10.10.x]
SW --> VLAN99[VLAN 99
10.99.99.x
Mode isolé]
VLAN10 --> PVE[Proxmox VE
10.10.10.x]
VLAN10 --> PBS[Proxmox Backup
10.10.10.x]
VLAN99 --> LXC[LXC-Frontend
10.99.99.10]
LXC --> TraefikStack[Stack Frontend
Traefik + Authelia
CrowdSec + Redis]
style VLAN99 fill:#ffcdd2,stroke:#c62828,stroke-width:3px,color:#000
style LXC fill:#ffebee,stroke:#d32f2f,stroke-width:2px,color:#000
style TraefikStack fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
Isolation du VLAN 99 (Mode DMZ) #
Pourquoi isoler la stack frontend dans un VLAN dédié ?
Le VLAN 99 est configuré en mode isolé sous Unifi Network (ou tout autre contrôleur réseau) pour des raisons de sécurité :
- Isolation du réseau de confiance : Les services exposés sur Internet ne peuvent pas accéder directement à mes réseaux internes (VLAN 10-20-30-etc)
- Principe de défense en profondeur : En cas de compromission du conteneur LXC, l’attaquant est limité au VLAN 99
- Règles de pare-feu strictes : Seuls les ports 80 (HTTP) et 443 (HTTPS) sont ouverts depuis Internet vers
10.99.99.10 - Flux contrôlés : Les services backend dans d’autres VLANs peuvent initier des connexions vers la stack frontend, mais pas l’inverse
Configuration Unifi Network : Dans le contrôleur Unifi, le VLAN 99 doit avoir l’option “Isolate Network” activée pour empêcher toute communication avec les autres réseaux locaux.
Flux réseau typique #
- Client externe (Internet) → Requête HTTPS sur le port 443
- Routeur/Firewall → NAT vers
10.99.99.10:443(LXC-Frontend) - Traefik (dans LXC) → Termine le SSL et applique la chaîne de sécurité
- CrowdSec + Authelia → Validation de l’IP et authentification
- Proxy vers backend → Traefik forward vers les services applicatifs (autres VLANs si autorisé)
🖥️ Préparation du conteneur LXC Proxmox #
Création du conteneur LXC en ligne de commande #
Téléchargement du template Debian 13 #
Connectez-vous à votre serveur Proxmox via SSH et téléchargez le template :
# Télécharge le template Debian 13 dans le stockage local
pveam update
pveam download iso-morpheus debian-13-standard_13.0-1_amd64.tar.zst
iso-morpheus correspond ici au nom de mon storage Proxmox contenant vos images ISO de VMs et vos templates LXC. Pensez à l’adapter à votre infrastructure.
Création du conteneur #
Créez le conteneur LXC avec la commande pct create :
pct create 110 iso-morpheus:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \
--hostname frontend \
--memory 2048 \
--cores 2 \
--rootfs datastore-zfs:16 \
--net0 name=eth0,bridge=vmbr0,firewall=1,gw=10.99.99.1,ip=10.99.99.10/24,tag=99,type=veth \
--nameserver 192.168.0.153 \
--searchdomain mydomain.local \
--password \
--unprivileged 0 \
--features nesting=1,keyctl=1 \
--onboot 1 \
--startup order=1
datastore-zfs correspond ici au nom de mon storage ZFS Proxmox contenant les images disques de VMs/LXC. Pensez à l’adapter à votre infrastructure.
Explication des paramètres :
110: ID du conteneur (adaptez selon votre environnement)--hostname frontend: Nom d’hôte du conteneur--memory 2048: 2 GB de RAM (minimum recommandé)--cores 2: 2 cœurs CPU--rootfs datastore-zfs:16: Disque de 16 GB sur le stockage datastore-zfs--net0: Configuration réseau (adaptez l’IP, gateway et bridge selon votre réseau)--unprivileged 0: Conteneur privilégié (voir avertissement de sécurité ci-dessous)--features nesting=1,keyctl=1: Nécessaire pour Docker dans LXC--onboot 1: Démarre automatiquement au boot de Proxmox--startup order=1: Ordre de démarrage
nesting=1 et keyctl=1 sont indispensables pour exécuter Docker dans un conteneur LXC.
Avertissement de sécurité : Conteneur LXC privilégié
Le paramètre --unprivileged 0 crée un conteneur privilégié, ce qui signifie que :
Risques de sécurité importants :
- L’utilisateur root dans le conteneur correspond à l’utilisateur root de l’hôte Proxmox
- Une compromission du conteneur peut entraîner une compromission complète de l’hôte Proxmox
- Les processus du conteneur ont un accès quasi-illimité aux ressources système de l’hôte
- En cas de faille de sécurité (CVE Docker, vulnérabilité applicative), un attaquant pourrait s’échapper du conteneur LXC
Pourquoi utiliser un conteneur privilégié ici ?
Dans certains cas, Docker dans un conteneur LXC non-privilégié peut rencontrer des problèmes de :
- Mapping des UID/GID complexe
- Permissions sur les volumes montés
- Compatibilité avec certaines images Docker
Recommandations de sécurité :
- Isolation réseau : Placez ce conteneur dans un VLAN dédié séparé de votre réseau de confiance
- Pare-feu strict : N’autorisez que les ports 80 et 443 depuis Internet, bloquez tous les autres ports
- Mises à jour régulières : Appliquez systématiquement les mises à jour de sécurité (Debian, Docker, images)
- Monitoring actif : Surveillez les logs système et les comportements anormaux
- Snapshots réguliers : Effectuez des sauvegardes fréquentes de votre conteneur avant toute modification
- Limitez l’accès SSH : Restreignez l’accès root au conteneur et utilisez des clés SSH plutôt que des mots de passe
- Principe du moindre privilège : N’exposez que les services strictement nécessaires
Alternative plus sécurisée :
Si votre environnement le permet, envisagez d’utiliser un conteneur non-privilégié (--unprivileged 1) avec un mapping d’UID/GID correct :
# Dans /etc/pve/lxc/110.conf (après création)
lxc.idmap: u 0 100000 1000
lxc.idmap: g 0 100000 1000
lxc.idmap: u 1000 1000 1
lxc.idmap: g 1000 1000 1
lxc.idmap: u 1001 101001 64535
lxc.idmap: g 1001 101001 64535
Cependant, cette configuration nécessite des ajustements supplémentaires pour Docker et peut compliquer le déploiement voir même le rendre impossible.
Pour un environnement de production critique et si vous ne maîtrisez pas tous les tenants et aboutissants d’un telle configuration, privilégiez :
- Une VM complète (plutôt qu’un conteneur LXC)
Démarrage du conteneur #
# Démarre le conteneur
pct start 110
# Vérifie le statut
pct status 110
# Entre dans le conteneur
pct enter 110
Configuration initiale du conteneur #
Une fois dans le conteneur, effectuez la configuration de base :
Mise à jour du système #
# Met à jour les dépôts et le système
sudo apt upgrade -y
Installation de Docker et Docker Compose #
# Installe les dépendances
sudo apt install -y ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
# Installation des paquets
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Vérifie l'installation
sudo systemctl status docker
docker --version
docker compose version
Création de l’utilisateur pour la stack #
Créez un utilisateur dédié s’il n’existe pas déjà (UID 1000) pour gérer la stack :
# Crée l'utilisateur myuser avec UID 1000
useradd -m -u 1000 -s /bin/bash myuser
# Définit un mot de passe
passwd myuser
# Ajoute l'utilisateur au groupe docker
usermod -aG docker myuser
# Ajoute l'utilisateur au groupe sudo (optionnel)
usermod -aG sudo myuser
Création de la structure de dossiers #
# Crée le répertoire de travail principal
mkdir -p /opt/docker/frontend-stack
# Donne les droits à l'utilisateur myuser (UID 1000)
chown -R 1000:1000 /opt/docker
chmod -R 755 /opt/docker
/opt/docker/frontend-stack.
🔭 Vue d’ensemble de l’architecture #
Schéma de l’architecture #
graph TB
subgraph "Internet"
Client[Client Web]
end
subgraph "Proxmox Host"
Bridge[Bridge vmbr0
10.10.10.X/24]
end
subgraph "LXC Container
10.99.99.10"
subgraph "Docker Network: frontend
172.18.0.0/16"
Traefik[Traefik
Reverse Proxy + SSL
Ports 80/443]
CrowdSec[CrowdSec
WAF + Detection
Port 8081]
Authelia[Authelia
SSO + 2FA
Port 9091]
Redis[Redis
Cache Sessions
Port 6379]
App[Application
Backend Services]
end
end
Client -->|HTTPS| Bridge
Bridge --> Traefik
Traefik -->|Middleware Chain| CrowdSec
CrowdSec --> Authelia
Authelia --> App
Authelia -.Session.-> Redis
CrowdSec -.Cache.-> Redis
Traefik -.Logs.-> CrowdSec
Authelia -.Logs.-> CrowdSec
Légende :
- Traefik : Point d’entrée unique, gestion SSL automatique
- CrowdSec : Protection contre les cyberattaques
- Authelia : Authentification et autorisation
- Redis : Cache haute performance
- Application : Services backend protégés
Tous les services communiquent via un réseau Docker bridge nommé frontend avec un sous-réseau dédié (172.18.0.0/16).
Services composant la stack #
| Service | Rôle | Port(s) | Image Docker |
|---|---|---|---|
| Traefik | Reverse proxy, routage HTTP/HTTPS, génération SSL automatique | 80, 443, 8080 | traefik:latest |
| Authelia | Authentification SSO, double facteur (TOTP, WebAuthn) | 9091 | authelia/authelia:4.39.15 |
| CrowdSec | Détection et blocage d’attaques, AppSec WAF | 8081 | crowdsecurity/crowdsec:latest |
| Redis | Cache session Authelia, cache CrowdSec bouncer | 6379 | redis:latest |
| Redis Insight | Interface web pour administrer Redis | 5540 | redis/redisinsight:latest |
Version fixe d’Authelia (4.39.15) : Le tag de version d’Authelia est volontairement fixé et non en latest. Cette décision est critique car :
- Authelia contrôle l’accès à tous vos services exposés : C’est le composant le plus sensible de la stack
- Les mises à jour majeures peuvent casser la configuration : Les versions 4.38+ et 4.39+ ont introduit des changements de configuration importants
- Évite les surprises en production : Une mise à jour automatique pourrait bloquer l’accès à toutes vos applications
- Version stable et éprouvée : La version 4.39.15 est testée et fonctionnelle avec cette configuration
Recommandation : Avant de mettre à jour Authelia, consultez les release notes officielles et testez dans un environnement de développement. Les changements de configuration doivent être validés avant le passage en production.
Flux de données #
sequenceDiagram
participant Client
participant Traefik
participant CrowdSec
participant Authelia
participant Redis
participant App as Application
Client->>Traefik: 1. Requête HTTPS
Traefik->>CrowdSec: 2. Vérification IP
CrowdSec->>Redis: Consultation cache décisions
Redis-->>CrowdSec: ✓ IP autorisée
CrowdSec->>Authelia: 3. Demande authentification
Authelia->>Redis: Vérification session
Redis-->>Authelia: ✓ Session valide + 2FA OK
Authelia->>App: 4. Transmission requête
App-->>Authelia: 5. Réponse applicative
Authelia-->>Traefik: 6. Réponse sécurisée
Traefik-->>Client: 7. Réponse HTTPS
Note over Traefik,CrowdSec: Les logs Traefik/Authelia sont
analysés en temps réel par CrowdSec
Explication simplifiée du flux :
- Client → Traefik : L’utilisateur accède à
https://app.mydomain.comvia HTTPS - Traefik → CrowdSec : Vérification de l’IP dans la base de décisions (mise en cache Redis)
- CrowdSec → Authelia : Si l’IP est autorisée, vérification de l’authentification utilisateur
- Authelia → Application : Si l’utilisateur est authentifié et 2FA validé, la requête est transmise
- Application → Client : La réponse remonte la chaîne jusqu’au client
CrowdSec analyse en continu les logs de Traefik et Authelia pour détecter les comportements suspects et mettre à jour automatiquement les décisions de blocage.
📋 Prérequis techniques #
Infrastructure Proxmox #
- Proxmox VE : version 8.0+ recommandée
- Conteneur LXC : Debian 13 avec fonctionnalités
nestingetkeyctlactivées - Réseau : Bridge réseau configuré (vmbr0) avec accès Internet
Logiciels requis (dans le LXC) #
- Docker : version 24.0+ Installer Docker
- Docker Compose : version 2.0+ (inclus avec Docker via docker-compose-plugin)
- Git : pour cloner le projet si nécessaire
- Éditeur de texte : vi, vim ou accès distant via VS Code
Connaissances recommandées #
Configuration minimale LXC #
| Composant | Minimum | Recommandé |
|---|---|---|
| CPU | 1 cœurs | 2 cœurs |
| RAM | 1 GB | 2 GB |
| Disque | 8 GB | 16 GB |
| Système | Debian 13 (template officiel Proxmox) | - |
| Réseau | IP statique, ports 80/443 accessibles | - |
| DNS | Nom de domaine avec accès DNS (certificats wildcard) | - |
Accès requis #
- Cloudflare ou OVH : Compte avec API token pour le DNS challenge ACME
- Email : Adresse email pour les notifications Authelia (SMTP Gmail ou autre)
📁 Structure du projet #
Voici l’arborescence complète du projet dans /opt/docker/frontend-stack :
/opt/docker/frontend-stack/
├── docker-compose.yml # Orchestration principale (include des sous-stacks)
├── .env # Variables d'environnement (SENSIBLE - ne pas commiter)
├── .env.example # Variables d'environnement modèles
├── authelia/
│ ├── docker-compose.yml # Service Authelia
│ ├── configuration.yml # Configuration complète Authelia
│ ├── users/ # Base utilisateurs (fichier YAML)
│ │ └── config.yml # Fichier utilisateurs avec hash Argon2id
│ ├── db/ # Base SQLite locale (persistance)
│ └── logs/ # Logs Authelia (analysés par CrowdSec)
│ └── authelia.log # Fichier de log principal
├── traefik/
│ ├── docker-compose.yml # Service Traefik
│ ├── config.yml # Configuration statique Traefik
│ ├── rules/ # Configuration dynamique (fichiers YAML)
│ │ ├── 00-middlewares.yml # Définition des middlewares (sécurité, compression)
│ │ ├── 100-frontend.yml # Routes pour Traefik et Authelia
│ │ └── ... # Autres règles de routage par catégorie
│ ├── certs/ # Certificats SSL générés (JSON ACME)
│ ├── logs/ # Logs Traefik (analysés par CrowdSec)
│ │ ├── access.log # Logs d'accès HTTP
│ │ └── error.log # Logs d'erreurs
│ └── plugins/ # Plugin CrowdSec bouncer (templates HTML)
│ └── crowdsec-bouncer/
│ ├── captcha.html # Page captcha CrowdSec
│ └── ban.html # Page de ban CrowdSec
├── crowdsec/
│ ├── docker-compose.yml # Service CrowdSec
│ ├── config/
│ │ ├── acquis.yaml # Sources de logs à analyser
│ │ ├── profiles.yaml # Profils de décisions
│ │ └── notifications/ # Configuration notifications (ntfy)
│ │ └── ntfy.yaml # Configuration ntfy.sh
│ └── data/ # Base de données CrowdSec (persistance)
└── redis/
├── docker-compose.yml # Services Redis + Redis Insight
├── data/ # Persistance Redis
└── insight/ # Données Redis Insight
Fichiers clés #
| Fichier | Chemin absolu | Description |
|---|---|---|
| docker-compose.yml | /opt/docker/frontend-stack/docker-compose.yml |
Orchestre les 4 sous-stacks via la directive include |
| .env | /opt/docker/frontend-stack/.env |
Variables sensibles (mots de passe Redis, tokens API DNS, clés CrowdSec) |
| config.yml | /opt/docker/frontend-stack/traefik/config.yml |
Configuration statique Traefik (entrypoints, certificats, plugins) |
| 00-middlewares.yml | /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml |
Middlewares de sécurité (headers, rate-limit, CrowdSec, Authelia) |
| configuration.yml | /opt/docker/frontend-stack/authelia/configuration.yml |
Configuration complète Authelia (authentification, règles d’accès, session Redis) |
| users/config.yml | /opt/docker/frontend-stack/authelia/users/config.yml |
Base utilisateurs Authelia avec hash Argon2id |
| acquis.yaml | /opt/docker/frontend-stack/crowdsec/config/acquis.yaml |
Définit les logs à analyser et le composant AppSec |
/opt/docker/frontend-stack.
⚙️ Configuration des services #
Service 1 : Redis #
Rôle et responsabilités #
Redis joue un rôle central dans cette architecture en fournissant un cache haute performance pour deux services critiques :
- Authelia : Stockage des sessions utilisateurs (base de données 0)
- CrowdSec Bouncer : Cache des décisions de blocage (base de données 5) pour éviter de surcharger l’API CrowdSec
Redis Insight est inclus pour faciliter l’administration et le monitoring.
Configuration Docker Compose #
Fichier : /opt/docker/frontend-stack/redis/docker-compose.yml
services:
redis:
container_name: redis
image: redis:latest
security_opt:
- no-new-privileges:true # Sécurité : empêche l'escalade de privilèges
restart: always
ports:
- 6379:6379 # Port standard Redis
command: >
redis-server
--save 60 1 # Sauvegarde sur disque toutes les 60s si ≥1 modification
--loglevel notice # Niveau de log équilibré
--requirepass ${REDIS_PASSWORD} # Authentification obligatoire
volumes:
- ./data:/data # Persistance des données
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 15s # Vérification toutes les 15s
timeout: 3s
retries: 3
networks:
- frontend
redis-insight:
container_name: redis-insight
image: redis/redisinsight:latest
security_opt:
- no-new-privileges:true
restart: unless-stopped
ports:
- 5540:5540 # Interface web
volumes:
- ./insight:/data # Configuration Redis Insight
networks:
- frontend
Variables d’environnement #
| Variable | Description | Valeur par défaut | Obligatoire |
|---|---|---|---|
| REDIS_PASSWORD | Mot de passe Redis | - | Oui |
Volumes et persistance #
- ./data →
/opt/docker/frontend-stack/redis/data: Données Redis (persistance RDB activée toutes les 60 secondes) - ./insight →
/opt/docker/frontend-stack/redis/insight: Configuration et données Redis Insight
Dépendances #
Aucune dépendance. Redis démarre en premier car d’autres services en dépendent.
Service 2 : Authelia #
Rôle et responsabilités #
Authelia est le gardien de votre infrastructure. Il fournit :
- Authentification SSO : Connexion unique pour tous les services
- Double facteur : TOTP (Google Authenticator, Authy) et WebAuthn (Yubikey, Touch ID)
- Gestion fine des accès : Politiques par domaine, réseau et utilisateur
- Réinitialisation de mot de passe : Via email SMTP
Configuration Docker Compose #
Fichier : /opt/docker/frontend-stack/authelia/docker-compose.yml
services:
authelia:
container_name: authelia
image: authelia/authelia:4.39.15
user: 1000:1000 # Exécute avec l'utilisateur myuser (UID 1000)
security_opt:
- no-new-privileges:true # Sécurité renforcée
restart: always
ports:
- 9091:9091 # API et interface web
depends_on:
redis:
condition: service_healthy # Attend que Redis soit opérationnel
volumes:
- ./:/config # Configuration complète montée dans le répertoire courant authelia
environment:
- TZ=Europe/Paris # Fuseau horaire pour les logs
networks:
- frontend
Variables d’environnement #
Authelia utilise principalement son fichier configuration.yml plutôt que des variables d’environnement. Les secrets suivants doivent être définis dans /opt/docker/frontend-stack/authelia/configuration.yml :
| Variable (dans config.yml) | Description | Obligatoire |
|---|---|---|
| jwt_secret | Clé JWT pour réinitialisation mot de passe | Oui |
| session.secret | Clé de chiffrement des sessions | Oui |
| storage.encryption_key | Clé de chiffrement de la base de données | Oui |
| session.redis.password | Mot de passe Redis (depuis .env) | Oui |
| notifier.smtp.password | Mot de passe SMTP pour les emails | Oui |
openssl rand -base64 32
Volumes et persistance #
- ./configuration.yml →
/opt/docker/frontend-stack/authelia/configuration.yml: Configuration principale Authelia - ./users/config.yml →
/opt/docker/frontend-stack/authelia/users/config.yml: Base utilisateurs (hash Argon2id) - ./db/db.sqlite3 →
/opt/docker/frontend-stack/authelia/db/db.sqlite3: Base de données locale (données 2FA, consentements) générée au démarrage du conteneur docker - ./logs/authelia.log →
/opt/docker/frontend-stack/authelia/logs/authelia.log: Fichier de logs (analysé par CrowdSec)
Dépendances #
- Redis : Stockage des sessions (condition: service_healthy)
Configuration des règles d’accès #
Authelia propose trois niveaux de politique :
- bypass : Accès sans authentification (services publics, applications avec auth native)
- one_factor : Mot de passe uniquement
- two_factor : Mot de passe + TOTP/WebAuthn
Exemple de règles dans /opt/docker/frontend-stack/authelia/configuration.yml :
access_control:
default_policy: "deny" # Par défaut, tout est bloqué
rules:
# Services publics ou avec auth native
- domain: 'nextcloud.mydomain.com'
policy: 'bypass'
# Monitoring léger
- domain: 'argus.ci.mydomain.com'
policy: 'one_factor'
# Services critiques
- domain: 'proxmox.pve.mydomain.com'
policy: 'two_factor'
# Bypass depuis réseaux internes
- domain:
- "*.mydomain.com"
policy: "bypass"
networks:
- "internal" # Défini dans access_control.networks
Service 3 : Traefik #
Approche de sécurité : Configuration par fichiers plutôt que par labels Docker
Dans cette stack, j’ai volontairement choisi de ne pas binder le socket Docker (/var/run/docker.sock) dans les volumes Traefik. Cette décision architecturale présente plusieurs avantages sécuritaires :
Pourquoi éviter le socket Docker ?
- Réduction de la surface d’attaque : Le socket Docker donne un accès root complet à l’hôte. Une compromission de Traefik ne permet pas d’accéder à Docker.
- Principe du moindre privilège : Traefik n’a pas besoin d’un accès complet à l’API Docker pour fonctionner.
- Isolation renforcée : Aucun conteneur de la stack ne peut interagir avec Docker lui-même.
Configuration par fichiers YAML
Au lieu d’utiliser les labels Traefik dans les docker-compose.yml des différents services, toute la configuration de routage se fait via des fichiers YAML situés dans le dossier traefik/rules/ :
00-middlewares.yml: Définition des middlewares de sécurité100-frontend.yml: Routes pour Traefik et Authelia- Autres fichiers de règles organisés par service ou catégorie
Avantages de cette approche :
- ✅ Configuration centralisée et versionnée
- ✅ Pas de redémarrage des conteneurs pour modifier le routage puisque les fichiers de routage se situent sous le dossier
./rules/qui est rechargé à chaud - ✅ Meilleure lisibilité et organisation
Rôle et responsabilités #
Traefik est le point d’entrée unique de toute notre infrastructure.
Il gère :
- Reverse proxy : Routage vers les différents services Docker
- SSL/TLS automatique : Génération et renouvellement via Let’s Encrypt (DNS challenge)
- Middlewares : Application de la chaîne de sécurité (CrowdSec, Authelia, headers, compression)
- Observabilité : Dashboard et logs détaillés
Configuration Docker Compose #
Fichier : /opt/docker/frontend-stack/traefik/docker-compose.yml
services:
traefik:
container_name: traefik
image: traefik:latest
restart: always
ports:
- 80:80 # HTTP (redirige vers HTTPS)
- 443:443 # HTTPS
- 8080:8080 # Dashboard (ne pas exposer en production !)
command:
- --configFile=/etc/traefik/config.yml
depends_on:
authelia:
condition: service_started
volumes:
- ./:/etc/traefik # Configuration complète
- ./logs:/var/log/traefik # Logs (analysés par CrowdSec)
- ./plugins/crowdsec-bouncer/captcha.html:/captcha.html
- ./plugins/crowdsec-bouncer/ban.html:/ban.html
environment:
- OVH_ENDPOINT=${OVH_ENDPOINT}
- OVH_APPLICATION_KEY=${OVH_APPLICATION_KEY}
- OVH_APPLICATION_SECRET=${OVH_APPLICATION_SECRET}
- OVH_CONSUMER_KEY=${OVH_CONSUMER_KEY}
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} # Cloudflare API
- TZ=Europe/Paris
networks:
- frontend
Variables d’environnement #
Définies dans /opt/docker/frontend-stack/.env :
| Variable | Description | Valeur par défaut | Obligatoire |
|---|---|---|---|
| CF_DNS_API_TOKEN | Token API Cloudflare pour DNS challenge | - | Oui (si Cloudflare) |
| OVH_ENDPOINT | Endpoint OVH API (ovh-eu, ovh-ca, etc.) | ovh-eu | Oui (si OVH) |
| OVH_APPLICATION_KEY | Clé application OVH | - | Oui (si OVH) |
| OVH_APPLICATION_SECRET | Secret application OVH | - | Oui (si OVH) |
| OVH_CONSUMER_KEY | Clé consommateur OVH | - | Oui (si OVH) |
certResolver correspondant dans /opt/docker/frontend-stack/traefik/config.yml.
Volumes et persistance #
- ./config.yml →
/opt/docker/frontend-stack/traefik/config.yml: Configuration statique (entrypoints, certificats) - ./rules/ →
/opt/docker/frontend-stack/traefik/rules/: Configuration dynamique (routers, services, middlewares) - ./certs/ →
/opt/docker/frontend-stack/traefik/certs/: Certificats ACME générés (JSON) - ./logs/ →
/opt/docker/frontend-stack/traefik/logs/: Logs access et error
Dépendances #
- Authelia : Middleware forwardAuth (condition: service_started)
Configuration complète de Traefik (config.yml) #
Voici la configuration statique complète de Traefik située dans /opt/docker/frontend-stack/traefik/config.yml :
---
global:
checkNewVersion: true # Vérifie les nouvelles versions
sendAnonymousUsage: false # Désactive la télémétrie
serversTransport:
insecureSkipVerify: true # Accepte les certificats auto-signés (backends internes)
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure # Redirige tout le trafic HTTP vers HTTPS
scheme: https
websecure:
address: ":443"
http:
tls:
certResolver: cloudflare # Resolver par défaut (cloudflare, ovh, ou staging)
domains:
- main: mydomain.com
sans:
- "*.mydomain.com" # Certificat wildcard pour tous les sous-domaines
- main: subdomain1.mydomain.com
sans:
- "*.subdomain1.mydomain.com"
- main: subdomain2.mydomain.com
sans:
- "*.subdomain2.mydomain.com"
middlewares:
- chain-secure # Applique la chaîne de sécurité par défaut
providers:
file:
directory: /etc/traefik/rules # Chargement des fichiers de configuration dynamique
watch: true # Rechargement automatique des modifications
log:
level: error # Niveau de log (debug, info, warn, error)
format: common # Format des logs
filePath: /var/log/traefik/error.log
accessLog:
filePath: /var/log/traefik/access.log
format: common # Format analysable par CrowdSec
fields:
defaultMode: keep # Conserve tous les champs par défaut
headers:
defaultMode: keep # Conserve tous les headers (utile pour le debugging)
api:
dashboard: true # Active le dashboard Traefik
insecure: true # Dashboard accessible sur :8080 (à sécuriser en prod !)
debug: false # Mode debug désactivé
# Resolvers de certificats SSL (4 configurations disponibles)
certificatesResolvers:
# Production Cloudflare
cloudflare:
acme:
email: user@gmail.com # Email pour les notifications Let's Encrypt
storage: /etc/traefik/certs/acme-cloudflare.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudflare
propagation:
disableChecks: true # Désactive la vérification de propagation DNS
delayBeforeChecks: 60 # Attente 60s avant vérification ACME
resolvers:
- "1.1.1.1:53" # DNS Cloudflare
- "1.0.0.1:53"
# Staging Cloudflare (certificats de test)
cloudflare-staging:
acme:
email: user@gmail.com
storage: /etc/traefik/certs/acme-cloudflare-staging.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudflare
propagation:
disableChecks: true
delayBeforeChecks: 60
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
# Production OVH
ovh:
acme:
email: user@gmail.com
storage: /etc/traefik/certs/acme-ovh.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: ovh
propagation:
disableChecks: true
delayBeforeChecks: 60
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
# Staging OVH (certificats de test)
ovh-staging:
acme:
email: user@gmail.com
storage: /etc/traefik/certs/acme-ovh-staging.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: ovh
propagation:
disableChecks: true
delayBeforeChecks: 60
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
# Plugin CrowdSec Bouncer pour Traefik
experimental:
plugins:
crowdsec-bouncer:
moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
version: "v1.4.5"
Points clés de cette configuration :
domains génère un certificat couvrant le domaine principal et tous ses sous-domaines via *..
-staging pour valider votre configuration sans risquer d’atteindre les limites de Let’s Encrypt, puis basculez sur les versions production.
api.insecure: true expose le dashboard sur le port 8080 sans authentification. En production, sécurisez-le avec Authelia via une route dans traefik/rules/100-frontend.yml.
Configuration de la chaîne de sécurité #
Le middleware chain-secure défini dans /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml applique plusieurs couches de protection :
http:
middlewares:
chain-secure:
chain:
middlewares:
- https-redirect # Force HTTPS
- crowdsec # Vérification CrowdSec (blocage IPs malveillantes)
- compression # Compression gzip/brotli
- secure-headers # Headers de sécurité (HSTS, X-Frame-Options, CSP)
- authelia # Authentification SSO
Cette chaîne est appliquée automatiquement à toutes les requêtes HTTPS grâce à la configuration de l’entrypoint websecure :
entryPoints:
websecure:
http:
middlewares:
- chain-secure # Chaîne appliquée par défaut
Service 4 : CrowdSec #
Rôle et responsabilités #
CrowdSec est le système de défense actif de notre infrastructure.
Il assure :
- Détection d’attaques : Analyse en temps réel des logs Traefik et Authelia
- Blocage automatique : Ban des IPs malveillantes (intégré à Traefik via plugin)
- Application Security (AppSec) : WAF virtuel avec patching et règles CRS
- Intelligence collective : Partage anonyme des attaques détectées
Configuration Docker Compose #
Fichier : /opt/docker/frontend-stack/crowdsec/docker-compose.yml
services:
crowdsec:
container_name: crowdsec
image: crowdsecurity/crowdsec:latest
restart: unless-stopped
ports:
- 8081:8080 # API locale (LAPI)
depends_on:
redis:
condition: service_healthy
traefik:
condition: service_started
volumes:
- ./config/acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- ./config/profiles.yaml:/etc/crowdsec/profiles.yaml:ro
- ./config/notifications/ntfy.yaml:/etc/crowdsec/notifications/ntfy.yaml:ro
- ./data:/var/lib/crowdsec/data # Base de données décisions
- ../traefik/logs:/var/log/traefik:ro # Logs à analyser
- ../authelia/logs/:/var/log/authelia:ro
environment:
- GID=${GID-1000}
- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/base-http-scenarios crowdsecurity/sshd crowdsecurity/linux crowdsecurity/appsec-generic-rules crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-crs LePresidente/authelia
- CUSTOM_HOSTNAME=frontend-crowdsec
- BOUNCER_KEY_TRAEFIK="${BOUNCER_KEY_TRAEFIK}"
networks:
- frontend
Variables d’environnement #
| Variable | Description | Valeur par défaut | Obligatoire |
|---|---|---|---|
| COLLECTIONS | Collections de scénarios à installer au démarrage | - | Oui |
| BOUNCER_KEY_TRAEFIK | Clé API du bouncer Traefik | - | Oui |
| GID | Group ID pour les permissions fichiers | 1000 | Non |
BOUNCER_KEY_TRAEFIK est générée avec la commande : docker exec crowdsec cscli bouncers add crowdsec-bouncer-traefik-plugin
Volumes et persistance #
- ./config/acquis.yaml →
/opt/docker/frontend-stack/crowdsec/config/acquis.yaml: Définition des sources de logs - ./config/profiles.yaml →
/opt/docker/frontend-stack/crowdsec/config/profiles.yaml: Profils de décisions (durée ban, remédiation) - ./data →
/opt/docker/frontend-stack/crowdsec/data: Base de données SQLite (décisions, métriques) - ../traefik/logs →
/opt/docker/frontend-stack/traefik/logs: Logs Traefik (lecture seule) - ../authelia/logs →
/opt/docker/frontend-stack/authelia/logs: Logs Authelia (lecture seule)
Dépendances #
- Redis : Cache optionnel (condition: service_healthy)
- Traefik : Nécessaire pour que les logs existent (condition: service_started)
Configuration des sources de logs (acquis.yaml) #
Fichier : /opt/docker/frontend-stack/crowdsec/config/acquis.yaml
---
filenames:
- /var/log/traefik/*.log
labels:
type: traefik # Applique les parsers traefik
---
filenames:
- /var/log/authelia/authelia.log
labels:
type: authelia # Applique les parsers authelia
---
listen_addr: 0.0.0.0:7422 # Port AppSec
appsec_config: crowdsecurity/virtual-patching
name: myAppSecComponent
source: appsec
labels:
type: appsec
Le composant AppSec analyse les requêtes HTTP en temps réel (via le plugin Traefik) pour détecter les tentatives d’exploitation (SQLi, XSS, RCE, etc.).
Collections installées #
- crowdsecurity/traefik : Détection spécifique Traefik (scan, brute-force)
- crowdsecurity/http-cve : Exploitation de CVE HTTP connues
- crowdsecurity/base-http-scenarios : Scénarios HTTP génériques (crawlers agressifs)
- crowdsecurity/appsec-generic-rules : Règles WAF génériques
- crowdsecurity/appsec-virtual-patching : Patching virtuel de vulnérabilités
- crowdsecurity/appsec-crs : Core Rule Set (équivalent ModSecurity)
- LePresidente/authelia : Scénarios spécifiques Authelia
🚀 Déploiement étape par étape #
myuser (UID 1000).
Workflow de déploiement #
Le déploiement suit un processus en 7 étapes :
graph LR
A[1. Préparation
Création dossiers] --> B[2. Configuration
Fichiers .env et YAML]
B --> C[3. Réseau Docker
Création bridge]
C --> D[4. Téléchargement
Images Docker]
D --> E[5. Lancement
Services démarrés]
E --> F[6. Post-config
Utilisateurs + clés]
F --> G[7. Vérification
Tests et validation]
G -.Erreurs.-> F
style A fill:#bbdefb,stroke:#1976d2,stroke-width:2px,color:#000
style B fill:#bbdefb,stroke:#1976d2,stroke-width:2px,color:#000
style C fill:#ffe0b2,stroke:#f57c00,stroke-width:2px,color:#000
style D fill:#ffe0b2,stroke:#f57c00,stroke-width:2px,color:#000
style E fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000
style F fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000
style G fill:#e1bee7,stroke:#7b1fa2,stroke-width:2px,color:#000
Étape 1 : Préparation de l’environnement #
1.1 Se positionner dans le répertoire de travail #
# Se connecte au conteneur LXC (depuis Proxmox host)
pct enter 110
# Switch vers l'utilisateur myuser
su - myuser
# Se positionne dans le répertoire de travail
cd /opt/docker/frontend-stack
1.2 Créer la structure de dossiers #
# Crée la structure complète
mkdir -p /opt/docker/frontend-stack/{authelia/{db,logs,users},traefik/{certs,logs,rules,plugins/crowdsec-bouncer},crowdsec/{config/notifications,data},redis/{data,insight}}
# Vérifie les permissions (doit être 1000:1000)
ls -la /opt/docker/
1.3 Configuration des variables d’environnement #
Créez le fichier .env :
# Crée le fichier .env
vi /opt/docker/frontend-stack/.env
Contenu de /opt/docker/frontend-stack/.env :
COMPOSE_PROJECT_NAME=frontend
########################
# REDIS
########################
REDIS_PASSWORD="votre_mot_de_passe_redis_securise_32_caracteres"
########################
# TRAEFIK
########################
###### DNS CHALLENGE ######
########### OVH ###########
OVH_ENDPOINT="ovh-eu"
OVH_APPLICATION_KEY="votre_ovh_application_key"
OVH_APPLICATION_SECRET="votre_ovh_application_secret"
OVH_CONSUMER_KEY="votre_ovh_consumer_key"
########### OVH ###########
####### CLOUDFLARE ########
CF_DNS_API_TOKEN="votre_cloudflare_dns_api_token"
########################
# CROWDSEC
########################
######## BOUNCER ##########
# Sera généré à l'étape 4.2 avec la commande:
# docker exec crowdsec cscli bouncers add crowdsec-bouncer-traefik-plugin
BOUNCER_KEY_TRAEFIK="sera_genere_plus_tard"
Variables à personnaliser obligatoirement :
-
REDIS_PASSWORD: Mot de passe Redis sécurisé (minimum 16 caractères)# Exemple de génération openssl rand -base64 24 -
CF_DNS_API_TOKEN: Token API Cloudflare avec permissions DNS:Edit- Créez un token sur : https://dash.cloudflare.com/profile/api-tokens
- Permissions : Zone > DNS > Edit
- Resources : Include > Specific zone > mydomain.com
-
BOUNCER_KEY_TRAEFIK: Sera généré après le premier démarrage de CrowdSec (voir Étape 4.2)
OVH_ENDPOINT, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET et OVH_CONSUMER_KEY. Suivez la documentation OVH pour générer ces clés.
1.4 Configuration Authelia #
Modifiez /opt/docker/frontend-stack/authelia/configuration.yml :
- Générez les secrets nécessaires :
# Génère 3 secrets de 32 caractères
openssl rand -base64 32
openssl rand -base64 32
openssl rand -base64 32
- Éditez le fichier :
vi /opt/docker/frontend-stack/authelia/configuration.yml
-
Remplacez dans le fichier :
jwt_secret: "create_jwt_secret_here"→ Premier secret générésession.secret: "create_secret_session_here"→ Deuxième secretstorage.encryption_key: "create_encryption_key_here"→ Troisième secret
-
Configurez votre domaine :
- Remplacez
mydomain.compar votre domaine réel - Adaptez les règles d’accès selon vos services
- Remplacez
-
Configurez le mot de passe Redis :
- Remplacez
from_redis_env_passwordpar la valeur de${REDIS_PASSWORD}du fichier.env
- Remplacez
-
Configurez SMTP (pour réinitialisation mot de passe) :
- Si Gmail : activez les “App passwords” dans votre compte Google
- Remplacez
user@gmail.cometget_password_from_google
1.5 Configuration Traefik #
Modifiez /opt/docker/frontend-stack/traefik/config.yml :
vi /opt/docker/frontend-stack/traefik/config.yml
- Remplacez tous les
mydomain.compar votre domaine - Choisissez votre resolver de certificats :
- Ligne 21 :
certResolver: cloudflare(ouovh)
- Ligne 21 :
- Vérifiez votre email ACME dans les différents resolver
Modifiez /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml :
vi /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml
-
Middleware CrowdSec : Mettez à jour les credentials Redis
- Ligne 30 :
redisCachePassword: "votre-mot-de-passe-redis" - Ligne 22 :
crowdsecLapiKeysera mis à jour après génération (Étape 4.2)
- Ligne 30 :
-
IPs de confiance : Ajustez
clientTrustedIPsavec vos IPs publiques et réseau local
/opt/docker/frontend-stack/traefik/rules/00-middlewares.yml avec des vraies clés dans un dépôt public.
Étape 2 : Configuration du réseau Docker via docker-compose.yml #
Le réseau Docker frontend est automatiquement créé lors du lancement de la stack via le fichier docker-compose.yml principal.
Vérifiez la configuration réseau dans /opt/docker/frontend-stack/docker-compose.yml :
---
include:
- ./redis/docker-compose.yml
- ./authelia/docker-compose.yml
- ./traefik/docker-compose.yml
- ./crowdsec/docker-compose.yml
networks:
frontend:
name: frontend # Nom du réseau
driver: bridge # Type de réseau (bridge = réseau local isolé)
ipam:
config:
- subnet: 172.18.0.0/16 # Plage d'adresses IP (65536 adresses)
gateway: 172.18.0.1 # Passerelle du réseau
Pourquoi cette approche ?
Avantage de la définition dans docker-compose.yml :
- ✅ Création automatique : Le réseau est créé lors du premier
docker compose up -d - ✅ Gestion déclarative : La configuration réseau fait partie du projet, pas de commande CLI à retenir
- ✅ Reproductibilité : La stack peut être déployée de manière identique sur plusieurs environnements
- ✅ Pas de réseau orphelin : Le réseau est supprimé automatiquement avec
docker compose down
Que se passe-t-il au lancement ?
Lors du docker compose up -d (Étape 3), Docker Compose :
- Vérifie si le réseau
frontendexiste - Si non, le crée automatiquement avec la configuration spécifiée
- Connecte tous les services (Redis, Authelia, Traefik, CrowdSec) à ce réseau
- Attribue des adresses IP dans la plage
172.18.0.0/16
Vérification manuelle : Après le déploiement, vous pouvez inspecter le réseau avec :
docker network inspect frontend
Étape 3 : Lancement de la stack #
# Se positionne dans le répertoire de la stack
cd /opt/docker/frontend-stack
# Lance tous les services en arrière-plan
docker compose up -d
Que se passe-t-il ?
- Docker Compose lit le fichier
/opt/docker/frontend-stack/docker-compose.ymlet inclut les 4 sous-stacks - Les images sont téléchargées (première fois uniquement)
- Les services démarrent dans l’ordre des dépendances :
- Redis démarre en premier (healthcheck actif)
- Authelia attend que Redis soit healthy
- Traefik attend qu’Authelia soit démarré
- CrowdSec attend Redis (healthy) et Traefik (started)
- Les volumes sont créés et initialisés dans
/opt/docker/frontend-stack/ - Traefik commence à générer les certificats SSL (peut prendre 1-2 minutes)
Vérifiez le démarrage :
# Affiche l'état de tous les conteneurs
docker compose ps
Sortie attendue :
NAME IMAGE STATUS PORTS
redis redis:latest Up 1 minute 0.0.0.0:6379->6379/tcp
authelia authelia/authelia:4.39.15 Up 1 minute 0.0.0.0:9091->9091/tcp
traefik traefik:latest Up 1 minute 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:8080->8080/tcp
crowdsec crowdsecurity/crowdsec:latest Up 30 seconds 0.0.0.0:8081->8080/tcp
redis-insight redis/redisinsight:latest Up 1 minute 0.0.0.0:5540->5540/tcp
Étape 4 : Configuration post-démarrage #
4.1 Création du premier utilisateur Authelia #
Générez un hash de mot de passe Argon2id :
# Génère un hash pour le mot de passe "VotreMotDePasse123!"
docker exec -it authelia authelia crypto hash generate argon2 --password 'VotreMotDePasse123!'
Il va s’en dire qu’il est nécessaire de remplacer
VotreMotDePasse123!par un vrai mot de passe robuste et sécurisé.
Sortie exemple :
Digest: $argon2id$v=19$m=65536,t=3,p=4$abcdefghijklmnop$xyz123...
Créez le fichier utilisateurs :
vi /opt/docker/frontend-stack/authelia/users/config.yml
Contenu de /opt/docker/frontend-stack/authelia/users/config.yml :
---
users:
myuser:
displayname: "Administrateur"
password: "$argon2id$v=19$m=65536,t=3,p=4$..." # Hash généré ci-dessus
email: admin@mydomain.com
groups:
- admins
- users
users:.
Vérifiez les permissions du fichier :
# Les fichiers doivent appartenir à l'utilisateur 1000:1000
chown 1000:1000 /opt/docker/frontend-stack/authelia/users/config.yml
chmod 644 /opt/docker/frontend-stack/authelia/users/config.yml
4.2 Configuration du bouncer CrowdSec #
Générez la clé API du bouncer Traefik :
# Entre dans le conteneur CrowdSec
docker exec crowdsec cscli bouncers add crowdsec-bouncer-traefik-plugin
Sortie :
Api key for 'crowdsec-bouncer-traefik-plugin':
abc123def456ghi789jkl...
Mettez à jour la configuration :
-
Copiez la clé générée
-
Éditez
/opt/docker/frontend-stack/.envet remplacez la valeur deBOUNCER_KEY_TRAEFIK:
vi /opt/docker/frontend-stack/.env
- Éditez
/opt/docker/frontend-stack/traefik/rules/00-middlewares.ymlligne 22 et renseignez la clé générée pourcrowdsecLapiKey:
vi /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml
- Redémarrez les services :
cd /opt/docker/frontend-stack
docker compose restart traefik crowdsec
4.3 Vérification des certificats SSL #
Suivez la génération des certificats :
# Affiche les logs Traefik en temps réel
docker compose logs -f traefik
Recherchez les lignes :
time="..." level=info msg="Certificate obtained for domains [mydomain.com *.mydomain.com]"
time="..." level=info msg="Certificates obtained for domains"
Vérifiez le fichier ACME :
# Liste les certificats générés
cat /opt/docker/frontend-stack/traefik/certs/acme-cloudflare.json | grep -A 2 '"domain"'
Attention : Si les certificats ne se génèrent pas, vérifiez :
- Les credentials API (Cloudflare ou OVH) dans
/opt/docker/frontend-stack/.env - Les logs Traefik pour des erreurs DNS
- Que votre domaine pointe bien vers votre IP publique (IP du serveur Proxmox ou du conteneur LXC si NAT)
Étape 5 : Accès et configuration initiale #
5.1 Accès au dashboard Traefik #
Ouvrez votre navigateur : http://10.99.99.10:8080 (remplacez par l’IP de votre conteneur LXC)
Vous devriez voir :
- Tous les routers configurés
- Les services backend
- Les middlewares actifs
- Les certificats générés
5.2 Première connexion Authelia #
Accédez à : https://auth.mydomain.com
- Connectez-vous avec le compte créé à l’étape 4.1
- Configurez votre double facteur :
- TOTP : Scannez le QR code avec Google Authenticator ou autre utilitaire 2FA
- WebAuthn (optionnel) : Enregistrez une clé de sécurité (Yubikey, Touch ID)
- Testez la déconnexion/reconnexion
5.3 Vérification CrowdSec #
Consultez les métriques CrowdSec :
# Affiche les métriques
docker exec crowdsec cscli metrics
# Liste les décisions actives (bans)
docker exec crowdsec cscli decisions list
Testez le blocage manuellement :
# Bannit votre IP pendant 4 heures (test)
docker exec crowdsec cscli decisions add --ip VOTRE_IP --duration 4h --reason "Test"
# Supprime le ban
docker exec crowdsec cscli decisions delete --ip VOTRE_IP
✅ Vérification et tests #
Vérifier que tous les services sont démarrés #
# Liste les conteneurs en cours d'exécution
cd /opt/docker/frontend-stack
docker compose ps
Sortie attendue :
NAME STATUS PORTS
redis Up 10 minutes 0.0.0.0:6379->6379/tcp
authelia Up 10 minutes 0.0.0.0:9091->9091/tcp
traefik Up 10 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:8080->8080/tcp
crowdsec Up 10 minutes 0.0.0.0:8081->8080/tcp
redis-insight Up 10 minutes 0.0.0.0:5540->5540/tcp
Tous les conteneurs doivent avoir le statut Up. Si un conteneur est en Restarting ou Exited, consultez les logs :
docker compose logs <nom-du-service>
Tests fonctionnels #
Test 1 : Redirection HTTP vers HTTPS #
# Teste la redirection automatique
curl -I http://mydomain.com
Résultat attendu :
HTTP/1.1 308 Permanent Redirect
Location: https://mydomain.com/
Test 2 : Validité SSL #
# Vérifie le certificat SSL
openssl s_client -connect mydomain.com:443 -servername mydomain.com < /dev/null | grep -A 2 "Verify return code"
Résultat attendu :
Verify return code: 0 (ok)
Test 3 : Headers de sécurité #
# Affiche les headers de sécurité
curl -I https://mydomain.com
Headers attendus :
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Test 4 : Authentification Authelia #
Accédez à un service protégé (configuré avec policy: two_factor) :
- Vous êtes redirigé vers
https://auth.mydomain.com - Connectez-vous avec vos identifiants
- Saisissez le code TOTP
- Vous êtes redirigé vers le service demandé
Test 5 : Protection CrowdSec #
Simulez une attaque par brute-force :
# Tente 20 connexions échouées sur Authelia
for i in {1..20}; do
curl -X POST https://auth.mydomain.com/api/firstfactor \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"wrong"}'
done
Vérifiez le ban :
docker exec crowdsec cscli decisions list
Vous devriez voir votre IP bannie avec le scénario crowdsecurity/authelia-bf.
Supprimez le ban :
docker exec crowdsec cscli decisions delete --ip VOTRE_IP
Vérification des logs #
Logs de tous les services #
# Affiche les logs en temps réel
cd /opt/docker/frontend-stack
docker compose logs -f
# Logs d'un service spécifique
docker compose logs -f traefik
docker compose logs -f authelia
docker compose logs -f crowdsec
Logs Traefik détaillés #
# Logs d'accès (toutes les requêtes)
tail -f /opt/docker/frontend-stack/traefik/logs/access.log
# Logs d'erreurs uniquement
tail -f /opt/docker/frontend-stack/traefik/logs/error.log
Logs Authelia #
# Logs Authelia (connexions, échecs, etc.)
tail -f /opt/docker/frontend-stack/authelia/logs/authelia.log
Signaux d’alerte :
| Message | Signification | Solution |
|---|---|---|
Failed to connect to Redis |
Authelia ne peut pas joindre Redis | Vérifiez le mot de passe Redis dans /opt/docker/frontend-stack/authelia/configuration.yml |
TLS challenge failed |
Échec génération certificat | Vérifiez les credentials API DNS dans /opt/docker/frontend-stack/.env |
Error 502 Bad Gateway |
Service backend non joignable | Vérifiez que le service existe et est démarré |
authentication failed (Authelia) |
Échec connexion utilisateur | Vérifiez le hash de mot de passe dans /opt/docker/frontend-stack/authelia/users/config.yml |
crowdsec LAPI unreachable |
Le bouncer ne peut pas joindre CrowdSec | Vérifiez la BOUNCER_KEY_TRAEFIK dans /opt/docker/frontend-stack/.env et /opt/docker/frontend-stack/traefik/rules/00-middlewares.yml |
Vérification Redis #
Accédez à Redis Insight : http://10.99.99.10:5540 (remplacez par l’IP de votre conteneur LXC)
- Ajoutez une connexion :
- Host:
redis - Port:
6379 - Password: le contenur de
${REDIS_PASSWORD}dans.env
- Host:
- Explorez les bases de données :
- DB 0 : Sessions Authelia (clés
authelia-session:*) - DB 5 : Cache CrowdSec (clés
crowdsec:*)
- DB 0 : Sessions Authelia (clés
Alternativement, via CLI :
# Se connecte à Redis
docker exec -it redis redis-cli -a "${REDIS_PASSWORD}"
# Liste les clés de la base 0 (sessions Authelia)
SELECT 0
KEYS authelia-session:*
# Liste les clés de la base 5 (cache CrowdSec)
SELECT 5
KEYS crowdsec:*
🔧 Maintenance et monitoring #
Commandes utiles au quotidien #
Toutes les commandes doivent être exécutées depuis /opt/docker/frontend-stack.
Redémarrer un service #
cd /opt/docker/frontend-stack
# Redémarre un service spécifique
docker compose restart traefik
docker compose restart authelia
docker compose restart crowdsec
Mettre à jour la stack #
cd /opt/docker/frontend-stack
# Récupère les dernières images
docker compose pull
# Reconstruit et redémarre (sans interruption grâce à rolling update)
docker compose up -d
Arrêter la stack #
cd /opt/docker/frontend-stack
# Arrête tous les services (conserve les données)
docker compose down
Sauvegarder les données #
Pensez à sauvegarder les données contenues dans le dossier racine du projet, c’est-à-dire /opt/docker/frontend-stack.
Cela fera l’objet d’un autre article de blog sur la sauvegarde avec l’utilitaire Restic.
Monitoring des ressources #
Utilisation CPU/RAM en temps réel #
# Affiche les stats de tous les conteneurs
docker stats
# Stats d'un seul conteneur
docker stats traefik
Consommation attendue (à vide) :
- Redis : ~10 MB RAM, <1% CPU
- Authelia : ~50-80 MB RAM, <1% CPU
- Traefik : ~40-60 MB RAM, 1-2% CPU
- CrowdSec : ~100-150 MB RAM, 1-3% CPU
Espace disque des volumes #
# Affiche l'espace utilisé par Docker
docker system df -v
# Affiche l'espace utilisé par la stack
du -sh /opt/docker/frontend-stack/*
Logs système (dans le conteneur LXC) #
Vérifiez les journaux système pour détecter des problèmes matériels :
# Logs du daemon Docker (dans le conteneur LXC)
sudo journalctl -u docker -f
Monitoring depuis Proxmox #
Depuis l’interface web Proxmox ou en ligne de commande :
# Affiche les ressources du conteneur LXC 110
pct status 110
# Affiche les statistiques détaillées
pct exec 110 -- top
Nettoyage et maintenance #
Nettoyage sélectif #
# Supprime les images inutilisées (anciennes versions)
docker image prune -a
# Supprime les conteneurs arrêtés
docker container prune
# Supprime les volumes non utilisés
docker volume prune
Nettoyage complet #
# Supprime tout ce qui n'est pas utilisé (conteneurs, images, volumes, networks)
docker system prune -a
# ⚠️ DANGER : Supprime aussi les volumes (perte de données)
docker system prune -a --volumes
docker system prune -a --volumes supprimera TOUTES les données persistantes (Redis, Authelia, CrowdSec). N’utilisez cette commande qu’après une sauvegarde complète.
Rotation des logs #
Les logs Traefik et Authelia peuvent rapidement consommer de l’espace disque. Configurez une rotation automatique via l’utilisature logrotate.
Généralement, cet utilitaire fait parti des packages par défaut de la distribution. Si toutefois, logrotate n’est pas installé sur votre système, installez-le :
sudo apt install -y logrotate
Dans le conteneur LXC, créez le fichier de configuration /etc/logrotate.d/frontend-stack :
vi /etc/logrotate.d/frontend-stack
Contenu :
/opt/docker/frontend-stack/traefik/logs/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d
copytruncate
sharedscripts
create 0644 1000 1000
}
/opt/docker/frontend-stack/authelia/logs/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d
copytruncate
sharedscripts
create 0644 1000 1000
}
Explication de la configuration :
| Directive | Description |
|---|---|
daily |
Rotation quotidienne des logs |
rotate 14 |
Conserve 14 jours d’historique (2 semaines) |
missingok |
Ne génère pas d’erreur si le fichier de log est manquant |
notifempty |
Ne fait pas de rotation si le fichier est vide |
compress |
Compresse les anciens logs avec gzip |
delaycompress |
Compresse le fichier lors de la rotation suivante (pour laisser le temps à CrowdSec de lire les logs) |
dateext |
Ajoute une date au nom du fichier rotaté |
dateformat -%Y%m%d |
Format de date : -20250327 (année-mois-jour) |
copytruncate |
Copie le fichier puis le tronque (évite de devoir recharger les services Docker) |
sharedscripts |
Exécute les scripts post-rotation une seule fois pour tous les fichiers |
create 0644 1000 1000 |
Crée un nouveau fichier avec permissions 0644 et propriétaire 1000:1000 (myuser) |
copytruncate est essentielle ici car elle permet de faire la rotation sans avoir à redémarrer les conteneurs Traefik et Authelia. Les logs continuent d’être écrits dans le même fichier (maintenant vide).
Test de la configuration :
# Test de la configuration logrotate (dry-run)
sudo logrotate -d /etc/logrotate.d/frontend-stack
# Force une rotation manuelle (pour tester)
sudo logrotate -f /etc/logrotate.d/frontend-stack
Monitoring avancé (optionnel) #
Pour un monitoring professionnel, intégrez une stack Prometheus + Grafana :
- Traefik : Exposez les métriques sur un endpoint dédié
- Redis : Utilisez
redis_exporter - CrowdSec : Utilisez les métriques intégrées
- Authelia : Exposez les métriques Prometheus (expérimental)
- Proxmox : Exportez les métriques LXC vers Prometheus
Exemple de dashboard Grafana : https://grafana.com/grafana/dashboards/17346
🔍 Troubleshooting #
Arbre de décision diagnostique #
Utilisez ce diagramme pour diagnostiquer rapidement les problèmes courants :
flowchart TD
Start([Problème détecté]) --> CheckContainers{Tous les conteneurs
sont Up?}
CheckContainers -->|Non| CheckLogs[Vérifier logs
docker compose logs]
CheckContainers -->|Oui| CheckSSL{Certificats SSL
valides?}
CheckLogs --> DockerIssue{Erreur Docker?}
DockerIssue -->|Permissions| FixPerms[Corriger permissions
chown 1000:1000]
DockerIssue -->|Redis| FixRedis[Vérifier mot de passe
Redis]
DockerIssue -->|Network| FixNetwork[Recréer réseau
frontend]
CheckSSL -->|Non| CheckCreds[Vérifier credentials
API DNS .env]
CheckSSL -->|Oui| CheckAuth{Authelia
fonctionne?}
CheckAuth -->|Non| CheckAuthConfig[Vérifier configuration.yml
et secrets]
CheckAuth -->|Oui| CheckCrowdSec{CrowdSec
bloque?}
CheckCrowdSec -->|Oui| UnbanIP[Débannir IP
cscli decisions delete]
CheckCrowdSec -->|Non| CheckTraefik[Vérifier routes Traefik
dashboard :8080]
FixPerms --> Restart[Redémarrer services]
FixRedis --> Restart
FixNetwork --> Restart
CheckCreds --> RestartTraefik[Redémarrer Traefik]
CheckAuthConfig --> RestartAuthelia[Redémarrer Authelia]
UnbanIP --> TestAgain[Retester l'accès]
CheckTraefik --> TestAgain
Restart --> Resolved{Problème
résolu?}
RestartTraefik --> Resolved
RestartAuthelia --> Resolved
TestAgain --> Resolved
Resolved -->|Oui| Success([✓ Production])
Resolved -->|Non| Support[Consulter FAQ
et/ou recherche Internet]
style Start fill:#e1f5ff,color:#000
style Success fill:#d4edda,color:#000
style Support fill:#fff3cd,color:#000
style Resolved fill:#f8d7da,color:#000
Problème 1 : Le conteneur LXC ne peut pas exécuter Docker #
Symptômes :
- Erreur au démarrage de Docker :
Failed to start docker.service - Erreur :
cgroup mountpoint does not exist - Docker démarre mais les conteneurs échouent
Cause probable :
- Fonctionnalités
nestingetkeyctlnon activées sur le conteneur LXC - Conteneur créé en mode privilégié (incompatible avec Docker)
Solution :
- Arrêtez le conteneur LXC :
# Depuis le serveur Proxmox
pct stop 110
- Vérifiez et modifiez la configuration :
# Éditez la configuration du conteneur
vi /etc/pve/lxc/110.conf
Vérifiez que ces lignes sont présentes :
unprivileged: 1
features: nesting=1,keyctl=1
- Redémarrez le conteneur :
pct start 110
- Vérifiez Docker :
pct enter 110
docker --version
systemctl status docker
Comment éviter ce problème :
- Toujours créer les conteneurs LXC pour Docker avec
--unprivileged 0 --features nesting=1,keyctl=1 - Utilisez le template Debian 13 officiel de Proxmox
Problème 2 : Traefik ne génère pas les certificats SSL #
Symptômes :
- Erreur SSL dans le navigateur (“Connexion non sécurisée”)
- Fichier
/opt/docker/frontend-stack/traefik/certs/acme-cloudflare.jsonvide ou avec erreurs - Logs Traefik :
unable to generate a certificate for domains
Cause probable :
- Credentials API DNS incorrects ou manquants
- Propagation DNS trop lente
- Rate limit Let’s Encrypt atteint (5 certificats par domaine/semaine)
- Domaine ne pointe pas vers l’IP correcte
Solution :
- Vérifiez les credentials dans
/opt/docker/frontend-stack/.env:
# Affichez les variables (masquez si nécessaire)
cat /opt/docker/frontend-stack/.env | grep CF_DNS_API_TOKEN
cat /opt/docker/frontend-stack/.env | grep OVH_
- Testez manuellement l’API Cloudflare :
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}"
Réponse attendue : "status": "active"
- Augmentez le délai de propagation DNS dans
/opt/docker/frontend-stack/traefik/config.yml:
dnsChallenge:
provider: cloudflare
propagation:
delayBeforeChecks: 120 # Augmentez à 120 secondes
- Utilisez d’abord le staging (évite rate limit) dans
/opt/docker/frontend-stack/traefik/config.yml:
# Ligne 21
certResolver: cloudflare-staging
Vérifiez que le certificat staging est généré, puis repassez en production.
- Redémarrez Traefik et suivez les logs :
cd /opt/docker/frontend-stack
docker compose restart traefik
docker compose logs -f traefik
Comment éviter ce problème :
- Testez toujours avec le staging avant la production
- Documentez vos credentials API dans un gestionnaire de secrets
- Configurez des alertes sur les expirations de certificats (90 jours)
Problème 3 : Permissions refusées sur les fichiers de configuration #
Symptômes :
- Authelia ne démarre pas :
Permission denied: /config/configuration.yml - CrowdSec ne peut pas lire les logs :
Permission denied: /var/log/traefik/access.log - Erreurs de permissions dans les logs Docker
Cause probable :
- Les fichiers/dossiers n’appartiennent pas à l’utilisateur 1000:1000
- Permissions trop restrictives sur les fichiers
Solution :
- Corrigez les permissions de toute la stack :
# Donne les droits à l'utilisateur 1000:1000 (myuser)
chown -R 1000:1000 /opt/docker/frontend-stack
# Définit les permissions correctes
chmod -R 755 /opt/docker/frontend-stack
chmod 644 /opt/docker/frontend-stack/.env
chmod 644 /opt/docker/frontend-stack/authelia/configuration.yml
chmod 644 /opt/docker/frontend-stack/authelia/users/config.yml
- Vérifiez les permissions :
ls -la /opt/docker/frontend-stack/
ls -la /opt/docker/frontend-stack/authelia/
- Redémarrez les services :
cd /opt/docker/frontend-stack
docker compose restart
Comment éviter ce problème :
- Toujours créer les fichiers en tant qu’utilisateur myuser (UID 1000)
- Utiliser
chown -R 1000:1000après chaque création de fichiers - Vérifier les permissions avant de démarrer la stack
Problème 4 : Redis refuse les connexions (Authelia ou CrowdSec) #
Symptômes :
- Authelia :
Failed to connect to session provider: dial tcp 172.18.0.X:6379: i/o timeout - CrowdSec bouncer :
redis connection refused
Cause probable :
- Mot de passe Redis incorrect
- Redis non démarré ou crashé
- Configuration réseau incorrecte
Solution :
- Vérifiez que Redis est démarré et healthy :
cd /opt/docker/frontend-stack
docker compose ps redis
# Doit afficher "Up" et "healthy"
Si unhealthy ou Restarting :
docker compose logs redis
- Testez la connexion Redis manuellement :
docker exec -it redis redis-cli -a "${REDIS_PASSWORD}" PING
Réponse attendue : PONG
Si erreur NOAUTH → Mot de passe incorrect.
- Vérifiez la cohérence des mots de passe :
/opt/docker/frontend-stack/.env:REDIS_PASSWORD=.../opt/docker/frontend-stack/authelia/configuration.yml:session.redis.password: "..."/opt/docker/frontend-stack/traefik/rules/00-middlewares.yml:redisCachePassword: "..."
Tous doivent être identiques.
- Si Redis ne démarre pas, vérifiez les permissions :
chown -R 999:999 /opt/docker/frontend-stack/redis/data
- Redémarrez dans l’ordre :
cd /opt/docker/frontend-stack
docker compose restart redis
# Attendez 10 secondes (healthcheck)
docker compose restart authelia crowdsec traefik
Comment éviter ce problème :
- Centralisez les mots de passe Redis dans
/opt/docker/frontend-stack/.envuniquement - Testez Redis avec
redis-cli PINGaprès chaque modification - Configurez le healthcheck Redis (déjà présent dans la stack)
FAQ #
Q : Puis-je utiliser cette stack avec Docker Swarm ou Kubernetes ? R : Cette configuration est optimisée pour Docker Compose sur LXC. Pour Swarm, vous devrez adapter les volumes en volumes nommés et les réseaux en overlay. Pour Kubernetes, n’ayant aucune expérience avec cette techno, je vous laisse tester !
Q : Comment sauvegarder le conteneur LXC complet ? R : Depuis Proxmox :
# Crée une sauvegarde complète du conteneur LXC 110
vzdump 110 --dumpdir /var/lib/vz/dump --mode snapshot
Q : Comment migrer la stack vers un autre serveur Proxmox ? R :
- Sauvegardez le conteneur LXC avec
vzdump - Copiez l’archive vers le nouveau serveur Proxmox
- Restaurez le conteneur avec
pct restore - Adaptez la configuration réseau si nécessaire
Q : Quelle est la consommation de ressources totale de la stack ? R : À vide (sans charge) :
- CPU : ~5-10% (2 cœurs)
- RAM : ~500-700 MB
- Disque : ~2-3 GB
En production avec trafic modéré :
- CPU : ~10-20%
- RAM : ~1-2 GB
- Disque : ~5-10 GB (avec logs et données)
Q : Puis-je accéder au dashboard Traefik depuis l’extérieur ? R : Par défaut, non (le port 8080 n’est exposé qu’en local). Pour y accéder en sécurité :
- Option 1 : Tunnel SSH depuis votre poste :
ssh -L 8080:localhost:8080 user@proxmox-host - Option 2 : Protégez-le avec Authelia en créant une route dans
/opt/docker/frontend-stack/traefik/rules/100-frontend.yml
Q : CrowdSec va-t-il me bannir si je me trompe de mot de passe ?
R : Oui, après 3 tentatives échouées en 2 minutes (configuré dans /opt/docker/frontend-stack/authelia/configuration.yml → regulation). Pour vous débannir :
docker exec crowdsec cscli decisions delete --ip VOTRE_IP
Q : Comment ajouter un nouveau service derrière Traefik + Authelia ?
R : Créez un fichier de routage Traefik au format YAML dans /opt/docker/frontend-stack/traefik/rules/ :
http:
routers:
mon-service:
entryPoints:
- websecure
rule: Host(`mon-service.mydomain.com`)
service: mon-service
services:
mon-service:
loadBalancer:
servers:
- url: http://ip-du-service:port
N’oubliez pas d’ajoutez une règle dans /opt/docker/frontend-stack/authelia/configuration.yml pour définir la politique d’accès.
⚡ Optimisations et bonnes pratiques #
Sécurité #
1. Gestion des secrets #
✅ À faire :
- Ne jamais commiter
/opt/docker/frontend-stack/.envou les fichiers avec clés API - Limiter l’accès SSH au conteneur LXC
❌ À éviter :
- Mettre des mots de passe en clair dans
docker-compose.yml - Partager
.envpar email ou chat - Utiliser des mots de passe faibles (< 16 caractères)
2. Durcissement du conteneur LXC #
✅ À faire :
- Limiter les capabilities dans la configuration LXC
- Configurer un pare-feu au niveau de Proxmox (firewall) ou de votre routeur qui gère le réseau
3. Mises à jour de sécurité #
Effectuez les mises à jour sur le serveur régulièrement. Assurez-vous également que les MAJ ne cassent pas la machine LXC comme c’était le cas avec le passage des nouvelles versions de Docker en novembre 2025 pour les conteneurs LXC.
Performance #
1. Optimisation Redis #
Pour un environnement de production avec beaucoup de sessions, éditez /opt/docker/frontend-stack/redis/docker-compose.yml :
command: >
redis-server
--save 900 1 # Sauvegarde moins fréquente
--maxmemory 512mb # Limite mémoire
--maxmemory-policy allkeys-lru # Éviction LRU si plein
2. Optimisation du conteneur LXC #
Allouez plus de ressources si nécessaire :
# Depuis le serveur Proxmox
pct set 110 --memory 8192 # 8 GB de RAM
pct set 110 --cores 4 # 4 cœurs CPU
pct set 110 --rootfs local-lvm:32 # Étend le disque à 32 GB
3. Compression et HTTP/2 #
La compression est déjà activée dans chain-secure. Vérifiez que HTTP/2 est actif :
curl -I --http2 https://mydomain.com | grep HTTP
Réponse attendue : HTTP/2 200
Logs et observabilité #
Configuration recommandée pour les logs #
On a déjà limité la taille des fichiers logs via logrotate mais cette fonctionnalité peut-être déployée via docker compose.
Limitez la taille des logs Docker dans chaque docker-compose.yml :
# À ajouter à chaque service
logging:
driver: "json-file"
options:
max-size: "10m" # Maximum 10 MB par fichier
max-file: "3" # Conserve 3 fichiers (30 MB total)
Bonnes pratiques générales #
✅ À faire :
- Documenter toutes les modifications dans un fichier CHANGELOG
- Sauvegarder le conteneur LXC régulièrement
- Monitorer les métriques (CPU, RAM, logs)
- Configurer des snapshots LXC avant les mises à jour majeures
- Tester en staging (clone LXC) avant production
❌ À éviter :
- Modifier directement en production sans backup
- Utiliser
latesten production (préférez des tags versionnés) - Exposer les dashboards et APIs sans authentification
- Ignorer les mises à jour de sécurité
🎯 Conclusion #
Dans cet article, vous avez appris à :
- Créer et configurer un conteneur LXC Debian 13 sur Proxmox pour héberger Docker
- Déployer une infrastructure frontend complète avec Docker Compose dans
/opt/docker/frontend-stack - Configurer un reverse proxy Traefik avec génération automatique de certificats SSL wildcard
- Mettre en place une authentification avec double facteur via Authelia
- Protéger vos services contre les cyberattaques avec CrowdSec et son AppSec WAF
- Optimiser les performances avec Redis comme cache distribué
- Gérer les permissions avec un utilisateur dédié (UID 1000)
- Maintenir et monitorer votre stack en production sur Proxmox LXC
Cette stack est maintenant prête pour un environnement de production en homelab.
Ressources complémentaires #
Documentation officielle #
- Proxmox VE Documentation
- Traefik Documentation
- Authelia Documentation
- CrowdSec Documentation
- Redis Documentation
Communautés et support #
Besoin d’aide ? #
N’hésitez pas à :
- Laisser un commentaire ci-dessous avec vos questions ou vos compléments, corrections !