Break things. Fix them. Learn.

This site runs on an Intel NUC hosted at home, behind a standard fiber connection. Its main purpose is to serve as an experimentation ground for testing server configurations, automation scripts, and open source security tools.

Not a professional website — a homelab: we break things, fix them, and learn.

Migration in progress
The site is gradually migrating from Grav CMS to Hugo. Old URLs are preserved, but the visual rendering is evolving. If you spot a bug, report it.

🛠️ Tech stack

Tool Role Link
🔒 CrowdSec Community IDS/IPS Dashboard
☁️ Cloudflare CDN · WAF · DNS · DDoS Dashboard
📊 BetterStack Monitoring · Alerts · Logs Status page
🌐 Hugo Static site generator gohugo.io
🛡️ ModSecurity Local WAF · OWASP CRS 4.x OWASP CRS
nginx Reverse proxy · TLS 1.3 nginx.org

🌟 Don’t miss

Three articles that capture the spirit of this homelab:

📚 Full documentation is in Documentation and automation scripts in Scripts.

🐛 Found a vulnerability?

If you discover a bug, misconfiguration, or security vulnerability on this server, please report it. This homelab is public and I learn from my mistakes.

📨 Responsible disclosure: www.arleo.eu/security.txt

Any contribution to improving security is welcome.

MCP Hugo Server Is Now Public: npm and Claude Desktop

This blog has been run for months by mcp-hugo-server-go, a Go MCP server.

It gives Claude direct, secure access to arleo.eu’s Hugo content: creating, editing, publishing, taxonomy management, images, and more.

It’s the successor to the 6-tool FastAPI/Python server documented here back in May.

This post explains why a project originally built for strictly personal use is now something anyone running a Hugo site can install.

Why this isn’t just “a script that happens to work”

Most content-management MCP tools I’ve come across handle the happy path and stop there.

Hugo SEO: noindex on taxonomies (Bing thin-content fix)

Context

Bing Webmaster Tools was raising a “There are too many pages with insufficient content” recommendation (severity: moderate) — 15 pages flagged, all of the same type:

  • https://www.arleo.eu/en/tags/svg/
  • https://www.arleo.eu/en/tags/sonarr/
  • https://www.arleo.eu/en/categories/incidents/
  • etc.

These are Hugo taxonomy pages — tag and category listing pages. They contain no article content of their own, just a list of links. From Bing’s perspective, that’s thin content.

This follows the same investigation habit as an earlier Googlebot 404s and sitemap normalization fix on this site: check the search console first, understand why Hugo generated the offending pages, then fix at the template level instead of patching each URL by hand.

Hugo SEO: Googlebot 404s, noindex aliases and sitemap normalization

Context

Google Search Console was reporting four categories of issues on arleo.eu:

  • Googlebot 404s: /fr/tag/cloudflare, /en/tag/nginx, /fr/tag/javascript… URLs with /fr/ prefix or singular /tag/ never served by nginx
  • 16 “Excluded by noindex tag” pages: all redirect pages generated by aliases: in Hugo frontmatter
  • Robots tag: noodp hardcoded in the LoveIt theme
  • FR/EN sitemap: 104 vs 105 URLs — a duplicate FR tag and two missing tags

Act 1: Hugo aliases → nginx 301 redirects

Why Hugo generates noindex pages

Hugo generates aliases: frontmatter entries as static HTML files:

Hugo: freezing Mermaid diagrams to static dark/light SVGs

Problem

Mermaid diagrams on arleo.eu were rendering client-side via cdn.jsdelivr.net. Three concrete consequences:

  1. CSP constraintscript-src cdn.jsdelivr.net and worker-src cdn.jsdelivr.net become mandatory (Mermaid v11 uses Web Workers for its parsers).
  2. Render flash — the diagram appears after JS execution, creating a visible delay.
  3. Dark theme ignored — Mermaid initialized the SVG in light mode even when the site theme was dark.

The solution: generate SVGs at build time with mmdc, outside any browser context.

CSP A+ on Hugo + Cloudflare: from hash-based to origin allowlist, auto-monitoring and hardening

Context

arleo.eu runs on Hugo (KVM VM) → OpenResty (NUC) → Cloudflare (CDN/WAF). Goal: A+ score on Mozilla Observatory with a strict CSP that resists edge-side injections.

The journey went through three strategies over a few weeks — nonces, hashes, then origin allowlist — before landing on a stable, automated solution.


Act 1: why hash-based failed

The initial idea seemed solid: Hugo Pipes externalizes all JS with SRI, we list the hashes in the CSP, clean result. In practice, two problems made the approach impossible.