<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Infrastructure - Tag - arleo.eu</title><link>https://www.arleo.eu/en/tags/infrastructure/</link><description>Infrastructure - Tag - arleo.eu</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 29 May 2026 20:30:00 +0200</lastBuildDate><atom:link href="https://www.arleo.eu/en/tags/infrastructure/" rel="self" type="application/rss+xml"/><item><title>Hugo SEO: Googlebot 404s, noindex aliases and sitemap normalization</title><link>https://www.arleo.eu/en/posts/debug-seo-404-broken-links/</link><pubDate>Fri, 29 May 2026 20:30:00 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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="context">Context</h2>
<p>Google Search Console was reporting four categories of issues on arleo.eu:</p>
<ul>
<li><strong>Googlebot 404s</strong>: <code>/fr/tag/cloudflare</code>, <code>/en/tag/nginx</code>, <code>/fr/tag/javascript</code>… URLs with <code>/fr/</code> prefix or singular <code>/tag/</code> never served by nginx</li>
<li><strong>16 &ldquo;Excluded by noindex tag&rdquo; pages</strong>: all redirect pages generated by <code>aliases:</code> in Hugo frontmatter</li>
<li><strong>Robots tag</strong>: <code>noodp</code> hardcoded in the LoveIt theme</li>
<li><strong>FR/EN sitemap</strong>: 104 vs 105 URLs — a duplicate FR tag and two missing tags</li>
</ul>
<hr>
<h2 id="act-1-hugo-aliases--nginx-301-redirects">Act 1: Hugo aliases → nginx 301 redirects</h2>
<h3 id="why-hugo-generates-noindex-pages">Why Hugo generates noindex pages</h3>
<p>Hugo generates <code>aliases:</code> frontmatter entries as static HTML files:</p>]]></description></item><item><title>Hugo: freezing Mermaid diagrams to static dark/light SVGs</title><link>https://www.arleo.eu/en/posts/debug-mermaid-svg-freeze/</link><pubDate>Fri, 29 May 2026 20:00:00 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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="problem">Problem</h2>
<p>Mermaid diagrams on arleo.eu were rendering client-side via <code>cdn.jsdelivr.net</code>. Three concrete consequences:</p>
<ol>
<li><strong>CSP constraint</strong> — <code>script-src cdn.jsdelivr.net</code> and <code>worker-src cdn.jsdelivr.net</code> become mandatory (Mermaid v11 uses Web Workers for its parsers).</li>
<li><strong>Render flash</strong> — the diagram appears after JS execution, creating a visible delay.</li>
<li><strong>Dark theme ignored</strong> — Mermaid initialized the SVG in light mode even when the site theme was dark.</li>
</ol>
<p>The solution: generate SVGs <strong>at build time</strong> with <code>mmdc</code>, outside any browser context.</p>]]></description></item><item><title>CrowdSec AppSec + OpenResty: Modern WAF Without ModSecurity</title><link>https://www.arleo.eu/en/posts/crowdsec-appsec-openresty/</link><pubDate>Mon, 18 May 2026 00:07:55 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/posts/crowdsec-appsec-openresty/</guid><description><![CDATA[<div class="featured-image">
                <img src="/images/crowdsec-appsec-openresty-featured.jpg" referrerpolicy="no-referrer">
            </div><p>After years running ModSecurity + OWASP CRS on nginx, I migrated arleo.eu to a more modern stack: <strong>CrowdSec AppSec on OpenResty</strong>. The result is a tighter inline WAF architecture — better integrated, easier to maintain, and fully coherent with the rest of the security stack.</p>
<h2 id="why-drop-modsecurity">Why Drop ModSecurity?</h2>
<p>ModSecurity v2 is in maintenance mode. Managing OWASP CRS rules on classic nginx generates friction: frequent false positives, logs that are hard to correlate with CrowdSec, and a configuration spread across multiple tools with no unified view.</p>]]></description></item><item><title>SRI on Hugo: automated hashes, auto-update and BetterStack alerting</title><link>https://www.arleo.eu/en/posts/sri-cdn-hugo-automate/</link><pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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="why-sri">Why SRI?</h2>
<p>When your site loads resources from a third-party CDN — FontAwesome, Mermaid, Animate.css — you&rsquo;re trusting an external party you have no control over. If jsdelivr.net gets compromised, or if a supposedly immutable version is silently mutated, your site can become an attack vector.</p>
<p><strong>Subresource Integrity</strong> (SRI) solves this cleanly: every <code>&lt;link&gt;</code> or <code>&lt;script&gt;</code> tag carries an <code>integrity=&quot;sha256-…&quot;</code> attribute that the browser verifies before executing the resource. If the hash doesn&rsquo;t match, the browser blocks the load.</p>]]></description></item><item><title>CSP Hash on Hugo: migrating from nonce to hash to preserve CDN cache</title><link>https://www.arleo.eu/en/posts/csp-hash-hugo/</link><pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/posts/csp-hash-hugo/</guid><description>&lt;div class="featured-image">
                &lt;img src="/images/csp-hash-hugo-featured.png" referrerpolicy="no-referrer">
            &lt;/div>CSP nonces and CDN caching are incompatible by design. On a Hugo static site, SHA-256 hashes are the native approach: computed at build time, stable across requests, and fully compatible with Cloudflare caching.</description></item><item><title>systemd hardening: taking a Python service from 9.6 to 1.7</title><link>https://www.arleo.eu/en/posts/hardening-systemd-mcp/</link><pubDate>Sat, 09 May 2026 13:02:29 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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> is an underused tool. It scans your unit files and computes an exposure score from <strong>0.0 (UNSAFE)</strong> to <strong>10.0 (PERFECT)</strong>. Custom Python services often score around <strong>9.6</strong> by default — that&rsquo;s bad.</p>
<p>I took my <code>hugo-mcp</code> service (FastAPI exposing 7 MCP tools) from <strong>9.6 → 1.7</strong> without breaking a single feature. Here are the directives that actually matter, and the ones that are traps.</p>
<h2 id="initial-score">Initial score</h2>]]></description></item><item><title>Migrating Grav → Hugo: 32 files, 0 regression</title><link>https://www.arleo.eu/en/posts/migration-grav-vers-hugo/</link><pubDate>Sat, 09 May 2026 13:01:28 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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 had been running on <strong>Grav CMS</strong> for ~3 years: flat-file, PHP-FPM, ModSecurity, Cloudflare. Everything worked. But operational debt was piling up: PHP upgrades, Grav plugins to patch, TTFB creeping past 800ms on some pages.</p>
<p>I migrated to <strong>Hugo</strong> (Go-based static site generator) in two weeks, keeping the same URLs, the same content, and both languages FR/EN. <strong>Zero regression</strong> on SEO, Cloudflare indexing, or internal links. Here&rsquo;s how.</p>
<h2 id="why-hugo">Why Hugo</h2>
<p>I had 3 criteria:</p>
<ol>
<li><strong>Performance</strong> — Pure static. No PHP, no DB. nginx serves pre-generated <code>.html</code> directly.</li>
<li><strong>Security</strong> — Attack surface divided by 10. No more PHP-FPM, no server-side execution on public pages.</li>
<li><strong>Clean multilingual</strong> — Hugo natively supports i18n via the <code>index.{lang}.md</code> convention (page bundles).</li>
</ol>
<p>Hugo checks all the boxes. Alternatives evaluated: <strong>Eleventy</strong> (JS, but less mature i18n), <strong>Zola</strong> (Rust, awesome, but fewer themes), <strong>Gatsby</strong> (too heavy for a homelab).</p>]]></description></item><item><title>Hugo MCP Server: Connecting Claude.ai to a Static Hugo Site</title><link>https://www.arleo.eu/en/posts/hugo-mcp-server/</link><pubDate>Sun, 03 May 2026 19:00:00 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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="-in-short">⚡ In short</h2>
<p>Connect Claude.ai to a <strong>Hugo</strong> site hosted in a KVM VM in 30 minutes: a FastAPI server exposes 6 MCP tools (read, create, modify, delete pages, rebuild the site) via JSON-RPC 2.0, an OAuth proxy reuses existing infrastructure, and every modification automatically triggers a Hugo rebuild + Cloudflare cache purge.</p>
<p>The code is available on GitHub:</p>
<ul>
<li>🔌 Hugo MCP Server: <a href="https://github.com/jmrGrav/hugo-mcp" target="_blank" rel="noopener noreffer ">jmrGrav/hugo-mcp</a></li>
<li>🔐 OAuth Proxy: <a href="https://github.com/jmrGrav/mcp-oauth-proxy" target="_blank" rel="noopener noreffer ">jmrGrav/mcp-oauth-proxy</a></li>
</ul>
<h2 id="-why">🧠 Why</h2>
<p>Anthropic&rsquo;s <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreffer ">MCP (Model Context Protocol)</a> allows Claude.ai to connect to external data sources via standardized tools. Unlike Grav CMS which is dynamic (PHP), Hugo generates pure static HTML — making content management via MCP even more powerful: every modification is compiled and deployed instantly.</p>]]></description></item><item><title>KVM Media VM: migrating Sonarr, Radarr and SABnzbd into an isolated VM</title><link>https://www.arleo.eu/en/posts/media-vm-migration/</link><pubDate>Sun, 03 May 2026 18:00:00 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/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="-tldr">⚡ TL;DR</h2>
<p>Migrating the media stack (Sonarr, Radarr, SABnzbd) into a dedicated KVM VM running Ubuntu 24.04: security isolation, easy snapshots, QNAP NFS mounted inside the VM, nginx reverse proxy on the host. The migration fully preserves SQLite databases and existing configuration.</p>
<p><strong>Target stack:</strong></p>
<ul>
<li>🖥️ <strong>Host</strong>: NUC8i3BEH, Ubuntu Server, nginx reverse proxy, Plex (GPU transcoding)</li>
<li>📦 <strong>VM media-vm</strong>: Ubuntu 24.04, 2 vCPU, 8 GB RAM, 120 GB (X5 NVMe), QNAP NFS</li>
<li>🎬 <strong>Migrated services</strong>: Sonarr (port 8989), Radarr (port 7878), SABnzbd (port 6789)</li>
</ul>
<h2 id="-why-isolate-the-media-stack-in-a-vm">🧠 Why isolate the media stack in a VM</h2>
<p>Sonarr, Radarr and SABnzbd present a significant attack surface: network calls to external indexers, post-download script execution, filesystem access to the media library. Confining them in a VM provides:</p>]]></description></item><item><title>Hugo on KVM: Installing an Ubuntu VM for a Static Site</title><link>https://www.arleo.eu/en/posts/hugo-vm-installation/</link><pubDate>Sun, 03 May 2026 09:00:00 +0200</pubDate><author>Jmr</author><guid>https://www.arleo.eu/en/posts/hugo-vm-installation/</guid><description><![CDATA[<div class="featured-image">
                <img src="/images/hugo-vm-installation-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-in-short">⚡ In short</h2>
<p>Progressive migration from <strong>Grav CMS</strong> to <strong>Hugo</strong> — a static site generator. The goal is to isolate Hugo in a dedicated KVM VM on the NUC8i3BEH, with nginx on the host as a reverse proxy. The generated static site is served by nginx inside the VM — no PHP, no database, no application attack surface.</p>
<ul>
<li>🖥️ <strong>Host</strong>: NUC8i3BEH Ubuntu 24.04 — nginx proxy + KVM</li>
<li>🗄️ <strong>VM disk</strong>: Samsung X5 external NVMe (exFAT → ext4 loop image)</li>
<li>🌐 <strong>Access</strong>: <a href="https://hugo-test.arleo.eu" target="_blank" rel="noopener noreffer ">hugo-test.arleo.eu</a></li>
<li>🎨 <strong>Theme</strong>: <a href="https://github.com/dillonzq/LoveIt" target="_blank" rel="noopener noreffer ">LoveIt</a></li>
</ul>
<h2 id="-why">🧠 Why</h2>
<p>Grav CMS is excellent but relies on PHP — a non-negligible attack surface. Hugo generates pure static HTML: no PHP, no database, no application vulnerability. Performance is also radically better — HTML is served directly by nginx without dynamic processing.</p>]]></description></item></channel></rss>