Intermediaire 12 min de lecture · 2 482 mots

Authentik sur Proxmox : SSO et authentification centralisée pour tous tes services

Authentik sur Proxmox : SSO et authentification centralisée pour tous tes services
Intermediaire · 2026.07.04

À un moment dans le homelab, tu te retrouves à gérer un carnet de mots de passe qui ressemble à une liste de courses : un pour Proxmox, un pour Gitea, un pour Vaultwarden, un pour Nextcloud, un pour Nginx Proxy Manager, un pour Uptime Kuma. Des comptes locaux dans chaque application, chacun avec ses propres règles de complexité, son propre système de 2FA – ou pas de 2FA du tout. Ce n’est pas une politique de sécurité, c’est du chaos géré à la main.

Authentik résout ça. C’est un Identity Provider (IdP) open source qui supporte OAuth2, OIDC, SAML et LDAP. Tu crées un compte utilisateur unique dans Authentik, tu configures le 2FA une fois, et chaque service que tu connectes hérite de ces protections sans avoir à les reconfigurer. L’audit log centralisé est le bonus que je n’attendais pas : maintenant je vois exactement qui s’est connecté à quoi, depuis où, et quand.

Architecture et contraintes

L’environnement : Proxmox VE 8.3 sur heighliner (MS-01 i9-13900H, 32 Go DDR5-5600). Les services existants tournent en LXC dans le VLAN Serveurs (VLAN 30, plage 10.10.30.0/24). Nginx Proxy Manager est en LXC 102 (10.10.30.102) et joue le rôle de reverse proxy pour tous les services exposés sous *.arewel.com.

Authentik va dans un LXC dédié. Je ne mélange pas avec un LXC existant – Authentik fait tourner PostgreSQL, Redis et son propre process Python. Ça mérite son propre conteneur.

LXC 110, Debian 12.7, 2 vCPU, 2 Go RAM, 20 Go disque, IP 10.10.30.110.

Pourquoi Docker Compose dans un LXC plutôt qu’une VM ? Parce que les LXC sont suffisamment légers pour ça, et que l’overhead d’une VM entière pour un seul service n’est pas justifié ici. Authentik n’a pas besoin d’un kernel isolé.

Authentik peut aussi tourner sur Kubernetes via son chart Helm officiel. Pour un homelab mono-nœud, Docker Compose est le bon choix : moins de pièces mobiles, moins de ressources consommées, maintenance plus simple.

Créer le LXC Authentik

Depuis l’interface Proxmox ou via pct, on crée le LXC avec le template Debian 12 :

# Depuis le shell du nœud Proxmox
pct create 110 /var/lib/vz/template/cache/debian-12-standard_12.7-1_amd64.tar.zst 
  --hostname authentik 
  --memory 2048 
  --cores 2 
  --net0 name=eth0,bridge=vmbr30,ip=10.10.30.110/24,gw=10.10.30.1 
  --storage local-zfs 
  --rootfs local-zfs:20 
  --unprivileged 1 
  --features nesting=1 
  --start 1

L’option --features nesting=1 est indispensable pour faire tourner Docker dans un LXC non privilégié. Sans elle, Docker ne peut pas créer ses namespaces internes et l’installation échoue silencieusement au démarrage des conteneurs.

# Se connecter au LXC
pct exec 110 -- bash

# Mise à jour de base
apt update && apt upgrade -y

# Installer Docker (méthode officielle, dépôt Docker)
apt install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

echo 
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian 
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | 
  tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Préfère docker compose (plugin V2, installé avec docker-compose-plugin) plutôt que docker-compose (V1, Python, déprécié). La syntaxe est identique, les performances sont meilleures.

Installer Authentik via Docker Compose

Authentik fournit un fichier docker-compose.yml de référence. Je l’adapte, je ne l’utilise pas tel quel – notamment pour les chemins de volumes et les variables d’environnement.

mkdir -p /opt/authentik
cd /opt/authentik

Créer le fichier /opt/authentik/.env avec les variables sensibles :

# Générer les secrets
openssl rand -base64 60 | tr -d 'n' > /tmp/secret_key
echo "PG_PASS=$(openssl rand -base64 36 | tr -d 'n')" >> /opt/authentik/.env
echo "AUTHENTIK_SECRET_KEY=$(cat /tmp/secret_key)" >> /opt/authentik/.env
echo "AUTHENTIK_ERROR_REPORTING__ENABLED=false" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__HOST=" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__PORT=587" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__USE_TLS=true" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__USERNAME=" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__PASSWORD=" >> /opt/authentik/.env
echo "AUTHENTIK_EMAIL__FROM=authentik@arewel.com" >> /opt/authentik/.env
rm /tmp/secret_key

Créer /opt/authentik/docker-compose.yml :

services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - /opt/authentik/data/postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${PG_PASS}
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik

  redis:
    image: docker.io/library/redis:alpine
    command: --save 60 1 --loglevel warning
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - /opt/authentik/data/redis:/data

  server:
    image: ghcr.io/goauthentik/server:2024.12.3
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
    volumes:
      - /opt/authentik/data/media:/media
      - /opt/authentik/data/custom-templates:/templates
    env_file:
      - .env
    ports:
      - "9000:9000"
      - "9443:9443"
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

  worker:
    image: ghcr.io/goauthentik/server:2024.12.3
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/authentik/data/media:/media
      - /opt/authentik/data/certs:/certs
      - /opt/authentik/data/custom-templates:/templates
    env_file:
      - .env
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
# Créer les répertoires de données
mkdir -p /opt/authentik/data/{postgres,redis,media,certs,custom-templates}

# Démarrer
cd /opt/authentik
docker compose up -d

# Vérifier que tout démarre (attendre 30-60 sec)
docker compose ps
docker compose logs server | tail -20

Le premier démarrage prend 2-3 minutes : Authentik exécute les migrations PostgreSQL. Ensuite, l’interface est accessible sur http://10.10.30.110:9000/if/flow/initial-setup/ pour créer le compte admin initial.

Ce premier setup crée le compte akadmin avec le mot de passe que tu choisis. Fais-le immédiatement après le démarrage, avant d’exposer Authentik sur internet. N’utilise pas akadmin au quotidien : crée un compte personnel distinct et désactive ou limite akadmin.

Ensuite, Nginx Proxy Manager crée un proxy host pour auth.arewel.com pointant vers 10.10.30.110:9000 (HTTP, pas HTTPS en interne – NPM gère le TLS en aval).

Configurer Proxmox VE avec OAuth2

C’est la configuration que j’aurais voulu trouver documentée clairement, parce que j’ai perdu 40 minutes sur un détail.

Côté Authentik : créer le Provider et l’Application

Dans l’interface Authentik (https://auth.arewel.com) :

Applications > Providers > Créer > OAuth2/OpenID Provider

  • Name : Proxmox VE
  • Client type : Confidential
  • Redirect URIs : https://heighliner.arewel.com:8006
  • Voilà le piège : Proxmox s’attend à une URL de redirection sans trailing slash et sans chemin supplémentaire. J’avais mis https://heighliner.arewel.com:8006/ (avec le slash final) et https://heighliner.arewel.com:8006/api2/json/access/openid/auth-url dans une tentative de débogage. Aucun des deux ne fonctionnait. La bonne valeur est simplement https://heighliner.arewel.com:8006 – ni slash final, ni chemin.

  • Signing Key : authentik Self-signed Certificate (ou ton certificat)
  • Scopes : email, openid, profile
  • Après la création du Provider, noter le Client ID et le Client Secret affichés.

    Créer ensuite l’Application qui lie le Provider :

    Applications > Applications > Créer

  • Name : Proxmox VE
  • Slug : proxmox-ve
  • Provider : Proxmox VE (celui qu’on vient de créer)
  • Côté Proxmox VE : configurer le Realm OpenID

    Dans Proxmox (Datacenter > Permissions > Realms > Add > OpenID Connect Server) :

    Champ Valeur
    Realm authentik
    Issuer URL https://auth.arewel.com/application/o/proxmox-ve/
    Client ID IDCOPIÉ>
    Client Key SECRETCOPIÉ>
    Username Claim email
    Autocreate Users Coché (optionnel)
    Default Non (garde le realm local par défaut)

    L’Issuer URL se trouve dans Authentik : Applications > Providers > ton provider > cliquer sur « OpenID Configuration ». Le champ issuer dans la réponse JSON est l’URL à copier dans Proxmox.

    Après validation, tester depuis la page de login Proxmox : sélectionner le realm authentik dans le dropdown. Tu dois être redirigé vers la page de login Authentik, t’authentifier, puis revenir dans Proxmox. Si Proxmox affiche une erreur de redirection URI, relis l’URL configurée dans le Provider Authentik – c’est quasi-certainement là le problème.

    Forward Auth via Nginx Proxy Manager

    Pour les services sans authentification native (Uptime Kuma dans ma config), Authentik peut jouer le rôle de proxy d’authentification via la fonctionnalité « Forward Auth » de NPM.

    Côté Authentik : créer un Provider et une Application Proxy

    Applications > Providers > Créer > Proxy Provider

  • Name : Uptime Kuma Forward Auth
  • Authorization flow : default-provider-authorization-implicit-consent
  • Type : Forward auth (single application)
  • External Host : https://uptime.arewel.com

Créer l’Application correspondante (slug : uptime-kuma).

Il faut aussi ajouter le middleware Authentik dans Authentik lui-même. Dans Admin Interface > Outposts, vérifier qu’un Outpost de type « Proxy » existe et qu’il inclut ce nouveau Provider.

Côté Nginx Proxy Manager : configurer le Forward Auth

Dans NPM, sur le proxy host d’Uptime Kuma, onglet « Advanced », ajouter dans « Custom Nginx Configuration » :

location /outpost.goauthentik.io {
    proxy_pass          https://auth.arewel.com;
    proxy_set_header    Host $host;
    proxy_set_header    X-Original-URL $scheme://$http_host$request_uri;
    add_header          Set-Cookie $auth_cookie;
    auth_request_set    $auth_cookie $upstream_http_set_cookie;
    proxy_pass_request_body off;
    proxy_set_header    Content-Length "";
}

location / {
    auth_request        /outpost.goauthentik.io/outpost.goauthentik.io/auth/nginx;
    error_page          401 = @goauthentik_proxy_signin;
    auth_request_set    $auth_cookie $upstream_http_set_cookie;
    add_header          Set-Cookie $auth_cookie;
    auth_request_set    $user $upstream_http_x_authentik_username;
    auth_request_set    $groups $upstream_http_x_authentik_groups;
    auth_request_set    $email $upstream_http_x_authentik_email;
    auth_request_set    $name $upstream_http_x_authentik_name;
    auth_request_set    $uid $upstream_http_x_authentik_uid;
    proxy_set_header    X-authentik-username $user;
    proxy_set_header    X-authentik-groups $groups;
    proxy_set_header    X-authentik-email $email;
    proxy_set_header    X-authentik-name $name;
    proxy_set_header    X-authentik-uid $uid;
    proxy_pass          http://10.10.30.105:3001;
}

location @goauthentik_proxy_signin {
    internal;
    add_header Set-Cookie $auth_cookie;
    return 302 /outpost.goauthentik.io/outpost.goauthentik.io/start?rd=$request_uri;
}

Ce bloc Nginx est spécifique à NPM – il ne fonctionnera pas tel quel avec Traefik ou Caddy qui ont leurs propres mécanismes de Forward Auth. Les blocs location personnalisés dans NPM s’ajoutent après la configuration générée automatiquement, donc certaines directives comme proxypass principale doivent être dans le bloc location / personnalisé et non dans le champ « Forward Hostname » de NPM.

Nextcloud et OpenID Connect

Nextcloud supporte OIDC via l’application officielle « Social Login » ou « OpenID Connect user backend ». Je préfère « OpenID Connect user backend » (app ID : useroidc) – elle est maintenue par l’équipe Nextcloud et s’intègre proprement.

# Dans le LXC Nextcloud (LXC 106)
su -s /bin/sh www-data -c "php /var/www/html/occ app:install user_oidc"
su -s /bin/sh www-data -c "php /var/www/html/occ app:enable user_oidc"

Dans Nextcloud Admin > OpenID Connect, ajouter un provider :

Champ Valeur
Identifier Authentik
Client ID ID> (nouveau provider créé dans Authentik)
Client secret SECRET>
Discovery endpoint https://auth.arewel.com/application/o/nextcloud/.well-known/openid-configuration
Scope openid email profile

Côté Authentik, créer un Provider OAuth2/OIDC avec le Redirect URI exact de Nextcloud :

https://cloud.arewel.com/apps/user_oidc/code

Le mapping des attributs dans Authentik → Nextcloud : le claim email devient le username Nextcloud si l’option « Use unique user ID » est activée. C’est le comportement que je veux : l’email sert d’identifiant stable, et changer le display name dans Authentik se propage à Nextcloud.

Si des comptes Nextcloud locaux existent déjà avec le même email, useroidc va créer des comptes doublons ou échouer selon la configuration. Faire la migration proprement : soit supprimer les comptes locaux après avoir vérifié que le login OIDC fonctionne, soit utiliser la commande occ useroidc:migrate-user-accounts si disponible dans ta version.

Ce qui a coincé

Le redirect URI dans Proxmox, donc. Quarante minutes sur une barre oblique. La deuxième friction : l’Outpost Authentik pour le Forward Auth NPM. L’Outpost doit être configuré avec l’URL externe d’Authentik (celle accessible depuis le navigateur du client), pas l’URL interne du LXC. Si NPM contacte Authentik en interne (10.10.30.110:9000) mais que les redirects de l’Outpost pointent vers https://auth.arewel.com, les cookies de session ne correspondent pas et l’authentification boucle.

La troisième friction, moins documentée : le certificat auto-signé. Proxmox VE refuse de valider un IdP OIDC avec un certificat non trusted. Solutions : utiliser un vrai certificat (Let’s Encrypt via NPM, ce que j’ai fait), ou ajouter le certificat Authentik dans le trust store de Proxmox via /usr/local/share/ca-certificates/ et update-ca-certificates. La première option est plus simple.

Résultat

Un compte utilisateur, un 2FA (TOTP via l’app Authentik), et tous les services protégés. L’audit log dans Authentik (Events > Logs) montre chaque connexion avec IP source, navigateur, application, et résultat (succès ou échec). Pour un homelab, c’est largement suffisant pour détecter une tentative de connexion suspecte.

La gestion des sessions centralisée a un effet secondaire que j’apprécie : si je révoque une session dans Authentik, le token OIDC est invalidé et l’utilisateur est déconnecté de toutes les applications qui vérifient la validité du token. C’est le comportement qu’on attend d’un vrai SSO.

La consommation mémoire du LXC Authentik en charge normale : environ 900 Mo pour l’ensemble PostgreSQL + Redis + server + worker. Le plafond à 2 Go est confortable.

Ce que je n’ai pas fait encore : les groupes Authentik pour différencier les droits selon les applications (admin Proxmox vs. utilisateur lecture seule). C’est dans la roadmap – la granularité de contrôle d’Authentik sur les scopes et les attributs propagés est bien meilleure que la gestion locale application par application.


slug: authentik-sso-proxmox
meta: Installer Authentik sur un LXC Proxmox et configurer le SSO OAuth2/OIDC pour Proxmox VE, Nginx Proxy Manager et Nextcloud – avec les vrais pièges documentés.
tags: authentik, sso, oauth2, oidc, proxmox, homelab, nginx-proxy-manager, nextcloud, securite

Une remarque, un retour ?

Cet article est vivant - corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.

Laisser un commentaire