<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Infrastructure - Balise - arleo.eu</title>
        <link>https://www.arleo.eu/tags/infrastructure/</link>
        <description>Infrastructure - Balise - arleo.eu</description>
        <generator>Hugo -- gohugo.io</generator><language>fr</language><lastBuildDate>Mon, 29 Jun 2026 07:00:00 &#43;0200</lastBuildDate><atom:link href="https://www.arleo.eu/tags/infrastructure/" rel="self" type="application/rss+xml" /><item>
    <title>Hugo SEO : noindex sur les taxonomies pour corriger l&#39;alerte Bing &#34;too many thin pages&#34;</title>
    <link>https://www.arleo.eu/posts/noindex-taxonomies-hugo-bing-seo/</link>
    <pubDate>Mon, 29 Jun 2026 07:00:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/noindex-taxonomies-hugo-bing-seo/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/noindex-taxonomies-hugo-bing-seo-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="contexte">Contexte</h2>
<p>Bing Webmaster Tools remontait une recommandation <strong>&ldquo;There are too many pages with insufficient content&rdquo;</strong> (sévérité : modérée) — 15 pages en erreur, toutes du même type :</p>
<ul>
<li><code>https://www.arleo.eu/en/tags/svg/</code></li>
<li><code>https://www.arleo.eu/en/tags/sonarr/</code></li>
<li><code>https://www.arleo.eu/en/categories/incidents/</code></li>
<li>etc.</li>
</ul>
<p>Ces pages sont les <strong>taxonomies Hugo</strong> — les listes par tag et par catégorie. Elles ne contiennent pas d&rsquo;article en elles-mêmes, juste une liste de liens. Pour Bing, c&rsquo;est du <em>thin content</em>.</p>
<hr>
<h2 id="stratégie-choisie">Stratégie choisie</h2>
<p>Trois options s&rsquo;offraient :</p>
<ol>
<li><strong>Bloquer via <code>robots.txt</code></strong> → déconseillé : empêche le crawl, masque les liens internes</li>
<li><strong>Enrichir le contenu des pages de taxonomie</strong> → trop coûteux pour un blog technique</li>
<li><strong><code>noindex,follow</code></strong> → la bonne réponse : on dit aux robots de ne pas indexer la page, mais de suivre les liens vers les articles</li>
</ol>
<p>L&rsquo;option 3 est retenue. Le <code>follow</code> préserve le maillage interne — les robots continuent de découvrir les articles via ces pages.</p>]]></description>
</item>
<item>
    <title>SEO Hugo : 404 Googlebot, aliases noindex et normalisation des sitemaps</title>
    <link>https://www.arleo.eu/posts/debug-seo-404-broken-links/</link>
    <pubDate>Fri, 29 May 2026 20:30:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/debug-seo-404-broken-links/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/debug-seo-404-broken-links-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="contexte">Contexte</h2>
<p>Google Search Console remontait quatre catégories de problèmes sur arleo.eu :</p>
<ul>
<li><strong>404 Googlebot</strong> : <code>/fr/tag/cloudflare</code>, <code>/en/tag/nginx</code>, <code>/fr/tag/javascript</code>… URLs avec préfixe <code>/fr/</code> ou singulier <code>/tag/</code> jamais servi par nginx</li>
<li><strong>16 pages &ldquo;Exclue par la balise noindex&rdquo;</strong> : toutes des pages de redirection générées par <code>aliases:</code> dans le frontmatter Hugo</li>
<li><strong>Balise robots</strong> : <code>noodp</code> hardcodée dans le thème LoveIt</li>
<li><strong>Sitemap FR/EN</strong> : 104 vs 105 URLs — un tag doublon FR et deux tags manquants</li>
</ul>
<hr>
<h2 id="acte-1--aliases-hugo--redirections-nginx-301">Acte 1 : aliases Hugo → redirections nginx 301</h2>
<h3 id="pourquoi-hugo-génère-des-pages-noindex">Pourquoi Hugo génère des pages noindex</h3>
<p>Hugo génère les entrées <code>aliases:</code> du frontmatter comme des fichiers HTML statiques :</p>]]></description>
</item>
<item>
    <title>Hugo : gel des diagrammes Mermaid en SVG statiques dark/light</title>
    <link>https://www.arleo.eu/posts/debug-mermaid-svg-freeze/</link>
    <pubDate>Fri, 29 May 2026 20:00:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/debug-mermaid-svg-freeze/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/debug-mermaid-svg-freeze-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="problème">Problème</h2>
<p>Les diagrammes Mermaid sur arleo.eu rendaient côté client via <code>cdn.jsdelivr.net</code>. Trois conséquences concrètes :</p>
<ol>
<li><strong>CSP contrainte</strong> — <code>script-src cdn.jsdelivr.net</code> et <code>worker-src cdn.jsdelivr.net</code> obligatoires (Mermaid v11 utilise des Web Workers pour ses parsers).</li>
<li><strong>Flash de rendu</strong> — le diagramme apparaît après l&rsquo;exécution JS, créant un décalage visible.</li>
<li><strong>Thème dark ignoré</strong> — Mermaid initialisait le SVG en mode clair même quand le thème du site était dark.</li>
</ol>
<p>La solution : générer les SVG <strong>au build</strong> avec <code>mmdc</code>, en dehors de tout contexte navigateur.</p>]]></description>
</item>
<item>
    <title>CrowdSec AppSec &#43; OpenResty : WAF moderne sans ModSecurity</title>
    <link>https://www.arleo.eu/posts/crowdsec-appsec-openresty/</link>
    <pubDate>Mon, 18 May 2026 00:07:11 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/crowdsec-appsec-openresty/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/crowdsec-appsec-openresty-featured.jpg" referrerpolicy="no-referrer">
            </div><p>Après des années avec ModSecurity + OWASP CRS sur nginx, j&rsquo;ai migré arleo.eu vers une stack plus moderne : <strong>CrowdSec AppSec sur OpenResty</strong>. 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é.</p>
<h2 id="pourquoi-abandonner-modsecurity-">Pourquoi abandonner ModSecurity ?</h2>
<p>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.</p>]]></description>
</item>
<item>
    <title>SRI sur Hugo : hashes automatiques, auto-update et alerting BetterStack</title>
    <link>https://www.arleo.eu/posts/sri-cdn-hugo-automate/</link>
    <pubDate>Sun, 17 May 2026 00:00:00 &#43;0000</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/sri-cdn-hugo-automate/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/sri-cdn-hugo-automate-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="pourquoi-le-sri-">Pourquoi le SRI ?</h2>
<p>Quand votre site charge des ressources depuis un CDN tiers — FontAwesome, Mermaid, Animate.css — vous faites confiance à un tiers sur lequel vous n&rsquo;avez aucun contrôle. Si jsdelivr.net est compromis ou si une version « immuable » est mutée silencieusement, votre site peut devenir vecteur d&rsquo;attaque.</p>
<p>Le <strong>Subresource Integrity</strong> (SRI) résout ça simplement : chaque balise <code>&lt;link&gt;</code> ou <code>&lt;script&gt;</code> porte un attribut <code>integrity=&quot;sha256-…&quot;</code> que le navigateur vérifie avant d&rsquo;exécuter la ressource. Si le hash ne correspond pas, le navigateur bloque le chargement.</p>]]></description>
</item>
<item>
    <title>CSP Hash sur Hugo : migrer du nonce vers le hash pour préserver le cache CDN</title>
    <link>https://www.arleo.eu/posts/csp-hash-hugo/</link>
    <pubDate>Sat, 16 May 2026 00:00:00 &#43;0000</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/csp-hash-hugo/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/csp-hash-hugo-featured.png" referrerpolicy="no-referrer">
            </div>Le nonce CSP et le cache CDN sont incompatibles par design. Sur un site Hugo statique, le hash SHA-256 est l&rsquo;approche native : il est calculé au build, reste stable entre les requêtes, et laisse Cloudflare cacher le HTML.]]></description>
</item>
<item>
    <title>Hardening systemd : passer un service Python de 9.6 à 1.7</title>
    <link>https://www.arleo.eu/posts/hardening-systemd-mcp/</link>
    <pubDate>Sat, 09 May 2026 12:40:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/hardening-systemd-mcp/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/hardening-systemd-mcp-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="tldr">TL;DR</h2>
<p><code>systemd-analyze security</code> est un outil sous-utilisé. Il scanne tes unit files et calcule un score d&rsquo;exposition de <strong>0.0 (UNSAFE)</strong> à <strong>10.0 (PERFECT)</strong>. Les services Python custom sortent souvent autour de <strong>9.6</strong> par défaut — c&rsquo;est mauvais.</p>
<p>J&rsquo;ai fait passer mon service <code>hugo-mcp</code> (FastAPI exposant 7 tools MCP) de <strong>9.6 → 1.7</strong> sans casser la moindre fonctionnalité. Voici les directives qui comptent vraiment, et celles qui sont des pièges.</p>
<h2 id="le-score-initial">Le score initial</h2>
<div class="code-block code-line-numbers open" data-start="0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="Copier dans le presse-papiers"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo systemd-analyze security hugo-mcp
</span></span><span class="line"><span class="cl">→ Overall exposure level <span class="k">for</span> hugo-mcp.service: 9.6 UNSAFE 😨</span></span></code></pre></div></div>
<p>9.6 sur 10. Le service tourne en root équivalent, peut faire <code>setuid()</code>, peut allouer de la mémoire <code>RWX</code>, voit tous les processus du système, peut écrire partout, peut faire des syscalls arbitraires.</p>
<p>Pour un MCP qui édite du contenu Markdown et déclenche un build Hugo, c&rsquo;est démesuré.</p>]]></description>
</item>
<item>
    <title>Migration Grav → Hugo : 32 fichiers, 0 régression</title>
    <link>https://www.arleo.eu/posts/migration-grav-vers-hugo/</link>
    <pubDate>Sat, 09 May 2026 12:38:56 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/migration-grav-vers-hugo/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/migration-grav-vers-hugo-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="tldr">TL;DR</h2>
<p>arleo.eu tournait sur <strong>Grav CMS</strong> depuis ~3 ans : flat-file, PHP-FPM, ModSecurity, Cloudflare. Tout marchait. Mais la dette opérationnelle s&rsquo;accumulait : MAJ PHP, plugins Grav à patcher, TTFB qui grimpait à &gt;800ms sur certaines pages.</p>
<p>J&rsquo;ai migré vers <strong>Hugo</strong> (générateur de site statique en Go) en deux semaines, en gardant les mêmes URLs, le même contenu, et les deux langues FR/EN. <strong>Zéro régression</strong> côté SEO, indexation Cloudflare, ou liens internes. Voici comment.</p>
<h2 id="pourquoi-hugo">Pourquoi Hugo</h2>
<p>J&rsquo;avais 3 critères :</p>
<ol>
<li><strong>Performance</strong> — Statique pur. Pas de PHP, pas de DB. nginx sert directement les <code>.html</code> pré-générés.</li>
<li><strong>Sécurité</strong> — Surface d&rsquo;attaque divisée par 10. Plus de PHP-FPM, plus d&rsquo;exécution serveur sur les pages publiques.</li>
<li><strong>Multilingue propre</strong> — Hugo supporte nativement i18n via la convention <code>index.{lang}.md</code> (page bundles).</li>
</ol>
<p>Hugo coche tout. Les alternatives évaluées : <strong>Eleventy</strong> (JS, mais moins mature niveau i18n), <strong>Zola</strong> (Rust, super, mais écosystème thèmes plus restreint), <strong>Gatsby</strong> (trop lourd pour un homelab).</p>]]></description>
</item>
<item>
    <title>Hugo MCP Server : connecter Claude.ai à un site Hugo statique</title>
    <link>https://www.arleo.eu/posts/hugo-mcp-server/</link>
    <pubDate>Sun, 03 May 2026 19:00:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/hugo-mcp-server/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/hugo-mcp-server-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Connecter Claude.ai à un site <strong>Hugo</strong> hébergé dans une VM KVM en 30 minutes : un serveur FastAPI expose 6 outils MCP (lire, créer, modifier, supprimer des pages, rebuilder le site) via JSON-RPC 2.0, un proxy OAuth réutilise l&rsquo;infrastructure existante, et chaque modification déclenche automatiquement un rebuild Hugo + une purge du cache Cloudflare.</p>
<p>Le code est disponible sur GitHub :</p>
<ul>
<li>🔌 Serveur MCP Hugo : <a href="https://github.com/jmrGrav/hugo-mcp" target="_blank" rel="noopener noreffer ">jmrGrav/hugo-mcp</a></li>
<li>🔐 Proxy OAuth : <a href="https://github.com/jmrGrav/mcp-oauth-proxy" target="_blank" rel="noopener noreffer ">jmrGrav/mcp-oauth-proxy</a></li>
</ul>
<h2 id="-pourquoi">🧠 Pourquoi</h2>
<p>Le protocole <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreffer ">MCP (Model Context Protocol)</a> d&rsquo;Anthropic permet à Claude.ai de se connecter à des sources de données externes via des outils standardisés. Contrairement à Grav CMS qui est dynamique (PHP), Hugo génère du HTML statique — ce qui rend la gestion de contenu via MCP encore plus puissante : chaque modification est compilée et déployée instantanément.</p>]]></description>
</item>
<item>
    <title>VM Media sur KVM : migrer Sonarr, Radarr et SABnzbd dans une VM isolée</title>
    <link>https://www.arleo.eu/posts/media-vm-migration/</link>
    <pubDate>Sun, 03 May 2026 18:00:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/media-vm-migration/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/media-vm-migration-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Migrer son media stack (Sonarr, Radarr, SABnzbd) dans une VM KVM dédiée sur Ubuntu 24.04 : isolation sécurité, snapshots facilités, NFS QNAP monté dans la VM, reverse proxy nginx sur l&rsquo;hôte. La migration conserve intégralement les bases de données SQLite et la configuration existante.</p>
<p><strong>Stack cible :</strong></p>
<ul>
<li>🖥️ <strong>Hôte</strong> : NUC8i3BEH, Ubuntu Server, nginx reverse proxy, Plex (transcodage GPU)</li>
<li>📦 <strong>VM media-vm</strong> : Ubuntu 24.04, 2 vCPU, 8 Go RAM, 120 Go (X5 NVMe), NFS QNAP</li>
<li>🎬 <strong>Services migrés</strong> : Sonarr (port 8989), Radarr (port 7878), SABnzbd (port 6789)</li>
</ul>
<h2 id="-pourquoi-isoler-le-media-stack-dans-une-vm">🧠 Pourquoi isoler le media stack dans une VM</h2>
<p>Sonarr, Radarr et SABnzbd présentent une surface d&rsquo;attaque non négligeable : accès réseau vers des indexeurs externes, exécution de scripts post-download, accès au système de fichiers de la bibliothèque. Les confiner dans une VM apporte :</p>]]></description>
</item>
</channel>
</rss>
