/images/avatar.png

Casser, réparer, apprendre.

Ce site tourne sur un NUC Intel hébergé à la maison, derrière une connexion fibre standard. Il sert avant tout de terrain d’expérimentation pour tester des configurations serveur, des scripts d’automatisation, et des outils de sécurité open source.

Pas un site professionnel — un homelab : on casse des choses, on les répare, on apprend.

Migration en cours
Le site migre progressivement de Grav CMS vers Hugo. Les anciennes URLs sont préservées, mais le rendu visuel évolue. Si vous voyez un bug, signalez-le.

🛠️ Stack technique

OutilRôleLien
🔒 CrowdSecIDS/IPS communautaire collaboratifDashboard
☁️ CloudflareCDN · WAF · DNS · DDoSDashboard
📊 BetterStackMonitoring · Alertes · LogsStatus page
🌐 HugoGénérateur de site statiquegohugo.io
🛡️ ModSecurityWAF local · OWASP CRS 4.xOWASP CRS
nginxReverse proxy · TLS 1.3nginx.org

🌟 À ne pas manquer

Trois articles qui résument l’esprit du homelab :

📚 La documentation complète est dans Documentation et les scripts d’automatisation dans Scripts.

🐛 Vous avez trouvé une faille ?

Si vous découvrez un bug, une mauvaise configuration ou une faille de sécurité sur ce serveur, merci de me le signaler. Ce homelab est public et j’apprends de mes erreurs.

📨 Signalement responsable : www.arleo.eu/security.txt

Toute contribution à l’amélioration de la sécurité est la bienvenue.

SEO Hugo : 404 Googlebot, aliases noindex et normalisation des sitemaps

Contexte

Google Search Console remontait quatre catégories de problèmes sur arleo.eu :

  • 404 Googlebot : /fr/tag/cloudflare, /en/tag/nginx, /fr/tag/javascript… URLs avec préfixe /fr/ ou singulier /tag/ jamais servi par nginx
  • 16 pages “Exclue par la balise noindex” : toutes des pages de redirection générées par aliases: dans le frontmatter Hugo
  • Balise robots : noodp hardcodée dans le thème LoveIt
  • Sitemap FR/EN : 104 vs 105 URLs — un tag doublon FR et deux tags manquants

Acte 1 : aliases Hugo → redirections nginx 301

Pourquoi Hugo génère des pages noindex

Hugo génère les entrées aliases: du frontmatter comme des fichiers HTML statiques :

Hugo : gel des diagrammes Mermaid en SVG statiques dark/light

Problème

Les diagrammes Mermaid sur arleo.eu rendaient côté client via cdn.jsdelivr.net. Trois conséquences concrètes :

  1. CSP contraintescript-src cdn.jsdelivr.net et worker-src cdn.jsdelivr.net obligatoires (Mermaid v11 utilise des Web Workers pour ses parsers).
  2. Flash de rendu — le diagramme apparaît après l’exécution JS, créant un décalage visible.
  3. Thème dark ignoré — Mermaid initialisait le SVG en mode clair même quand le thème du site était dark.

La solution : générer les SVG au build avec mmdc, en dehors de tout contexte navigateur.

CSP A+ sur Hugo + Cloudflare : de hash-based à origin allowlist, monitoring auto et durcissement

Contexte

arleo.eu tourne sur Hugo (VM KVM) → OpenResty (NUC) → Cloudflare (CDN/WAF). Objectif : score A+ sur Mozilla Observatory avec une CSP stricte qui résiste aux injections côté edge.

Le parcours a traversé trois stratégies en quelques semaines — nonces, hashes, puis origin allowlist — avant d’aboutir à une solution stable et automatisée.


Acte 1 : pourquoi hash-based a échoué

L’idée de départ semblait solide : Hugo Pipes externalise tout le JS avec SRI, on liste les hashes dans la CSP, résultat propre. En pratique, deux problèmes ont rendu l’approche impossible.

Postmortem — CrowdSec AppSec : faux positif heuristique sur Sonarr/Radarr

Résumé

Le 25 mai 2026 vers 22h02 (heure locale), Sonarr et Radarr sont devenus totalement inaccessibles depuis l’IP maison (82.XX.XX.XX), retournant 403 sur toutes les URLs y compris /login. Le service était pourtant opérationnel. Le diagnostic initial suspectait les récents déploiements du refactor crowdsec-cf-sync — la cause réelle est un faux positif heuristique CrowdSec AppSec.


Timeline

Heure (locale)Événement
~22h00Cookie de session Sonarr expiré côté navigateur
22h02:31Le navigateur charge la bibliothèque Sonarr → tente de charger 20+ /MediaCover/*.jpg simultanément
22h02:31Sonarr retourne 302 → /login pour chaque image (session invalide)
22h02:34La connexion SignalR WebSocket s’établit (101) via access_token dans l’URL
~22h05CrowdSec AppSec déclenche la règle heuristique http-probing : rafale de requêtes échouées depuis la même IP
22h11:37Toutes les requêtes de 82.XX.XX.XX retournent 403 — cs_reason=heuristic dans les logs nginx
22h13:34Même /login bloqué — l’IP ne peut plus s’authentifier

Cause racine

CrowdSec AppSec maintient un état heuristique en mémoire, distinct des décisions LAPI. Lorsque le navigateur tente de charger simultanément de nombreuses ressources et reçoit des 302/403 de l’application upstream (Sonarr), AppSec interprète cette rafale d’échecs comme du sondage agressif (http-probing) et bloque l’IP source.

CrowdSec AppSec + OpenResty : WAF moderne sans ModSecurity

Après des années avec ModSecurity + OWASP CRS sur nginx, j’ai migré arleo.eu vers une stack plus moderne : CrowdSec AppSec sur OpenResty. Le résultat est une architecture WAF inline mieux intégrée, plus facile à maintenir, et plus cohérente avec le reste de la stack de sécurité.

Pourquoi abandonner ModSecurity ?

ModSecurity v2 est en fin de vie active. Le maintien des règles OWASP CRS sur nginx classique génère de la friction : faux positifs fréquents, logs difficiles à corréler avec CrowdSec, et une configuration dispersée entre plusieurs outils sans vision unifiée.

SRI sur Hugo : hashes automatiques, auto-update et alerting BetterStack

Pourquoi le SRI ?

Quand votre site charge des ressources depuis un CDN tiers — FontAwesome, Mermaid, Animate.css — vous faites confiance à un tiers sur lequel vous n’avez aucun contrôle. Si jsdelivr.net est compromis ou si une version « immuable » est mutée silencieusement, votre site peut devenir vecteur d’attaque.

Le Subresource Integrity (SRI) résout ça simplement : chaque balise <link> ou <script> porte un attribut integrity="sha256-…" que le navigateur vérifie avant d’exécuter la ressource. Si le hash ne correspond pas, le navigateur bloque le chargement.

Hugo