# 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.` - **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.` 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." 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./ 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 :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.