202 lines
5.3 KiB
Markdown
202 lines
5.3 KiB
Markdown
# Auth Stack — LLDAP + Authelia + Redis (DSM 7.3 / Synology DS220+)
|
||
|
||
## Objectif
|
||
Fournir une pile d’authentification robuste (anti-lockout) pour protéger des services web via reverse-proxy :
|
||
- Annuaire utilisateurs : **LLDAP**
|
||
- Portail / SSO / MFA : **Authelia**
|
||
- Cache/sessions (optionnel selon config) : **Redis**
|
||
- Exposition publique : **Reverse proxy** (Synology / Nginx / Traefik) vers Authelia
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
### Composants
|
||
- **LLDAP**
|
||
- UI admin (HTTP) : `127.0.0.1:17170`
|
||
- LDAP : `127.0.0.1:3890`
|
||
- Base : sqlite dans `/volume2/docker/auth/data/lldap`
|
||
|
||
- **Authelia**
|
||
- API/portal : `127.0.0.1:9091`
|
||
- Stockage : sqlite dans `/volume2/docker/auth/data/authelia/db.sqlite3`
|
||
- Accès externe : via reverse proxy -> `https://auth.<domaine>`
|
||
|
||
- **Redis**
|
||
- Local uniquement : `127.0.0.1:6379`
|
||
- (peut servir plus tard à sessions/rate-limit selon config)
|
||
|
||
### Exposition réseau (principe de sécurité)
|
||
- Tous les services **bindés sur 127.0.0.1** (loopback NAS)
|
||
- Seul le **reverse proxy** expose `https://auth.<domaine>` vers `127.0.0.1:9091`
|
||
|
||
---
|
||
|
||
## Fichiers de référence
|
||
|
||
### 1) docker-compose.auth.yml
|
||
- Déploie redis + lldap + authelia.
|
||
- Recommandation DSM : **network_mode: host** + bind sur localhost.
|
||
- Supprime les aléas “bridge + DNS + subnets”
|
||
- Évite les timeouts LDAP sporadiques.
|
||
|
||
### 2) /volume2/docker/auth/compose/.env
|
||
Variables attendues :
|
||
|
||
#### LLDAP
|
||
- `LLDAP_JWT_SECRET=...` (random 32+)
|
||
- `LLDAP_KEY_SEED=...` (random 32+)
|
||
- `LLDAP_LDAP_USER_PASS=...` (mot de passe admin LLDAP)
|
||
|
||
#### Authelia
|
||
- `AUTHELIA_JWT_SECRET=...` (utilisé ici comme source pour reset_password)
|
||
- `AUTHELIA_SESSION_SECRET=...`
|
||
- `AUTHELIA_STORAGE_ENCRYPTION_KEY=...`
|
||
|
||
> Ne jamais committer `.env`. Stocker dans DSM / secrets.
|
||
|
||
### 3) /volume2/docker/auth/config/authelia/configuration.yml
|
||
- LDAP address en mode robuste : `ldap://127.0.0.1:3890`
|
||
- Cookie domain : `archicratie.trans-hands.synology.me`
|
||
- `authelia_url` : `https://auth.archicratie.trans-hands.synology.me`
|
||
- `default_redirection_url` : service principal (ex: gitea)
|
||
|
||
---
|
||
|
||
## Procédures opératoires
|
||
|
||
### Restart safe (redémarrage propre)
|
||
en bash :
|
||
cd /volume2/docker/auth/compose
|
||
sudo docker compose --env-file .env -f docker-compose.auth.yml down --remove-orphans
|
||
sudo docker compose --env-file .env -f docker-compose.auth.yml up -d --force-recreate
|
||
|
||
### Tests santé (sans dépendances DSM)
|
||
curl -fsS http://127.0.0.1:17170/ >/dev/null && echo "LLDAP UI OK"
|
||
curl -fsS http://127.0.0.1:9091/api/health && echo "AUTHELIA LOCAL OK"
|
||
curl -kfsS https://auth.archicratie.trans-hands.synology.me/api/health && echo "AUTHELIA HTTPS OK"
|
||
|
||
### Test TCP LDAP :
|
||
sudo docker run --rm --network host nicolaka/netshoot:latest sh -lc 'nc -vz -w2 127.0.0.1 3890'
|
||
|
||
### Rotate secrets (rotation)
|
||
|
||
# Principes :
|
||
|
||
Rotation = redémarrage forcé d’Authelia (sessions invalidées)
|
||
|
||
Rotation de LLDAP_KEY_SEED est sensible : peut affecter chiffrement des mots de passe.
|
||
|
||
# Procédure conseillée :
|
||
|
||
Sauvegarder DBs :
|
||
|
||
/volume2/docker/auth/data/lldap/users.db
|
||
|
||
/volume2/docker/auth/data/authelia/db.sqlite3
|
||
|
||
Changer d’abord secrets Authelia (AUTHELIA_SESSION_SECRET, AUTHELIA_STORAGE_ENCRYPTION_KEY)
|
||
|
||
docker compose up -d --force-recreate authelia
|
||
|
||
Vérifier /api/health + login.
|
||
|
||
Reset admin LLDAP (break-glass)
|
||
|
||
# Si tu perds le mot de passe admin :
|
||
|
||
Activer temporairement LLDAP_FORCE_LDAP_USER_PASS_RESET=true dans l’environnement LLDAP
|
||
|
||
Redémarrer LLDAP une seule fois
|
||
|
||
Désactiver immédiatement après.
|
||
|
||
⚠️ Ne jamais laisser ce flag en permanence : il force le reset à chaque boot.
|
||
|
||
## Checklist anti-lockout (indispensable)
|
||
### 1) Accès direct local (bypass)
|
||
|
||
LLDAP UI accessible en local : http://127.0.0.1:17170
|
||
|
||
Authelia health local : http://127.0.0.1:9091/api/health
|
||
|
||
### 2) Règle Authelia : domaine auth en bypass
|
||
|
||
Dans configuration.yml :
|
||
access_control:
|
||
rules:
|
||
- domain: "auth.<domaine>"
|
||
policy: bypass
|
||
|
||
But : pouvoir charger le portail même si les règles des autres domaines cassent.
|
||
|
||
### 3) Route de secours reverse-proxy
|
||
|
||
Prévoir une route non protégée (ou protégée différemment) pour pouvoir corriger :
|
||
|
||
ex: https://admin.<domaine>/ ou un vhost interne LAN-only.
|
||
|
||
### 4) Fenêtre privée pour tester
|
||
|
||
Toujours tester login/authelia dans un onglet privé pour éviter cookies “fantômes”.
|
||
|
||
## Troubleshooting (ce qu’on a rencontré et résolu)
|
||
### A) YAML/Compose cassé (tabs, doublons)
|
||
|
||
# Symptômes :
|
||
|
||
mapping key "ports" already defined
|
||
|
||
found character that cannot start any token
|
||
|
||
# Fix :
|
||
|
||
supprimer tabs
|
||
|
||
supprimer doublons (volumes/ports/networks)
|
||
|
||
valider : docker compose ... config
|
||
|
||
### B) Substitution foireuse des variables dans healthcheck
|
||
|
||
# Problème :
|
||
|
||
$VAR évalué par compose au parse-time
|
||
|
||
# Fix :
|
||
|
||
utiliser $$VAR dans CMD-SHELL si nécessaire.
|
||
|
||
### C) /config monté read-only
|
||
|
||
# Symptômes :
|
||
|
||
chown: /config/... Read-only file system
|
||
|
||
# Fix :
|
||
|
||
monter /config en :rw si Authelia doit écrire des backups/keys.
|
||
|
||
### D) Timeouts LDAP aléatoires en bridge
|
||
|
||
# Symptômes :
|
||
|
||
dial tcp <ip>:3890: i/o timeout
|
||
|
||
IP Docker “surprise” (subnet 192.168.32.0/20 etc.)
|
||
|
||
# Fix robuste DSM :
|
||
|
||
passer en network_mode: host + bind 127.0.0.1
|
||
|
||
Authelia -> ldap://127.0.0.1:3890
|
||
|
||
### E) “Authelia OK mais Gitea redemande login”
|
||
|
||
# Normal :
|
||
|
||
tant que Gitea n’est pas configuré en OIDC vers Authelia, ce n’est pas du SSO.
|
||
|
||
Authelia protège l’accès, mais ne crée pas de session Gitea.
|
||
|