-
Notifications
You must be signed in to change notification settings - Fork 1
Cloudflare Setup
Complete guide for setting up Doorman with Cloudflare WAF.
Status: Cloudflare support is in beta — actively developed, with comprehensive error handling, validation, and rule translation, but not yet as battle-tested as the stable Vercel Firewall support. Review changes carefully before applying to production.
- Cloudflare account with at least one domain
- Node.js 18+ installed
- Doorman installed (
npm install -g @gfargo/doorman)
- Go to Cloudflare API Tokens
- Click Create Token → Custom token
- Set these permissions:
| Permission Type | Permission | Access Level |
|---|---|---|
| Zone | Zone Settings | Read |
| Zone | Zone | Read |
| Zone | Firewall Services | Edit |
| Account | Account Rulesets | Edit (optional) |
- Under Zone Resources, select your domain (or "All zones from an account" for multiple domains)
- Optionally set Client IP Filtering and TTL for extra security
- Click Continue to summary → Create Token
- Copy the token immediately — you won't see it again
- Go to Cloudflare Dashboard and select your domain
- On the Overview page, find Zone ID in the right sidebar
- Copy it
The Account ID enables the Cloudflare Lists API for efficient bulk IP management.
- On any Cloudflare dashboard page, find Account ID in the right sidebar
- Copy it
Without an Account ID, Doorman falls back to individual IP rules instead of Lists.
export CLOUDFLARE_API_TOKEN="your_api_token_here"
export CLOUDFLARE_ZONE_ID="your_zone_id_here"
export CLOUDFLARE_ACCOUNT_ID="your_account_id_here" # OptionalOr create a .env file in your project root:
CLOUDFLARE_API_TOKEN=your_api_token_here
CLOUDFLARE_ZONE_ID=your_zone_id_here
CLOUDFLARE_ACCOUNT_ID=your_account_id_hereImportant: Add
.envto your.gitignoreto avoid committing secrets.
doorman init only supports Vercel today — it has no --provider flag and doesn't prompt for Cloudflare credentials. For Cloudflare, create .doorman.json manually:
{
"$schema": "https://doorman.griffen.codes/schema.json",
"provider": "cloudflare",
"providers": {
"cloudflare": {
"zoneId": "your_zone_id",
"accountId": "your_account_id"
}
},
"rules": [],
"ips": []
}Write rules by hand in your Cloudflare-provider config (see Configuration for the rule format). doorman template doesn't take a --provider flag or an add subcommand — doorman template <name> (e.g. doorman template bad-bots) only exists today, and it generates Vercel-format rules, not Cloudflare ones, so it isn't a fit for a Cloudflare config yet.
# Preview what will change
doorman diff --provider cloudflare
# Deploy rules
doorman sync --provider cloudflare
# Verify deployment
doorman status --provider cloudflaredoorman status --provider cloudflare # Check sync status and health
doorman list --provider cloudflare # List deployed rules
doorman diff --provider cloudflare # Preview pending changes
doorman sync --provider cloudflare # Deploy changes
doorman validate # Validate config syntax
doorman backup # Create a backup
doorman watch --provider cloudflare # Auto-sync on file changesDeploy a vendor-managed ruleset (Cloudflare Managed Ruleset, OWASP CRS, etc.) alongside your custom rules by adding managedRules to your config:
{
"managedRules": [
{
"ruleset": "efb7b8c949ac4650a09736fc376e9aee",
"enabled": true,
"action": "log"
}
]
}This example deploys Cloudflare's Managed Ruleset (that well-known id) with every rule downgraded to log — a safe way to see what it would block before enforcing anything. Drop the action override once you're ready to enforce, or use overrides to tune individual rules. Full field reference and an overrides example: Configuration#managed-rule-groups.
Managed rule groups deploy in Cloudflare's separate managed-rules phase, evaluated independently of your custom rules — no ordering interaction to think about between the two.
Create separate config files per zone by hand (see Initialize Your Project above), e.g. zone1.config.json and zone2.config.json, each with its own providers.cloudflare.zoneId.
With an Account ID, you can create rules that apply across all zones:
{
"providers": {
"cloudflare": {
"accountId": "your_account_id",
"useAccountRules": true
}
}
}| Plan | Custom Rules |
|---|---|
| Free | 5 |
| Pro | 20 |
| Business | 100 |
| Enterprise | Unlimited |
- Verify the token hasn't expired
- Confirm it has Zone: Firewall Services: Edit permission
- Test manually:
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
- Double-check the Zone ID in the Cloudflare dashboard
- Ensure the token has access to that zone
- List accessible zones:
curl -X GET "https://api.cloudflare.com/client/v4/zones" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {name, id}'
- Check Security → WAF → Custom rules in the Cloudflare dashboard
- Run
doorman sync --provider cloudflare --debugfor detailed output - Look for translation warnings — complex conditions may have been simplified
Doorman has built-in retry logic, but if you hit persistent rate limits:
- Avoid running multiple sync operations simultaneously
- Wait 60 seconds and retry
- Ensure IPs use CIDR notation (
192.168.1.1/32not192.168.1.1) - Provide an Account ID to enable the more efficient Lists API
- Check rule priority in the Cloudflare dashboard
- Never commit API tokens — use environment variables or secret management
- Use minimum permissions — only grant what Doorman needs
- Set token expiration — rotate tokens regularly
- Test in staging first — create rules disabled, enable after testing
- Create backups before major changes
- Monitor Cloudflare Analytics (Security → Events) for rule effectiveness
- Getting Started — General Doorman setup
- Configuration — Configuration file reference
- Vercel Setup — Setting up the Vercel provider
- Cloudflare Migration — Migrating from Vercel to Cloudflare
- Commands Overview — Full CLI reference
Getting Started
Configuration
Commands
Guides