86 lines
4.4 KiB
Markdown
86 lines
4.4 KiB
Markdown
---
|
|
project: cloudflare-cache-rules
|
|
type: session-notes
|
|
status: active
|
|
tags:
|
|
- pbs
|
|
- cloudflare
|
|
- caching
|
|
- production
|
|
- wordpress
|
|
created: 2026-03-30
|
|
updated: 2026-03-30
|
|
path: PBS/Tech/Sessions/
|
|
---
|
|
|
|
# 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
|
|
|
|
### Cookie-Based Admin Bypass
|
|
- 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? |