Skip to content

Protecting Craft CMS with Cloudflare

Andrew Fairlie
7 min read

Every website gets traffic it doesn't want, whether it runs on Craft CMS, WordPress or something built from scratch.

Bots outnumber humans on the web, and they try passwords on login pages, scanners probe for known vulnerabilities, forms fill up with spam, and crawlers work through every filter combination on your listing pages.

Cloudflare's firewall deals with most of that before it reaches your server and it's usually a quick and effective way to add extra protection to a Craft site.

Why put Cloudflare in front of Craft?

Cloudflare is a reverse proxy which means that visitors connect to Cloudflare, and Cloudflare connects to your server. It's basically a bouncer for your website.

It filters attacks before they arrive. Cloudflare's WAF (Web Application Firewall) blocks a lot of the bad stuff before it reaches your server. Its DDoS protection soaks up floods of traffic that would knock a single server over.

It can buy you time. Security advisories are rising across all software, as we wrote recently, because AI tools are finding long-standing bugs faster than ever. Updating is still the fix. But a WAF can block an exploit in the gap between a patch landing and your site being updated.

It protects your login pages. Rate limiting the login and password reset pages makes brute-forcing accounts far harder, and (for example) you can challenge anyone visiting /admin from outside the countries your team works in.

It deals with bots. Bot Fight Mode, controls for AI crawlers, and Turnstile (Cloudflare's privacy-friendly alternative to CAPTCHAs) for your forms.

It takes load off your server. Images, CSS and JavaScript (and, with Blitz, whole pages) are served from Cloudflare, so traffic spikes hit Cloudflare rather than Craft.

It hides your server. Attackers see Cloudflare's IP addresses, not yours. But only if you finish the job, which we cover further down.

The firewall rules to start with

Cloudflare maintains rulesets that block common attacks and known exploits, and updates them as new threats appear. Free plans get a smaller free ruleset, while Pro and above get the full Cloudflare Managed Ruleset and the OWASP Core Ruleset.

You should check the Cloudflare security events for the first few days after enabling it, so you can catch any false-positives and add rules in place to mitigate.

Block the noise

Bots don't necessarily know you're using Craft, and quite often just assume you're running WordPress. A custom rule can block requests for things that will never exist on a Craft site:

(starts_with(http.request.uri.path, "/wp-"))
or (http.request.uri.path eq "/xmlrpc.php")
or (starts_with(http.request.uri.path, "/.env"))
or (starts_with(http.request.uri.path, "/.git"))

Set the action to Block. One catch: if you moved from WordPress and still redirect old /wp-content/ URLs, adjust the rule first.

Protect the control panel

A custom rule can challenge anyone else who visits the control panel:

(starts_with(http.request.uri.path, "/admin") and not ip.src.country in {"GB"})

Set the action to Managed Challenge, swap in your own cpTrigger if it isn't admin, and list the countries your team actually works from. For tighter control, Cloudflare Access can put the whole control panel behind your company login or limit to to your VPN IP.

Be careful with Bot Fight Mode

Bot Fight Mode is a one-click way to challenge automated traffic, but on the Free plan you can't make exceptions to it. That can catch traffic you want, like payment gateway webhooks for Craft Commerce or your uptime monitoring. If you rely on those, leave it off, or use Super Bot Fight Mode on Pro and above, which lets you skip trusted traffic.

Combining it with Blitz

Firewall rules stop the obviously naughty traffic but a lot of unwanted traffic looks perfectly normal, like an aggressive crawler or a sudden spike, and every one of those requests still has to be rendered by your server. Blitz is the most popular full-page caching plugin for Craft and has Cloudflare support built in. With it, warmed pages are served straight from Cloudflare.

Out of the box, Cloudflare doesn't cache HTML. It caches your images and CSS, but every page request still goes to your server. Blitz fixes that from both ends:

  1. Blitz sends Cache-Control headers telling Cloudflare which pages it can cache, and for how long.
  2. You add a Cache Rule in Cloudflare so HTML is eligible for caching and respects those headers.
  3. Blitz's Cloudflare purger clears the right pages when content changes.

A cached page is the same for everyone, so anything personal (a logged-in user's name, a basket count, a form's CSRF token) needs loading separately. Blitz has helpers for this, like craft.blitz.csrfInput() and dynamic includes, which fetch those pieces after the page loads.

Also remember scheduled content. Craft doesn't fire an event when a post date arrives, so run php craft blitz/cache/refresh-expired on a cron to make future-dated entries appear when they should.

Rolling a custom module: feed Craft's signals into the firewall

If you're comfortable writing a module or a plugin (or having an agent write a small one for you) and it's a simple site, you could write your own module that sets the appropriate headers and sends purge events to Cloudflare.

Servd and Craft Cloud are already protected

If your site is on Servd or Craft Cloud, most of this is done for you. Both put every site behind Cloudflare's enterprise-level protection, and you don't have to set up a thing.

But doing so means you give up control over the Cloudflare setup. For example, you can't add your own rate limits or WAF rules to your host's Cloudflare setup. If you need those, you can put your own Cloudflare zone in front as well (Craft Cloud documents this as "orange-to-orange"), but for most sites the defaults are plenty and certainly a lot better than not having them.

Both hosts also have their own take on caching, so check their docs before layering Blitz or your own purging on top.

Block non-Cloudflare traffic

Cloudflare only protects traffic that goes through Cloudflare. If someone finds your server's real IP address, they can skip the WAF, the rate limits and the bot protection entirely.

So lock the server down so it only talks to Cloudflare. One of the simplest ways to do this is to update your firewall to only accept traffic from Cloudflare IPs. 

Also be sure to set Cloudflare's SSL mode to Full (strict), and don't forget SSH, staging sites and anything else on the same box.

The downsides

You'll probably have to move your DNS

On Cloudflare's Free and Pro plans, Cloudflare has to run DNS for your whole domain, which means changing your nameservers.

The alternative, a partial (CNAME) setup where your DNS stays put and you point individual hostnames at Cloudflare, is only available on Business and Enterprise. And even then, Cloudflare's DDoS protection for DNS itself only comes with the full setup.

But DNS is often looked after by an IT team or supplier, it holds email records (MX, SPF, DKIM and DMARC) that really can't break, and moving it becomes a project of its own.

Servd and Craft Cloud can fill the gap

With a managed host, you add a CNAME record at your existing DNS provider and their enterprise Cloudflare setup sits in front of your site. That's enterprise-grade protection with no Business plan, no nameserver change, and no tricky conversation with IT about email records.

Cache only what you need

If purging misses something, people see stale content. Pages with forms may quietly not cache because of session cookies. Live Preview and share links need to bypass the cache entirely. 

Cloudflare's limits become your limits

  • Uploads: request sizes are capped at 100MB on Free and Pro, so large uploads through the control panel will fail.
  • Timeouts: if your server takes longer than 100 seconds to respond, Cloudflare gives up with a 524 error. Big exports and resaves in the control panel can hit this.
  • False positives: rich text containing code snippets or embed codes can look like an attack to the WAF. Expect to add some exceptions for control panel routes.

Privacy and lock-in

Cloudflare decrypts your traffic to inspect it, so it belongs in your privacy policy and data processing agreements. And config built around Cloudflare doesn't move easily to another provider.

So, which route?

  • On Servd or Craft Cloud: you're already behind Cloudflare, so unless you need specific rules or configurations you can probably sleep well at night and use your attention on other security improvements.
  • Self-hosting: start with the firewall rules above, then lock down the server so nobody can go around them. Add Blitz if you want the edge to absorb traffic spikes, and a custom module if you want Craft's own signals feeding your rules.
  • Self-hosting and can't move your DNS: a Business plan gets you a partial setup, or consider a host that brings Cloudflare with it.

And remember, even when fully setup: it's another tool in your arsenal, not a silver bullet.

Andrew Fairlie
Andrew Fairlie
Technical Director · 13+ years with Craft CMS

Andrew is Technical Director at Mutual, a Craft CMS Partner agency. He has been building with Craft CMS since its public beta in 2012 — working through every major version from Craft 1 to Craft 5 — and has delivered over 100 sites for clients including Apple, Transparency International, and Arts University Bournemouth.

He writes about Craft CMS on the Mutual blog and has contributed to net Magazine. At Mutual, he leads development of Mutual One, a marketing platform built on Craft CMS as its foundation.

He has spoken about Craft CMS to undergraduate students at the University of Brighton and Canterbury Christ Church University, and appeared on the Devmode.fm podcast. He has also trained other developers on working with the platform.

More from the blog

Let's get your site
where it should be

Tell us a bit about your site and what it needs to do. We'll reply within a working day, and you'll be talking to the people who'd do the work.