⚠️ v2.4.0 — Profile Management Update
Rule profiles now use a beta → release workflow.
See Profile Management below.
- Beta channel —
mwp-rules-beta.jsonis the new staging profile for rule changes - Default symlink —
default.jsonis a symlink to the latest numbered release bin/build.sh— Unified build orchestrator (generate-md, generate-readme, or all)bin/release.sh— Promote beta to a numbered release with one command- v3 schema — All bundled profiles now use the v3 Rulesets API format natively
- Rulesets API — Replaced the deprecated Firewall Rules & Filters APIs with the modern Rulesets API. All
create-rules,update-rules,list-rules, anddelete-*commands now use the new API behind the scenes. migrate-to-rulesets— One-time command to convert existing Firewall Rules to the Rulesets API format (with optional--delete-oldcleanup).- Skip action —
allow/bypassactions are replaced by the unifiedskipaction. v2 profiles are auto-converted when read. - Custom block responses — The
blockaction now supports configurable status codes, content, and content types. - Rate limiting — Rate limit configuration can be defined directly within custom rules.
- New commands —
ruleset-get-entrypoint,ruleset-add-rule,ruleset-update-rule,ruleset-delete-rule. - Profile conversion —
bin/convert-profile-v2-to-v3.shconverts existing v2 profiles to v3 format for the new API. - Deprecated — Filter commands (
list-filters,get-filter,delete-filter,delete-filters) still work but show warnings.
This repository provides a bash script for the creation of Cloudflare WAF rules for WordPress specific sites. It also provides a script for creating API tokens and turnstile widgets for Cloudflare.
| File | Description |
|---|---|
| cloudflare-wordpress-rules.sh | Bash script to create Cloudflare WAF and Cache rules (uses Rulesets API) |
| cloudflare-token.sh | Create and manage Cloudflare API tokens (including for the Super Page Cache plugin) |
| cloudflare-turnstile.sh | Creates turnstile widgets for Cloudflare |
| PROFILES.md | v3 profile format reference (Rulesets API) |
| zones.txt.example | Example zones file for multi-zone operations |
| File | Description |
|---|---|
inc/cf-inc-rulesets.sh |
Rulesets API functions (entry point, CRUD, migration tool) |
inc/cf-inc-wp.sh |
Profile-based rule management (v3 compatible) |
inc/cf-inc-api.sh |
Core API functions (includes deprecated Firewall Rules API for backward compat) |
| File | Description |
|---|---|
bin/build.sh |
Unified build orchestrator — regenerate .md files, update README changelog |
bin/release.sh |
Promote beta to a numbered release (snapshot, version substitution, symlinks) |
bin/convert-profile-v2-to-v3.sh |
Converts v2 profiles to v3 (Rulesets API) format |
| File | Description |
|---|---|
bin/convert-profile-v2-to-v3.sh |
Converts v2 profiles to v3 (Rulesets API) format |
| docs/ruleset_plan.md | Full migration plan and API reference |
profiles/features-skip.md |
Skip action guide |
profiles/features-block-response.md |
Custom block response guide |
profiles/features-rate-limiting.md |
Rate limiting guide |
All scripts read credentials from a single config file at: ~/.cloudflare.
You can define either generic (default) credentials or multiple named profiles. If multiple profiles exist, the scripts will offer an interactive menu to choose which profile to use.
- Generic (fallback) credentials:
CF_ACCOUNT+CF_KEY(Global API Key auth), orCF_TOKEN(scoped API Token auth)
- Profile-based credentials (recommended):
CF_ACCOUNT_<PROFILE>+CF_KEY_<PROFILE>CF_TOKEN_<PROFILE>
Profiles are any uppercase name you choose (e.g., PROD, DEV, CLIENT1). The scripts will detect all CF_(ACCOUNT|TOKEN|KEY)_<PROFILE> entries and list them for selection.
- A specific profile you pass explicitly using
--cf-profile(or--cf-auth-profile) - Interactive choice (if multiple profiles are found)
- Generic credentials:
CF_TOKENorCF_ACCOUNT+CF_KEY
Minimal (generic) credentials:
# Uses a single default set for all scripts
CF_ACCOUNT=example@domain.com
CF_KEY=your_global_api_key
# OR
CF_TOKEN=your_api_token
Multiple profiles (recommended):
# Production
CF_ACCOUNT_PROD=prod@company.com
CF_KEY_PROD=prod_global_api_key
# OR
# CF_TOKEN_PROD=prod_api_token
# Development
CF_TOKEN_DEV=dev_api_token
# Client-specific
CF_ACCOUNT_CLIENT1=client1@theircompany.com
CF_TOKEN_CLIENT1=client1_api_token
Legacy (still supported):
# Super Page Cache (legacy keys remain compatible)
CF_ACCOUNT_SPC=spc@company.com
CF_TOKEN_SPC=spc_api_token
# Turnstile (legacy keys remain compatible)
CF_ACCOUNT_TS=turnstile@company.com
CF_TOKEN_TS=turnstile_api_token
See .cloudflare.example in the repo root for a complete, commented template.
- Token auth is preferred: safer and easier to scope (
Zone.Firewall Services:Edit, etc.). - Some commands do not require authentication and will run without reading
~/.cloudflare:list-profilesprint-profile <profile>validate-profile <profile>list-auth-profiles
Bash script to create and manage Cloudflare WAF rules for WordPress sites through the Cloudflare API. Supports batch operations across multiple zones.
cloudflare-wordpress-rules -d <domain> -c <command> [options]
RULES COMMANDS (Rulesets API)
create-rules <profile> Create rules on domain using profile
update-rules <profile> Update rules on domain using profile
upgrade-default-rules Upgrade MWP default rules on domain
list-rules List rules on domain
delete-rule <id> Delete specific rule by ID
delete-rules Delete all rules on domain
PROFILE COMMANDS
list-profiles List available rule profiles
print-profile <profile> Print rules from profile
validate-profile <profile> Validate profile JSON syntax
RULESET COMMANDS
list-rulesets List rulesets on domain
get-ruleset <id> Get specific ruleset by ID
get-ruleset-fw-custom Get http_request_firewall_custom ruleset
ruleset-get-entrypoint Get the WAF custom rules entry point
ruleset-add-rule <json> Add a single rule to the entry point
ruleset-update-rule <id> <json> Update a single rule in the entry point
ruleset-delete-rule <id> Delete a single rule from the entry point
migrate-to-rulesets [--delete-old] Migrate old Firewall Rules to Rulesets API
FILTER COMMANDS (DEPRECATED since 2025-06-15)
list-filters List filters on domain
get-filter <id> Get specific filter by ID
delete-filter <id> Delete specific filter by ID
delete-filters Delete all filters on domain
SETTINGS COMMANDS
get-settings Get security settings on domain
set-settings <setting> <value> Set security setting
Settings: security_level, challenge_ttl, browser_integrity_check, always_use_https
AUTH COMMANDS
list-auth-profiles List available authentication profiles
OPTIONS
-d, --domain <domain> Domain to operate on (can be used multiple times)
-zf, --zones-file <file> Load zones from file (one per line)
-y, --yes Skip confirmation prompt for multi-zone ops
-c, --command <cmd> Command to execute
--cf-profile <name> Cloudflare auth profile from .cloudflare
--cf-auth-profile <name> Alias for --cf-profile
--debug Enable debug mode
--table-only list-rules only: show table output and errors only
-dr, --dryrun Dry run, don't send to Cloudflare
# Create rules on a single domain
cloudflare-wordpress-rules -d domain.com -c create-rules default
# Create rules and force a specific auth profile
cloudflare-wordpress-rules -d domain.com -c create-rules default --cf-profile PROD
# List rules on a domain
cloudflare-wordpress-rules -d domain.com -c list-rules
# List rules with table output only (keep errors visible)
cloudflare-wordpress-rules -d domain.com -c list-rules --table-only
# Delete a specific rule
cloudflare-wordpress-rules -d domain.com -c delete-rule 1234567890
# Get security settings
cloudflare-wordpress-rules -d domain.com -c get-settings
# Set security level
cloudflare-wordpress-rules -d domain.com -c set-settings security_level high
# One-time migration from old Firewall Rules to Rulesets API
cloudflare-wordpress-rules -d domain.com -c migrate-to-rulesets
# Migration + cleanup of old rules
cloudflare-wordpress-rules -d domain.com -c migrate-to-rulesets --delete-oldThe repository uses a beta → release workflow:
mwp-rules-beta.json— Staging profile for rule changes (IPs, UAs, expressions)default.json— Symlink to the latest numbered release (current stable)mwp-rules-v<NNN>.json— Versioned release snapshots
# Edit profiles/mwp-rules-beta.json with your changes
# Then regenerate the markdown documentation:
bin/build.sh generate-md
# Commit your changes:
git add profiles/mwp-rules-beta.*
git commit -m "feat: update beta rules"cloudflare-wordpress-rules -d staging.example.com -c create-rules mwp-rules-beta# Create release v208 from beta:
bin/release.sh 208
# Commit and tag:
git add profiles/mwp-rules-v208.* profiles/default.* VERSION
git commit -m "feat: release mwp-rules-v208"
git tag v208
# Update README changelog from git log:
bin/build.sh generate-readme# Default profile always points to the latest release:
cloudflare-wordpress-rules -d domain.com -c create-rules default
# Or upgrade an existing deployment:
cloudflare-wordpress-rules -d domain.com -c upgrade-default-rulesThe Firewall Rules API and Filters API were deprecated by Cloudflare on 2025-06-15 and replaced by the Rulesets API. This repository has been fully migrated to the new API.
| Aspect | Old (Firewall Rules API) | New (Rulesets API) |
|---|---|---|
| Rule creation | 2 API calls per rule (filter + rule) | 1 API call (expression inline) |
| Profile schema | v2 with priority field |
v3 with enabled/logging/action_parameters |
| Skip action | allow + bypass (two actions) |
skip (one action with config) |
| Custom responses | Not supported | Supported for block action |
| Logging control | Not supported | Per-rule logging.enabled |
| Rate limiting | Separate product | Configurable within custom rules |
| Old Action | New Action | Notes |
|---|---|---|
allow |
skip with "ruleset": "current" |
Stops evaluating remaining custom rules |
bypass |
skip with "phases": [...] |
Skips specific security products |
block |
block |
Same, with optional custom response |
challenge / js_challenge / managed_challenge |
Same | No changes needed |
log |
log |
Same |
If you have existing Firewall Rules on your zones, use the migration tool to convert them:
# Preview the migration (rules will be applied, old ones preserved)
cloudflare-wordpress-rules -d domain.com -c migrate-to-rulesets
# Full migration with cleanup of old rules + filters
cloudflare-wordpress-rules -d domain.com -c migrate-to-rulesets --delete-old
# Multi-zone migration
cloudflare-wordpress-rules -zf zones.txt -c migrate-to-rulesetsThe migration tool:
- Fetches all existing Firewall Rules via the old API
- Converts them to Rulesets API format (allow→skip, priority removed, etc.)
- Applies them to the phase entry point
- Optionally deletes old rules and filters after verification
Convert existing v2 profiles to v3 format:
bin/convert-profile-v2-to-v3.sh profiles/default.json profiles/default-v3.jsonFor the Rulesets API, ensure your API token includes at least one of:
Zone WAF Write— for zone-level custom rulesZone Rulesets Write— for zone-level ruleset managementAccount WAF Write— for account-level custom rulesetsAccount Rulesets Write— for account-level ruleset management
The old Zone.Firewall Services:Edit permission may still work for backward compatibility but the new permissions are recommended.
The script supports running commands across multiple zones at once. This is useful for managing rules on many domains.
Use the -d flag multiple times:
cloudflare-wordpress-rules -d site1.com -d site2.com -d site3.com -c create-rules defaultCreate a text file with one domain or zone ID per line:
# zones.txt
site1.com
site2.com
site3.com
# Comments are supported
example.org # inline comments tooThen reference it with -zf:
cloudflare-wordpress-rules -zf zones.txt -c create-rules defaultYou can also combine both methods:
cloudflare-wordpress-rules -zf zones.txt -d extra-site.com -c list-rulesBy default, the script will list all affected zones and ask for confirmation before proceeding. Use -y to skip:
cloudflare-wordpress-rules -zf zones.txt -c delete-rules -ycreate-rules- Create rules on all specified zonesupdate-rules- Update rules on all specified zoneslist-rules- List rules from all specified zonesdelete-rules- Delete rules from all specified zonesget-settings- Get settings from all specified zonesset-settings- Set settings on all specified zones
The script will process each zone sequentially and provide a summary at the end showing:
- Total zones processed
- Number of successful operations
- Number of failed operations
- List of failed zones (if any)
Profiles are stored in the profiles directory. They are JSON files that contain the rules to be created. The profile name is the filename without the .json extension.
{
"rules": [
{
"action": "block",
"description": "Block bad bots",
"filter": {
"expression": "(http.user_agent contains \"WPScan\")",
"paused": false
}
},
{
"action": "block",
"description": "Block bad bots",
"filter": {
"expression": "(http.user_agent contains \"WPSpider\")",
"paused": false
}
}
]
}
This script creates and manages Cloudflare API tokens, including tokens for the Super Page Cache for Cloudflare WordPress plugin. Supports account-owned tokens.
Usage: cloudflare-token.sh [command] [options]
Commands:
create-token <domain> <token-name> Create API token for domain
list List account tokens
test-creds Test credentials against Cloudflare API
test-token <token> Test created token against Cloudflare API
Options:
-z, --zone <zoneid> Set zone ID
-a, --account <email> Cloudflare account email address
-t, --token <token> API Token to use
-ak, --apikey <apikey> API Key to use
--cf-profile <name> Cloudflare auth profile from .cloudflare
--cf-auth-profile <name> Alias for --cf-profile
-d, --debug Debug mode
-dr, --dryrun Dry run mode
This script creates and manages Cloudflare Turnstile widgets.
Usage: cloudflare-turnstile.sh [command] [options]
Commands:
create Create a turnstile widget
list List account turnstiles
delete Delete a turnstile
test-creds Test credentials against Cloudflare API
Options:
-z, --zone <domain> Zone domain name
-a, --account <email> Cloudflare account email address
-t, --turnstile <sitekey> Turnstile Sitekey
-tn, --turnstile-name <name> Turnstile Name
-ak, --apikey <apikey> API Key
--cf-profile <name> Cloudflare auth profile from .cloudflare
--cf-auth-profile <name> Alias for --cf-profile
-d, --debug Debug mode
-dr, --dryrun Dry run mode
Generated using git log --pretty=format:"## %s%n%b%n" | sed '/^## /b; /^[[:space:]]*$/b; s/^/* /' > CHANGELOG.md
-
- Added Screaming Frog to allow list.
-
- Updated rules to v205
-
- improvement: Added color to the usage screen
-
- fix Updated CHANGELOG.md and README.md as well as profiles/mwp-rules-v204-beta.md
-
- Add multi-zone support for batch operations
-
- Add support for multiple -d flags to specify multiple domains
-
- Add -zf|--zones-file flag to load zones from a file
-
- Add -y|--yes flag to skip confirmation prompts
-
- Add zone deduplication to prevent processing same zone twice
-
- Add confirmation prompt showing affected zones before execution
-
- Add summary output with success/failure counts per zone
- New functions in cf-inc.sh:
-
- _load_zones_file: Parse zones file with comment support
-
- _deduplicate_zones: Remove duplicate zones from array
-
- _confirm_zones: Display zones and prompt for confirmation
-
- _run_on_zones: Execute command across multiple zones with progress
- Commands supporting multi-zone:
-
- create-rules, update-rules, list-rules, delete-rules
-
- get-settings, set-settings
- Files changed:
-
- cloudflare-wordpress-rules.sh: Multi-zone CLI and command integration
-
- cf-inc.sh: Multi-zone support functions
-
- CHANGELOG.md: Release notes for v2.2.0
-
- README.md: Multi-zone documentation and examples
-
- VERSION: Bump to 2.2.0
-
- TODO.md: Mark completed items
-
- zones.txt.example: Template for zones file format
- (af39726) (HEAD -> dev, origin/dev) fix: add domain validation for get-settings and support filtering by specific setting parameter
- (2270998) Updated usage for get-settings and set-settings
- (de29bfb) (HEAD -> dev, origin/dev) chore: Updated README.md to better document .cloudflare file
- (f03c426) improvement: Updated authentication system.
- (68ac46b) Merged changes that were missing
- (32ed657) Added TODO.md
- (92b0b14) Small fixes
- (d5d41e5) Added mwp-rules-v204-beta.md
- (9e6d417) Added asn.txt for building rules
- (cf3f595) Updated API credentials system to enable multiple profiles
- (6dc4a1b) (HEAD -> dev, origin/dev) Small fixes
- (5f97c85) Created v204-beta rules
- (04727ce) Backup of default rules v203 and create v204 beta
- (1100cfc) improvement: Better messaging on what key/token is being utilized
- (23623ea) improvement: Renamed cloudflare-spc.sh to cloudflare-token.sh Added create-app-cf for app for cloudflare plugin Created list-perissions Created list-permission-groups
- improvement(spc): Improved test-token command
- fix(profiles): Fixed improper naming of profiles
- fix(bin): Fixed generate-md.sh locatiing profiles dir
- refactor: Brought in cf-inc-refactor.sh for reference
- enhance: Added ipblocks-ua template for rule R2
- fix: Renamed files
- improvement: Created ipblocks-ua-qs method
- fix: Updated .gitignore to only skip .json within profiles directory
- fix: Errors with tyepset and declare
- fix: Profiles with incorrect json
- improvement: Created print-profiles command
- feat(profile): Added block-event-calendar.json
- style: Added .shellcheckrc
- enhance: Added ips for blogvault and wp-umbrella, as well as useragents and querystrings for ipblocks-ua-qs
- refactor: Shifted old code into cf-inc-old.sh
- fix: Fixed shellcheck errors
- refactor: Fixed shellcheck errors in cf-in-api.sh increased to v1.5
- fix: Increase version number for cf-inc-api.sh properly.
- test: Added cf-settings.json
- fix: Changed WP Umbrella User Agent to WPUmbrella
- refactor: Moved settings based api commands to cf-inc-api.sh
- fix: Small adjustments
- refactor: Removed settings from cf-inc-old.sh
- refactor: Removed create-rules-v1
- refactor: Renamed create-rules-profile to create-rules
- refactor: Moved rules and profile functions to cf-inc-wp.sh
- Added some debugging
- Reverted shellcheck code.
- chore: Removed unecessary files and updated README.md
- docs: Updated cloudflare-waf-wordpress.md
- Small fixes
- feat: Created update-rule function
- Small changes
- fix(profile): Added profile data for rule_number and rule_version
- improvement: Added code for upgrading the default rule
- Added test-perms
- chore: Moved ipblocks-ua-qs to it's own folder.
- chore: Moving archives around
- improvement(rules): Updated default to include Infusionsoft useragent.
- fix: Moved generate-readme.sh to bin and updated paths
- chore: Moved scripts into /bin
- chore: Created default.md for default.json
- fix(core): Brought back set-settings
- fix(core): Merged code without testing.
- improvement(cf-api): Udpated cf-inc-api.sh to v1.4
- docs(cf-inc): Fixed documentation.
- refactor(cloudflare-spc): Refactored some aspects of cloudflare-spc
- improvement(inc): Updated cf-inc.sh
- improvement(core): Updated inc files formatting
- refactor(core): Moved api commands to cf-api-inc.sh
- improvement(api): Updated cf-inc-api.sh to v1.1
- improvement(api): Updated API file location
- improvement(api): Updated cfi-in-api.sh location
- improvement(api): Updated cf-inc-api.sh to 1.2
- improvement(core): Updated cf-inc.sh to 2.1
- improvement(cf-turnstile): Updated create command to handle multiple accounts
- improvement: Updated Managing WP rules to v201.
- fix: Fixed issue with MWP rules .md and json differing.
- improvement: Created profiles-archive of older profiles.
- refactor(spc): Refactored cloudflare-spc command
- improvement: Ask to delete all rules, versus one by one.
- improvement: Created profile with mwp-rules-v2 including event calendars bot blocking
- improvement: Created generate-readme.sh to generate/add CHANGELOG.md to README.md
- improvement(doc): Updated README.md
- improvement(profiles): Added mwp-rules-v1.json as an example
- fix: Addd /profiles to .gitignore for custom profile creation
- doc: Created CHANGELOG.md and command to generate it
- fix: Removed $ZONE_ID which is unused
- refactor: Moving cwr general commands into cf-inc.sh
- refactor: Clean-up and refactor to pass $ZONE_ID for functions
- fix: Adding pre-flight check.
- fix: Ensure user agents are contains not equals
- docs: Added more tests cf-create-filter.json cf-error.json cf-filter.json cf-rule.json cf-rules.json
- fix: Fixed deleting all rules
- test: Added more tests!
- refactor: Huge refactor for debugging
- refactor(major): Major refactor
- enhance: Creating cf-inc.sh and cf-api-inc.sh files
- enhance: Created cloudflare-turnstile.sh for turnstile widget creation
- improvement: Created tests directory with example cloudflare API json results
- fix(readme): Updated readme formartting
- fix(rulesv2): Added Let's Encrypt to useragent allow R2V2
- improvement(account-tokens): Added support for account owned tokens
- improvement(account-owned-tokens): Added additional permissions
- Added listing of account owned tokens.
- Updated README.md for cloudflare-spc.sh
- Updated user-agent for WP Umbrella to "WPUmbrella"
- Updated firewall rules to v2, an overhaul of the rules.
- Using R1V2 for naming scheme, R1 = Rule 1, V2 = Version 2
- Small fix to allow for multiple zones.
- fix: Error message wasn't updated to use $CF_SPC_TOKEN
- fix: Updated Rule #4 to included woo password-strength-meter.min.js
- 5ca3b1b fix: Updated user agent for WP Umbrella
- 33d83dc refactor: Refactored cloudflare-spc.sh, watch out!
- 56fbd31 Updated
- b43d126 Cleaned up the code a bit, changed -t to allow for specifiying a token if nothing in env or .cloudflare file. Fixed error handling.
- ecb1bfa - Working create token command with zoneid (16 hours ago)
- 6b5a07e - Major overhaul of functions (17 hours ago) d5b64de - Small code refactor and renaming. (4 weeks ago)
- 6c5c384 Code refactoring and variable changes for Cloudflare token.
- 3a1f9c7 Removed git merge comments
- 668773d Updated permissions.
- 1199d75 Updated user agents
- 22ca705 Updated
- 9408e41 Merge branch 'main' into dev
- fbbd977 Updated
- f1b4dae * Added cloudflare-spc.sh
-
- Created cloudflare-cache-wordpress.md for Cloudflare cache rules, and renamed cloudflare-protect-wordpress.md to cloudflare-waf-wordpress.md
-
- Reworked the code to support profiles that are file based.
- 3ca859e Update cloudflare-protect-wordpress.md
- 2d54676 Updated README.md some more and added in -d and -dr options
- 022d174 Added symlink for cloudflare-wordpress-rules to cloudflare-wordpress-rules.sh
- 5ac8a8c Updated README.md with usage information.
- a959c74 Merge branch 'main' of github.com:managingwp/cloudflare-wordpress-rules into main
- aae599f Updated to add WP Umbrella User Agent
- 5a6d0c0 Merge branch 'main' of github.com:managingwp/cloudflare-wordpress-rules into main
- fc64011 Update README.md
- 84fc6a0 Update cloudflare-protect-wordpress.md
- 71b2a80 Success was read instead of green!
- 8f8d675 Improved code overall
- bc72ee3 Created cloudflare-wordpress-rules.sh as an example to create rules automatically.
- 6caf689 Update cloudflare-protect-wordpress.md
- 9fb62d5 Update cloudflare-protect-wordpress.md
- 1ce5e59 Update cloudflare-protect-wordpress.md
- 4804f60 Update and rename cloudflare-protect-wordpress.rules to cloudflare-protect-wordpress.md
- ca0b3e6 Create cloudflare-protect-wordpress.rules
- f3c5be1 Update README.md
- f920d51 Initial commit