/images/avatar.png

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.

🌟 Don’t miss

Three articles that capture the spirit of this homelab:

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

🛠️ Tech stack

ToolRole
OpenRestyReverse proxy · nginx + LuaJIT · TLS 1.3
🔒 CrowdSecCommunity IDS/IPS
🧱 CrowdSec AppSecInline WAF · OWASP CRS 4.x
☁️ CloudflareCDN · WAF · DNS · DDoS
🌐 HugoStatic site generator
🤖 MCP Hugo ServerMCP server to drive this site from an AI
📊 BetterStackMonitoring · Alerts · Logs

🐛 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

Reports are publicly credited in the Hall of Fame, or kept anonymous on request.

Any contribution to improving security is welcome.

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.

CrowdSec AppSec Postmortem: Sonarr/Radarr False Positive

What happened
  • Date: May 25, 2026
  • Severity: P3
  • Status: Resolved
  • Impact: Sonarr and Radarr unreachable (403) for ~15-20 minutes — CrowdSec AppSec heuristic false positive, no data loss

In short

On May 25, 2026 at around 10:02 PM (local time), Sonarr and Radarr became completely inaccessible from the home IP (82.XX.XX.XX), returning 403 on every URL including /login. The service was fully operational. Initial suspicion fell on the day’s crowdsec-cf-sync refactor deployment — the real cause was a CrowdSec AppSec heuristic false positive.

CrowdSec AppSec + OpenResty: Modern WAF Without ModSecurity

In short

After years running ModSecurity + OWASP CRS on nginx, I migrated arleo.eu to a more modern stack: CrowdSec AppSec on OpenResty. The result is a tighter inline WAF architecture — better integrated, easier to maintain, and fully coherent with the rest of the security stack.

Why Drop ModSecurity?

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.

Hugo SRI: Automated Hashes and CDN Monitoring

In short

When your site loads resources from a third-party CDN — FontAwesome, Mermaid, Animate.css — you’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.

Subresource Integrity (SRI) solves this cleanly: every <link> or <script> tag carries an integrity="sha256-…" attribute that the browser verifies before executing the resource. If the hash doesn’t match, the browser blocks the load.

Postmortem: TypeIt broken by Mermaid in LoveIt theme

What happened
  • Date: May 14, 2026
  • Severity: P3
  • Status: Resolved
  • Impact: TypeIt animation broken on the home page via a DOM conflict with an orphan Mermaid block in summaries — 16 bilingual posts fixed

In short

The LoveIt theme’s typewriter animation (TypeIt) stopped working on the home after adding Mermaid diagrams to posts. Cause: a #id-1 DOM selector shared between both libraries. When Mermaid finds an orphan block in a home summary, its initialization crashes, and the JS init chain stops before reaching TypeIt. Fix: add `

hugo-mcp Cloudflare plugin: smart cache purge

In short

The Cloudflare plugin in hugo-mcp v2.0 implements 3 cache purge modes (full, partial, smart). The partial mode computes the linked URLs to invalidate (canonical + sitemap + RSS + listing + home) to preserve 95% of the CDN cache on every modification. Concretely: 6 URLs purged instead of wiping everything. This post details the computation, the pitfalls, and why smart became the default.

Hugo