background image of night city

Vercel Doorman 2.0: Cloudflare WAF Support and a New Config Format

May 09, 2026 · 3 min read

Doorman started as a way to stop copy-pasting firewall rules into the Vercel dashboard. Two versions later, it manages Cloudflare WAF too.

I kept running into the same problem when projects grew beyond a single Vercel deployment: some traffic goes through Cloudflare, some doesn’t, and the firewall rules that protected one weren’t automatically protecting the other. Keeping those two configs in sync by hand was the kind of thing that breaks at 2am. So I built Doorman to treat firewall rules the same way we treat everything else – as code, in version control, deployed through CI.

If you’re new here, the original post covers why I built it and how v1 worked. This post is about what’s new in 2.0.

Version 1.x handled Vercel Firewall well. With 2.0, Cloudflare WAF is a first-class provider. One config file, one CLI, two providers.

What Changed

Cloudflare WAF Support

Every command that worked against Vercel now works against Cloudflare with a --provider cloudflare flag. Full CRUD for Cloudflare Rulesets and Rules, Lists API integration for bulk IP blocking, and provider-aware validation and health scoring throughout.

# Target Cloudflare with any command
vercel-doorman sync --provider cloudflare
vercel-doorman list --provider cloudflare
vercel-doorman status --provider cloudflare

There’s also automatic rule translation between Vercel and Cloudflare formats. The translation engine uses an expression builder for Cloudflare’s wirefilter syntax, maps field names between providers, and surfaces warnings when a conversion is lossy (regex rules on non-Enterprise Cloudflare plans, for example).

.doorman.json Config Format

The default config filename is now .doorman.json – shorter, provider-agnostic, and matches the project name. Existing vercel-firewall.config.json files are still auto-detected and work unchanged, so there’s nothing to migrate if you’re already using v1.

{
  "$schema": "https://doorman.griffen.codes/schema.json",
  "provider": "cloudflare",
  "providers": {
    "cloudflare": {
      "zoneId": "your_zone_id",
      "accountId": "your_account_id"
    }
  },
  "rules": [],
  "ips": []
}

Provider Abstraction Layer

Underneath the CLI, a unified IFirewallProvider interface means the same command surface works identically across providers. Provider detection follows a clear priority: --provider flag, then the provider field in config, then provider-specific config keys, then environment variables (DOORMAN_PROVIDER, CLOUDFLARE_ZONE_ID, VERCEL_PROJECT_ID), and finally Vercel as the default.

Structured Error Handling

Every error now includes a code, an actionable suggestion, and a documentation link. I got tired of cryptic API failures that didn’t tell you which credential was wrong or where to fix it.

[PROV_5000] Authentication failed for cloudflare

Suggestion: Verify your CLOUDFLARE_API_TOKEN is valid and not expired.
            Create a new token at dash.cloudflare.com/profile/api-tokens

Documentation: https://doorman.griffen.codes/docs/cloudflare-setup

Performance and Reliability

A few things that quietly make the CLI more resilient: API response caching with TTL-based invalidation, request deduplication for concurrent operations, exponential backoff with jitter on retries, batch processing for large rule sets, and graceful shutdown that preserves progress mid-run.


By the Numbers

The test coverage jump was intentional. Multi-provider code has a lot of surface area and I wanted to be confident the abstraction layer held before shipping.

Metricv1.5v2.0
Providers1 (Vercel)2 (Vercel + Cloudflare)
Test suites2655
Tests passing4101,132
New source files47
Lines of new code~3,600
TypeScript errors00

Upgrading from v1

Nothing breaks. Provider defaults to Vercel when not specified, existing config files are auto-detected, and all the same commands work the same way.

npm install -g vercel-doorman@latest

To start managing Cloudflare from the same config:

export CLOUDFLARE_API_TOKEN="..."
export CLOUDFLARE_ZONE_ID="..."
vercel-doorman init --provider cloudflare --interactive

What’s Next

If you’re already using Doorman and run into anything weird with the Cloudflare integration, open an issue or find me on Discord. And if you’ve been waiting for the Cloudflare support to give it a try, now’s a good time.


Griffen Fargo headshot

Griffen Fargo

Published

Share
Keep Reading

Discussion

Have thoughts? Drop them in.

Comments are powered by Disqus. Sign in once, comment anywhere.

Loading comments…
Fin.

griffen.codes

made with 💖 and

© 2026all rights reservedupdated 44 seconds ago