<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on Mook’s Lab Chronicles</title><link>https://blog.homeblack.fr/tags/docker/</link><description>Recent content in Docker on Mook’s Lab Chronicles</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><lastBuildDate>Fri, 31 Jul 2026 15:06:16 +0200</lastBuildDate><atom:link href="https://blog.homeblack.fr/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Authentik, la porte d’entrée de mon homelab — et le ménage qui lui manquait</title><link>https://blog.homeblack.fr/p/authentik-sso-homelab/</link><pubDate>Fri, 31 Jul 2026 15:06:16 +0200</pubDate><guid>https://blog.homeblack.fr/p/authentik-sso-homelab/</guid><description>&lt;img src="https://blog.homeblack.fr/p/authentik-sso-homelab/cover.png" alt="Featured image of post Authentik, la porte d’entrée de mon homelab — et le ménage qui lui manquait" /&gt;&lt;p&gt;Je voulais gagner quelques millisecondes sur mes connexions. En ouvrant la VM d’Authentik, j’ai surtout trouvé un petit musée de son histoire : un conteneur Redis devenu inutile, deux fichiers d’environnement presque identiques et des images Docker accumulées.&lt;/p&gt;
&lt;p&gt;Comme le service tournait bien, j’avais laissé cette sédimentation vivre tranquillement. Pas idéal pour celui qui garde la porte de presque tout mon homelab. Cette maintenance était donc l’occasion de faire le ménage, mais aussi de présenter enfin Authentik sur ce blog.&lt;/p&gt;
&lt;h2 id="bien-plus-quune-jolie-page-de-connexion"&gt;Bien plus qu’une jolie page de connexion
&lt;/h2&gt;&lt;p&gt;SSO signifie &lt;em&gt;Single Sign-On&lt;/em&gt;, ou authentification unique. Le raccourci habituel consiste à dire : « un seul compte pour toutes mes applications ». C’est vrai, mais ce n’est pas le point le plus important.&lt;/p&gt;
&lt;p&gt;Une application raccordée à Authentik ne reçoit pas mon mot de passe. Elle délègue l’authentification à un fournisseur d’identité — un &lt;em&gt;Identity Provider&lt;/em&gt; ou IdP — puis fait confiance au jeton ou à l’assertion qu’il lui retourne. Je peux donc centraliser la double authentification, les groupes, les règles d’accès et le cycle de vie des comptes sans recopier la même logique dans chaque service.&lt;/p&gt;
&lt;p&gt;Au 31 juillet 2026, mon instance contient 21 applications. La majorité utilise OpenID Connect (OIDC), notamment GitLab, Grafana, Warpgate, Technitium et PatchMon. Wazuh passe par SAML. Pour OpenVSCode, qui n’a pas le même raccordement natif, nginx demande directement à l’outpost Proxy d’Authentik si la requête peut continuer.&lt;/p&gt;
&lt;p&gt;Cette souplesse est l’une des raisons pour lesquelles Authentik s’est imposé chez moi. Je privilégie OIDC lorsqu’il est disponible, SAML lorsque l’application l’impose et le &lt;a class="link" href="https://docs.goauthentik.io/add-secure-apps/providers/proxy/create-proxy-provider/" target="_blank" rel="noopener"
&gt;provider Proxy&lt;/a&gt; pour les services qui ne savent rien faire de tout cela.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GitLab ─────────────── OIDC ──────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Grafana ────────────── OIDC ──────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warpgate ───────────── OIDC ──────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Wazuh ──────────────── SAML ──────┼──&amp;gt; Authentik ──&amp;gt; identité, MFA, groupes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OpenVSCode ── nginx / forward auth ┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le confort est évident : une seule session ouvre plusieurs outils et je n’administre plus une collection de comptes locaux oubliés. Le revers l’est tout autant : Authentik est devenu une dépendance critique. Une panne n’arrête pas forcément les sessions déjà ouvertes, mais elle peut bloquer toute nouvelle connexion. Une compromission aurait, elle, un rayon d’action particulièrement généreux.&lt;/p&gt;
&lt;p&gt;Je le traite donc comme une brique de sécurité, pas comme un tableau de bord de plus.&lt;/p&gt;
&lt;h2 id="pourquoi-authentik-plutôt-que-keycloak-"&gt;Pourquoi Authentik plutôt que Keycloak ?
&lt;/h2&gt;&lt;p&gt;J’ai longtemps hésité avec Keycloak. Il avait pour lui l’ancienneté, une documentation abondante et un écosystème déjà installé. &lt;a class="link" href="https://api.github.com/repos/keycloak/keycloak" target="_blank" rel="noopener"
&gt;Son dépôt public remonte à 2013&lt;/a&gt;, alors que &lt;a class="link" href="https://goauthentik.io/blog/2023-11-1-happy-birthday-to-us/" target="_blank" rel="noopener"
&gt;le premier commit d’Authentik date de 2018&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Choisir Authentik revenait donc à miser sur le plus jeune. Son interface et ses flows me parlaient davantage, son proxy intégré convenait bien au mélange d’applications modernes et de vieux services de mon homelab, et je me sentais plus à l’aise avec un cœur Python/Django qu’avec une JVM.&lt;/p&gt;
&lt;p&gt;Ce n’est pas un verdict contre Java : Keycloak fonctionne sur Quarkus et propose un &lt;a class="link" href="https://www.keycloak.org/server/configuration" target="_blank" rel="noopener"
&gt;build optimisé&lt;/a&gt;. Authentik n’est pas spécialement léger non plus avec son serveur, son worker, PostgreSQL et ses éventuels outposts. Mon choix était surtout pratique : lequel aurais-je envie de comprendre et de dépanner pendant plusieurs années ? Pour moi, la réponse était Authentik.&lt;/p&gt;
&lt;h2 id="un-projet-qui-a-mûri"&gt;Un projet qui a mûri
&lt;/h2&gt;&lt;p&gt;Les premières versions que j’ai suivies demandaient davantage de prudence : migrations sensibles, interface mouvante et notes de version à lire religieusement. Depuis la création d’Authentik Security en 2022, le projet a changé d’échelle et adopté un modèle &lt;em&gt;open core&lt;/em&gt;, avec les protocoles essentiels toujours disponibles dans &lt;a class="link" href="https://goauthentik.io/pricing/" target="_blank" rel="noopener"
&gt;l’édition open source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Au 31 juillet 2026, &lt;a class="link" href="https://api.github.com/repos/goauthentik/authentik" target="_blank" rel="noopener"
&gt;le dépôt GitHub&lt;/a&gt; affichait 22 563 étoiles et une activité le jour même. La &lt;a class="link" href="https://github.com/goauthentik/authentik/releases/tag/version/2026.5.6" target="_blank" rel="noopener"
&gt;version 2026.5.6&lt;/a&gt; datait du 22 juillet. Ces chiffres ne prouvent pas la qualité du logiciel, mais ils confirment un développement suivi. Après plusieurs années de mises à jour, c’est surtout cette continuité qui me rassure.&lt;/p&gt;
&lt;h2 id="redis-était-parti-mon-compose-ne-le-savait-pas"&gt;Redis était parti, mon Compose ne le savait pas
&lt;/h2&gt;&lt;p&gt;Authentik a déplacé ses tâches vers PostgreSQL en 2025.8, puis le cache, les sessions Proxy et les WebSockets en 2025.10. Redis pouvait disparaître. Mon ancien Compose continuait pourtant à lancer ce quatrième conteneur, presque inactif mais toujours présent dans les dépendances et les variables d’environnement.&lt;/p&gt;
&lt;p&gt;L’architecture actuelle repose sur trois rôles : PostgreSQL conserve les données, le serveur traite les requêtes et le worker s’occupe des tâches asynchrones. Les &lt;a class="link" href="https://docs.goauthentik.io/releases/2025.10" target="_blank" rel="noopener"
&gt;notes de version 2025.10&lt;/a&gt; préviennent toutefois que PostgreSQL reçoit environ 50 % de connexions supplémentaires. J’ai supprimé une dépendance, pas sa charge de travail.&lt;/p&gt;
&lt;p&gt;Après le ménage, la liste des services est devenue très lisible :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; docker compose -f /opt/authentik/docker-compose.yml config --services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;postgresql
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;server
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;worker
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;J’en ai profité pour fusionner &lt;code&gt;.env&lt;/code&gt; et &lt;code&gt;authentik.env&lt;/code&gt;, retirer les variables Redis, ajouter le montage &lt;code&gt;/data&lt;/code&gt; et porter la mémoire partagée du serveur et du worker à 512 Mio. Avant le déploiement Ansible, j’ai vérifié la sauvegarde Proxmox Backup Server et la lisibilité d’un dump PostgreSQL. Le second passage du playbook n’a produit aucun changement.&lt;/p&gt;
&lt;h2 id="les-logs-avaient-aussi-besoin-dune-limite"&gt;Les logs avaient aussi besoin d’une limite
&lt;/h2&gt;&lt;p&gt;La VM ne dispose que d’un disque de 20 Gio. Avant l’intervention, 13 Gio étaient occupés et le stack produisait environ 19 000 lignes de logs par jour sans aucune rotation.&lt;/p&gt;
&lt;p&gt;J’ai conservé le pilote &lt;code&gt;json-file&lt;/code&gt;. Vector consomme l’API de logs Docker et Wazuh lit les fichiers JSON ; changer de pilote aurait donc cassé silencieusement une partie de l’observabilité. En revanche, chaque conteneur possède maintenant une rotation bornée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;json-file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;20m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Après inventaire des images actives et nettoyage des seules images inutilisées, l’occupation est passée de 13 Gio à 4,6 Gio : environ 8,4 Gio récupérés, sans toucher aux volumes.&lt;/p&gt;
&lt;h2 id="le-vrai-goulot-nétait-pas-docker"&gt;Le vrai goulot n’était pas Docker
&lt;/h2&gt;&lt;p&gt;J’étais venu chercher quelques millisecondes dans le bridge Docker. Il n’en ajoutait que 0,1 à 0,2, tandis que la route publique répondait autour de 152 ms. Passer en mode &lt;code&gt;host&lt;/code&gt; aurait surtout échangé de l’isolation contre un gain invisible.&lt;/p&gt;
&lt;p&gt;La piste utile se trouvait un étage plus bas. La VM tournait sur &lt;code&gt;pve-fuji&lt;/code&gt;, un nœud Intel déjà chargé, avec parfois 5 à 8 % de temps CPU volé. Je l’ai migrée à chaud vers &lt;code&gt;pve-forum&lt;/code&gt;, un nœud AMD plus disponible. La latence a immédiatement chuté… puis la VM a perdu le réseau avant de se figer. À cet instant, mon petit benchmark venait de se transformer en exercice de reprise.&lt;/p&gt;
&lt;p&gt;Après retour sur &lt;code&gt;pve-fuji&lt;/code&gt; et redémarrage forcé, PostgreSQL et les trois conteneurs sont repartis sans perte. La bonne méthode était une migration à froid : arrêt propre par Proxmox HA, déplacement de la VM éteinte, puis redémarrage sur &lt;code&gt;pve-forum&lt;/code&gt;. L’interruption a duré environ 2 min 40.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Étape&lt;/th&gt;
&lt;th style="text-align: right"&gt;Route publique moyenne observée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;état initial sur &lt;code&gt;pve-fuji&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;151,6 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compose modernisé, retour sur &lt;code&gt;pve-fuji&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;105,8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;migration à froid vers &lt;code&gt;pve-forum&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;68,9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Ces mesures appartiennent à mon environnement, pas à un benchmark universel d’Authentik. Elles montrent surtout que le placement de la VM pesait bien plus que le réseau Docker — rien de très surprenant dans mon homelab bricolé de toutes pièces :D&lt;/p&gt;
&lt;h2 id="une-première-porte-ouverte"&gt;Une première porte ouverte
&lt;/h2&gt;&lt;p&gt;Ce billet n’avait pas vocation à devenir un guide d’Authentik. Mon blog vient de démarrer et je n’avais encore jamais présenté le service qui protège pourtant 21 de mes applications. Cette maintenance était simplement la bonne occasion de lui ouvrir la porte.&lt;/p&gt;
&lt;p&gt;Je reviendrai dans un autre article sur mon organisation autour d’Authentik : les flows, les groupes, la double authentification, le raccordement des applications et les cas où j’utilise le proxy plutôt qu’OIDC ou SAML. Pour cette fois, je voulais simplement raconter comment un conteneur Redis devenu inutile m’a donné le prétexte de présenter le gardien de mon homelab.&lt;/p&gt;</description></item></channel></rss>