↓ Skip to main content

Why Modern Security left WordPress: rebuilding the blog with Hugo and Blowfish

Modern Security logo with the text WordPress to Hugo, rebuilt with Blowfish on Cloudflare Workers
Table of Contents

Introduction

If you’re reading this, you’re looking at a completely new Modern Security. Same articles, same URLs, same Microsoft security focus. But under the hood almost nothing is left of the old site.

For years this blog ran on WordPress. It worked, but every month I spent more time maintaining the platform than writing about Microsoft security. Plugin updates, a security plugin to protect the other plugins, a cache plugin to make it fast again, a cookie plugin to explain all the other plugins. At some point I asked myself the question I ask customers all the time: why is the attack surface this big for what it actually needs to do?

So I rebuilt it. Modern Security is now a static site built with Hugo and the Blowfish theme, hosted on Cloudflare Workers. In this post I explain why I made the move, how I migrated every article without breaking a single link, what I built on top of Blowfish, and what changed for you as a reader.

Why leave WordPress?

WordPress isn’t bad. It runs a huge part of the internet for good reasons. But for a blog like this one, the trade-offs had tipped the wrong way.

Over time the old site needed a long list of plugins: Rank Math Pro for SEO, Wordfence for security, LiteSpeed Cache for performance, Complianz for cookie consent, Google Tag Manager, reCAPTCHA for the contact form, and a newsletter plugin. Each of them is code that runs on every request, needs updates, and can have its own vulnerabilities.

For a security blog that felt wrong for three reasons:

  • Attack surface: A login page, a database, PHP and a stack of plugins, all reachable from the internet, to serve articles that change a few times a month.
  • Maintenance: Updates were never “just” updates. Something always needed checking afterwards.
  • Privacy: The cookie policy listed cookies from WordPress, Wordfence, LiteSpeed, Google, Facebook, Twitter and LinkedIn. That’s a lot of third parties for reading an article about Defender XDR.

A static site removes most of that by design. There is no database to inject into, no login page to brute-force and no plugins to patch. The server only hands out files.

The new stack

PartOld siteNew site
PlatformWordPress with PHP and a databaseHugo static site generator
ThemeWordPress theme plus page builder blocksBlowfish, with my own layouts on top
HostingWeb hosting with a LiteSpeed serverCloudflare Workers (static assets)
SEORank Math ProBuilt into the templates (titles, descriptions, structured data, sitemap)
SecurityWordfenceNo login, no database, nothing to log in to
Contact formWordPress form with reCAPTCHAA small Cloudflare Worker with Cloudflare Turnstile
Cookie consentComplianz pluginA small self-hosted consent banner
WritingWordPress editorMarkdown files in Git

Hugo turns Markdown files into plain HTML pages in seconds. Blowfish gives a modern, fast theme with dark mode, search and an accessibility panel. Cloudflare Workers builds the site from GitHub on every change and serves it from Cloudflare’s network. Pages are plain files; code only runs for the contact form.

One rule I set myself from day one: never edit the Blowfish theme files. Blowfish is a Git submodule, pinned to a fixed version, and everything that makes the site look like Modern Security lives in my own layouts and styles. Where I had to replace a Blowfish template, it’s documented, so I know exactly what to check when Blowfish releases a new version.

Migrating every article without breaking a link

The scariest part of any migration is SEO. Years of articles are indexed by Google, linked from LinkedIn posts and bookmarked by readers. If URLs change, all of that turns into 404 errors overnight.

So the migration started with an audit, not with a design. I exported everything from the WordPress REST API: posts, pages, categories, media, and the SEO data Rank Math generated for every page. Then a Python converter turned each WordPress article into a Hugo page bundle: one folder per article with the Markdown text and its images next to it.

A few things the converter had to get right:

  1. Identical URLs: Every article, category and page keeps exactly the same address as on WordPress. One article even had a non-breaking hyphen (U+2011) in its URL, which Hugo silently strips. That one now has its URL set explicitly.
  2. Identical SEO: Titles, meta descriptions and robots settings are copied exactly as Rank Math had them. A comparison script checks the old and new page headers side by side.
  3. Tables: Many of my articles are full of tables with KQL queries and settings. The converter checked all 133 tables against the original. That’s how I found that a WordPress math plugin had quietly eaten the $ signs in a PowerShell command at some point.
  4. Images: Every screenshot is converted to WebP, and Hugo now creates several sizes of each image, so a phone downloads a small version and a 4K screen a sharp one.
  5. KQL highlighting: Hugo’s code highlighter doesn’t know KQL, so the site highlights KQL itself while building. No JavaScript needed in your browser.

The old cookie policy pages for different countries will point to one cookie policy, and the remaining old WordPress addresses get permanent redirects. Google sees the same pages, with the same titles, at the same addresses.

Building the frontend

Blowfish is a great starting point, but I wanted the site to stay recognisably Modern Security: the black top bar, the big logo, black section headings and the photo tiles on the homepage. So most of what you see is built on top of the theme:

  • Homepage: a mosaic of featured articles, the Security, Identity and Compliance tiles, and every other article with pagination.
  • Articles: a table of contents at the top, a featured posts and categories sidebar, a reading progress bar and code blocks with a copy button.
  • Topic pages: a photo banner, an introduction per topic, related topics and the articles in that topic.
  • Dark mode and accessibility: a dark-mode switch and Blowfish’s accessibility panel for text size, link underlines and a distraction-free reading mode.
  • Sharing without trackers: share buttons for LinkedIn, X, Bluesky and email are plain links. Nothing from those networks loads until you click.
  • Mobile: every page type was checked at phone size, so nothing scrolls sideways and every button is big enough to tap.

Privacy and security by design

This is the part I’m most happy with, because it’s where the old site felt most uncomfortable.

Nothing tracks you before you choose: The site uses Google Analytics and Microsoft Clarity to see which articles are read, but only after you allow it in the cookie banner. Before that choice, no Google or Microsoft script is loaded at all. Rejecting is exactly as easy as accepting, and advertising features are switched off in both tools. You can change your mind at any time via the Cookie settings button on the Cookie Policy, linked at the bottom of every page.

The contact form has no database behind it: Messages go through a small Cloudflare Worker that checks Cloudflare Turnstile on the server and sends the message by email through an EU mail provider. No form plugin, no stored submissions.

A security.txt file: If you find a vulnerability, /.well-known/security.txt tells you how to report it, following RFC 9116. Fitting for a security blog, and something the old site never had.

Fewer moving parts: There is no admin login to attack, no database to dump and no plugin to exploit. The most important thing to protect is now the GitHub account that publishes the site, so that’s where the security effort goes.

Writing new articles

Every article is now a Markdown file in a Git repository. I write in VS Code, screenshots go into the same folder as the article, and every change is version-controlled. If I make a mistake, I can roll back. If a reader spots an error, the history shows exactly what changed and when.

For quick fixes away from my laptop, the site is set up for Pages CMS, a simple editor in the browser that commits straight to the repository. When I push a change, Cloudflare builds and publishes the site automatically.

What I learned

  1. Audit before you design: Exporting all URLs and SEO data first made every later decision easier. You can’t keep what you never wrote down.
  2. Treat a theme like a dependency: Pin the version, don’t edit it, and keep a list of what you override. Upgrades become a checklist instead of a gamble.
  3. Check the content, not just the pages: Automated checks on tables and images found problems that had been invisible on the old site for years.
  4. Privacy is a design choice: Loading nothing before consent was easier to build from scratch than to bolt onto a plugin stack.
  5. Static is a security feature: The safest login page is the one that doesn’t exist.

I’ll share real performance numbers (Lighthouse and Core Web Vitals) once the new site has been live for a few weeks. If you notice anything that looks broken or a link that no longer works, please let me know.

Sources

Conclusion

Moving Modern Security from WordPress to Hugo and Blowfish wasn’t about chasing a new tool. It was about applying the same principles I write about here to my own site: reduce the attack surface, control what runs, and don’t collect more data than you need.

The result is a blog that’s faster to maintain, easier to secure and more respectful of your privacy, with every old link still working.

Same content. Same addresses. Far fewer moving parts.

Farid Kalaidji

Farid Kalaidji

Security expert with expertise spanning MxDR, detection engineering, digital forensics, cybercrime and privacy. On Modern Security I share practical, tested guides on the Microsoft security stack.

Keep reading