wiki-vault/Sources/Dev/cloudflare-cache-rules.md
Travis Herbranson 34a268d8dc migration: copy 62 notes from pbs-projects and homelab-projects
Two-layer structure: Sources (raw notes) + Wiki (compile output)
Four domains: Dev (40), Venture (3), Homelab (23), Reference (0)
Includes CLAUDE.md spec, index pages at all levels, compile log

Co-Authored-By: Lovebug <lovebug@herbylab.dev>
2026-05-08 17:21:13 -04:00

4.4 KiB

created path project status tags type updated
2026-03-30 Sources/Dev cloudflare-cache-rules active
pbs
cloudflare
caching
production
wordpress
session-notes 2026-03-30

Cloudflare Cache Rules - Fix & Cleanup - March 30, 2026

Problem

After production server migration (clone → update → promote), Cloudflare cache broke admin functionality. Jenny's post edits were reverting on save — the editor was serving stale cached versions of wp-admin pages. Both the IP-based bypass rule and the wp-admin path bypass rule were failing.

Root Causes Found

1. Cloudflare Cache Rules use "last match wins"

Unlike Page Rules (first match wins), Cache Rules are stackable — all matching rules apply, and for conflicting settings, the last matching rule wins. Our bypass rules were ordered above the Cache Everything rule, so Cache Everything was always winning.

2. Missing leading slashes on URI paths

The wp-admin bypass rule had wp-admin instead of /wp-admin, so it never matched actual request paths like /wp-admin/post.php.

3. Invalid n8n/Gitea entries in path rules

Full URLs (https://n8n.plantbasedsoutherner.com) were in URI Path filters, which only match path portions (like /wp-admin/). These entries were doing nothing. n8n and Gitea already have Cloudflare proxy disabled, so cache rules aren't needed for them.

4. Staging URL contamination

473 references to staging.plantbasedsoutherner.com were baked into the WordPress database from the server migration — post content, Elementor data, postmeta, GUIDs, and plugin caches.

What We Fixed

Cache Rule Reordering

Moved Cache Everything to position 1 (top) with bypass rules below it. Since last match wins, the bypass rules now correctly override caching.

Current rule order:

  1. Cache Everything (2hr Edge TTL, 1 day Browser TTL, serve stale while revalidating)
  2. Bypass Cache - PBS Admins (cookie: pbs_admin_bypass)
  3. Bypass Cache - WP Admin Paths (/wp-admin, /wp-login.php)
  4. Bypass Cache - WooCommerce (/cart, /checkout, /my-account, woocommerce cookie)

URI Path Fixes

  • Added leading slashes: /wp-admin, /wp-login.php, /cart, /checkout, /my-account
  • Removed invalid full-URL entries for n8n and Gitea
  • Replaced IP-based bypass with custom pbs_admin_bypass cookie
  • Confirmed working via Cloudflare Trace and DevTools (CF-Cache-Status: DYNAMIC)
  • Cookie set manually in DevTools for now — WPCode snippet for auto-set on admin login is next

Staging URL Cleanup

  • Ran WP-CLI search-replace inside Docker container:
    docker exec -it wordpress wp search-replace 'staging.plantbasedsoutherner.com' 'plantbasedsoutherner.com' --all-tables --allow-root
    
  • 473 replacements made across wp_posts, wp_postmeta, and GUIDs
  • Flushed Redis object cache: wp cache flush --allow-root
  • Manually cleared stale plugin caches: Jetpack site icon, Astra partials cache
  • Deleted astra_partials_config_cache from wp_options to force regeneration

Debugging Tools Used

  • Cloudflare Trace (Rules → Trace): Simulates a request and shows which rules match in order — confirmed both bypass and Cache Everything were firing, with Cache Everything winning
  • Browser DevTools Network tab: Checked CF-Cache-Status response header
  • curl blocked by Cloudflare bot challenge (Bot Fight Mode) — use DevTools instead

Key Learnings

  • Cloudflare Cache Rules: last match wins — opposite of Page Rules. Put broad rules first, specific overrides below.
  • URI Path filters only match paths — never full URLs with hostnames
  • Always include leading slashes in URI path filters (/wp-admin not wp-admin)
  • Server cloning contaminates URLs — always run wp search-replace after migrating/cloning WordPress between environments
  • WP-CLI handles serialized data safely — never do raw SQL find-and-replace on WordPress content (Elementor data can break)
  • wp-config.php tip: Add define('FS_METHOD', 'direct'); to suppress FTP credentials prompt in Docker

Still To Do

  • WPCode Lite snippet to auto-set pbs_admin_bypass cookie on admin login
  • Clean up Rule 2 extra expressions (leftover tjherbranson wildcard and starts_with conditions)
  • Create scoped Cloudflare API token (Zone.Cache Purge only)
  • Build n8n auto-purge workflow (WordPress publish/update → Cloudflare targeted cache purge)
  • Decide: auto-purge homepage on content updates?