Own a domain? Host it free on Cloudflare Pages — and lock it down. This generates five free-plan WAF rules plus a deploy checklist that block roughly 95% of hostile traffic against a static site. The rules key only on hard signals (method, verified-bot status, country, path, rate), so they stay effective even though they're public — no security-through-obscurity, and a static origin has no server logic for the rest to attack.
Try it now
💡 Good to know: Good security rules don't depend on being secret; they key on signals an attacker can't fake, so publishing them changes nothing.
Worked example
# ============================================================
# GG Cloudflare Pages Hardening — example.com
# 5 free-plan WAF rules. Security -> WAF -> Custom rules.
# Public-safe by design: every rule matches hard, unforgeable
# signals, so it holds even though attackers can read it.
# ============================================================
## Rule 1 — Method lockdown [action: Block]
# A static site needs only these methods. Block the rest.
(not http.request.method in {"GET" "HEAD" "OPTIONS"})
## Rule 2 — Bot sieve [action: Managed Challenge]
# Challenge non-verified bots with a bad/empty user agent or a
# high threat score. Verified search crawlers are exempt (SEO safe).
(not cf.client.bot and (http.user_agent eq "" or cf.threat_score gt 14))
## Rule 3 — Region gate [action: Managed Challenge]
# Allow the countries you serve; challenge/deny the rest.
# Verified search bots are exempt so global crawling still works.
(not ip.geoip.country in {"US" "CA" "GB"} and not cf.client.bot)
## Rule 4 — Exploit-path block [action: Block]
# A static host serves none of these — any request for them is hostile.
(ends_with(http.request.uri.path, ".php")
or ends_with(http.request.uri.path, ".env")
or ends_with(http.request.uri.path, ".sql")
or ends_with(http.request.uri.path, ".bak")
or http.request.uri.path contains "/.git/"
or http.request.uri.path contains "/wp-"
or http.request.uri.path in {"/.env" "/xmlrpc.php" "/.aws/credentials" "/config.php"})
## Rule 5 — Rate limit [Security -> Rate limiting rules]
# Blunt scrapers and floods. Static assets are cache-cheap, so real
# visitors never notice.
# When: requests from one IP exceed 120 / 1 minute
# Then: Managed Challenge for 60 seconds
# Expression: (http.host eq "example.com")
# ---- Deploy checklist ----
# 1. Cloudflare -> Pages -> Create project -> connect repo or upload your dist/.
# 2. Custom domains -> add example.com (Cloudflare proxies it automatically).
# 3. Add a hardened _headers file (use the GG "Security Headers" tool).
# 4. Security -> WAF -> Custom rules -> add rules 1-4 (paste each expression).
# 5. Security -> Rate limiting rules -> add rule 5.
# 6. SSL/TLS -> Full (strict); turn on "Always Use HTTPS".
# Done. This stops ~95% of hostile traffic; the static origin has no
# server logic for the last 5% to attack.
Allowed countries (2-letter, comma-sep) US, CA, GB
Rate limit (req/min per IP) 120
Bot / region action Managed Challenge / Block
Site has a form / function (allow POST)? No / Yes
Frequently asked
Why only 5 rules?
Cloudflare's free plan allows 5 WAF custom rules. Against a static site that's plenty — the five here cover method abuse, bad bots, region, exploit-path scans and floods.
Will these hurt my SEO?
No. The bot and region rules explicitly exempt verified search crawlers (cf.client.bot), so Googlebot and friends pass through.
Aren't public rules easy to bypass?
They're built to be public-safe: every rule matches unforgeable signals, and they layer, so evading one still leaves the others. The origin is a static bucket with nothing to exploit.