Authelia : SSO et 2FA pour services self-hosted

Authelia : SSO et 2FA pour services self-hosted

Centralisez l'authentification de tous vos services (Nginx Proxy Manager, Grafana, Portainer, etc.) derrière un seul login Authelia avec 2FA TOTP/WebAuthn. Single Sign-On open-source qui remplace une auth basique HTTP par une vraie passerelle de sécurité.

Introduction

Plus vous hébergez de services (Portainer, Grafana, Uptime Kuma, NextCloud, Vaultwarden...), plus vous multipliez les comptes et mots de passe. Authelia résout ce problème :

  • Un seul login pour tous vos services
  • 2FA TOTP (Google Authenticator) ou WebAuthn (YubiKey, Touch ID)
  • Politiques par URL (ex: /admin requiert 2FA, /public accessible librement)
  • Whitelist IP intégrée
  • Brute-force protection intégrée

Authelia se place devant votre reverse proxy (Nginx, Traefik, Caddy) et intercepte les requêtes pour vérifier l'authentification.

Prérequis

  • VPS Debian 12 / Ubuntu 22.04+
  • Docker + Docker Compose installés
  • Un reverse proxy (Nginx ou Traefik) déjà en place
  • Un nom de domaine avec sous-domaine pour Authelia (ex: auth.votre-domaine.com)

Étape 1 : Préparer la structure

sudo mkdir -p /opt/authelia/{config,secrets}
cd /opt/authelia

Étape 2 : Générer les secrets

Authelia a besoin de plusieurs secrets cryptographiques. Générez-les :

cd /opt/authelia/secrets

# Secret JWT (sessions)
openssl rand -base64 64 > JWT_SECRET

# Clé de session
openssl rand -base64 64 > SESSION_SECRET

# Clé de chiffrement BD
openssl rand -base64 64 > STORAGE_ENCRYPTION_KEY

# Mot de passe Redis (sera utilisé plus tard)
openssl rand -base64 32 > REDIS_PASSWORD

# Permissions
chmod 600 *

Étape 3 : Fichier configuration.yml

sudo nano /opt/authelia/config/configuration.yml

Contenu minimal :

# Serveur
server:
  address: 'tcp://0.0.0.0:9091'

# Logs
log:
  level: 'info'

# TOTP
totp:
  issuer: 'verycloud.fr'

# Authentification - on utilise un fichier YAML local pour la démo
authentication_backend:
  file:
    path: '/config/users_database.yml'

# Access Control - règles par URL
access_control:
  default_policy: 'deny'
  rules:
    # Auth UI elle-même
    - domain: 'auth.votre-domaine.com'
      policy: 'bypass'
    
    # Services protégés (2FA obligatoire)
    - domain: 'grafana.votre-domaine.com'
      policy: 'two_factor'
    
    - domain: 'portainer.votre-domaine.com'
      policy: 'two_factor'
    
    # Service où le 1FA suffit
    - domain: 'kuma.votre-domaine.com'
      policy: 'one_factor'

# Sessions (stockées dans Redis)
session:
  name: 'authelia_session'
  expiration: '1h'
  inactivity: '5m'
  remember_me: '1M'
  cookies:
    - domain: 'votre-domaine.com'
      authelia_url: 'https://auth.votre-domaine.com'
  redis:
    host: 'redis'
    port: 6379

# Protection brute-force
regulation:
  max_retries: 3
  find_time: '2m'
  ban_time: '5m'

# Stockage des données (SQLite pour la simplicité)
storage:
  local:
    path: '/config/db.sqlite3'

# Notifier (envoi des codes par email)
notifier:
  filesystem:
    filename: '/config/notifications.txt'
  # Pour SMTP réel :
  # smtp:
  #   host: 'mail.votre-domaine.com'
  #   port: 587
  #   username: '[email protected]'
  #   password: 'password'
  #   sender: '[email protected]'

Étape 4 : Créer la base utilisateurs

sudo nano /opt/authelia/config/users_database.yml

Format :

users:
  mathys:
    disabled: false
    displayname: "Mathys"
    password: "$argon2id$v=19$m=65536,t=3,p=4$..." # voir étape suivante
    email: "[email protected]"
    groups:
      - "admin"
      - "users"

Générer le hash du mot de passe

sudo docker run --rm authelia/authelia:latest authelia crypto hash generate argon2

Entrez votre mot de passe. Copiez le hash résultant et collez-le dans users_database.yml.

Étape 5 : Docker Compose

sudo nano /opt/authelia/docker-compose.yml
services:
  authelia:
    image: authelia/authelia:latest
    container_name: authelia
    restart: unless-stopped
    volumes:
      - ./config:/config
    environment:
      - TZ=Europe/Paris
      - AUTHELIA_JWT_SECRET_FILE=/secrets/JWT_SECRET
      - AUTHELIA_SESSION_SECRET_FILE=/secrets/SESSION_SECRET
      - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/secrets/STORAGE_ENCRYPTION_KEY
      - AUTHELIA_SESSION_REDIS_PASSWORD_FILE=/secrets/REDIS_PASSWORD
    secrets:
      - JWT_SECRET
      - SESSION_SECRET
      - STORAGE_ENCRYPTION_KEY
      - REDIS_PASSWORD
    ports:
      - "9091:9091"
    depends_on:
      - redis

  redis:
    image: redis:alpine
    container_name: authelia-redis
    restart: unless-stopped
    command: >
      sh -c 'redis-server --requirepass "$$(cat /run/secrets/REDIS_PASSWORD)"'
    secrets:
      - REDIS_PASSWORD
    volumes:
      - ./redis-data:/data

secrets:
  JWT_SECRET:
    file: ./secrets/JWT_SECRET
  SESSION_SECRET:
    file: ./secrets/SESSION_SECRET
  STORAGE_ENCRYPTION_KEY:
    file: ./secrets/STORAGE_ENCRYPTION_KEY
  REDIS_PASSWORD:
    file: ./secrets/REDIS_PASSWORD

Démarrez :

sudo docker compose up -d
sudo docker compose logs -f authelia

Étape 6 : Reverse proxy Nginx

Authelia s'intègre via le forwardAuth ou le snippet Nginx.

sudo nano /etc/nginx/snippets/authelia.conf
# Endpoint d'autorisation
location /authelia {
    internal;
    set $upstream_authelia http://127.0.0.1:9091/api/verify;
    proxy_pass_request_body off;
    proxy_pass $upstream_authelia;
    proxy_set_header Content-Length "";

    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
    proxy_set_header X-Forwarded-Method $request_method;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Uri $request_uri;
    proxy_set_header X-Forwarded-For $remote_addr;
}

Site auth.votre-domaine.com

sudo nano /etc/nginx/sites-available/authelia
server {
    listen 443 ssl http2;
    server_name auth.votre-domaine.com;

    ssl_certificate /etc/letsencrypt/live/auth.votre-domaine.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.votre-domaine.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9091;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Protéger un service existant (ex: Grafana)

sudo nano /etc/nginx/sites-available/grafana
server {
    listen 443 ssl http2;
    server_name grafana.votre-domaine.com;

    ssl_certificate /etc/letsencrypt/live/grafana.votre-domaine.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/grafana.votre-domaine.com/privkey.pem;

    include /etc/nginx/snippets/authelia.conf;

    location / {
        # Vérification Authelia avant chaque requête
        auth_request /authelia;
        auth_request_set $target_url $scheme://$http_host$request_uri;
        auth_request_set $user $upstream_http_remote_user;
        auth_request_set $groups $upstream_http_remote_groups;
        error_page 401 =302 https://auth.votre-domaine.com/?rd=$target_url;

        proxy_set_header Remote-User $user;
        proxy_set_header Remote-Groups $groups;

        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
    }
}

Rechargez :

sudo nginx -t && sudo systemctl reload nginx

Étape 7 : Obtenir les certificats SSL

sudo certbot --nginx -d auth.votre-domaine.com -d grafana.votre-domaine.com

Étape 8 : Premier login

Ouvrez https://grafana.votre-domaine.com → vous êtes redirigé vers Authelia.

Connectez-vous avec votre login/password. Authelia vous propose d'enrôler le 2FA :

  1. Cliquez sur Enroll TOTP
  2. Authelia envoie un email avec un lien (ou écrit dans /config/notifications.txt si vous avez gardé le notifier filesystem)
  3. Cliquez sur le lien → QR code → scannez avec votre app
  4. Entrez le premier code TOTP pour valider

À partir de maintenant, vous êtes connecté à Grafana automatiquement.

Étape 9 : Ajouter WebAuthn (YubiKey, Touch ID)

Plus sûr que TOTP. Dans configuration.yml :

webauthn:
  display_name: 'VeryCloud Authelia'
  attestation_conveyance_preference: 'indirect'
  user_verification: 'preferred'
  timeout: '60s'

Et créez une règle qui exige WebAuthn :

access_control:
  rules:
    - domain: 'admin.votre-domaine.com'
      policy: 'two_factor'
      methods: ['webauthn']

Côté utilisateur, dans Authelia → Méthodes 2FA → Enrôler une clé de sécurité.

Étape 10 : Backend LDAP / Active Directory (avancé)

Pour gérer des dizaines d'utilisateurs, remplacez le file backend par LDAP :

authentication_backend:
  ldap:
    url: 'ldap://ldap.votre-domaine.com'
    base_dn: 'dc=verycloud,dc=fr'
    username_attribute: 'uid'
    additional_users_dn: 'ou=people'
    users_filter: '(&({username_attribute}={input})(objectClass=person))'
    additional_groups_dn: 'ou=groups'
    groups_filter: '(member={dn})'
    group_name_attribute: 'cn'
    mail_attribute: 'mail'
    user: 'cn=admin,dc=verycloud,dc=fr'
    password: 'admin_password'

Dépannage

Boucle de redirection sur Authelia

Souvent dû à des cookies de session mal configurés. Vérifiez que domain dans session.cookies correspond bien à votre domaine racine (votre-domaine.com et pas auth.votre-domaine.com).

"Authentication required" en boucle

Le snippet authelia.conf n'est pas chargé. Vérifiez l'include dans la config Nginx du service.

Le code TOTP est rejeté

L'horloge du VPS est désynchronisée :

sudo systemctl status chrony
sudo chronyc tracking

Permission denied sur les secrets

sudo chown -R 1000:1000 /opt/authelia/secrets
sudo chmod 600 /opt/authelia/secrets/*

Commandes utiles

# Statut Authelia
sudo docker compose ps

# Logs
sudo docker compose logs -f authelia

# Recharger config sans restart
sudo docker compose kill -s HUP authelia

# Tester la config
sudo docker compose exec authelia authelia validate-config

# Lister les utilisateurs
sudo cat /opt/authelia/config/users_database.yml

# Réinitialiser le 2FA d'un user (supprimer leur enregistrement)
sudo docker compose exec authelia sqlite3 /config/db.sqlite3 "DELETE FROM totp_configurations WHERE username='mathys';"

Conclusion

Authelia transforme votre infra self-hosted en environnement professionnel avec SSO et 2FA. Bénéfices :

  • Un seul mot de passe à retenir
  • 2FA obligatoire sur les services critiques
  • Whitelist IP par règle
  • Audit logs complets

Pour aller plus loin :

  • Migrez vers LLDAP (LDAP léger) pour la gestion multi-users
  • Intégrez avec Vaultwarden pour stocker les mots de passe
  • Ajoutez WebAuthn avec YubiKey pour les comptes admin
  • Combinez avec Cloudflare Zero Trust pour une protection en couches

Ressources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members