-
Notifications
You must be signed in to change notification settings - Fork 1
Configuration
Griffen Fargo edited this page Aug 17, 2026
·
6 revisions
Doorman uses a JSON configuration file to define your firewall rules. The configuration is validated using JSON Schema and provides full TypeScript support.
Add the schema reference to your config file for editor autocompletion and validation:
{
"$schema": "https://doorman.griffen.codes/schema.json"
}{
"$schema": "https://doorman.griffen.codes/schema.json",
"projectId": "prj_abc123",
"teamId": "team_xyz789",
"rules": [],
"ips": []
}{
"$schema": "https://doorman.griffen.codes/schema.json",
"provider": "cloudflare",
"providers": {
"cloudflare": {
"zoneId": "zone_abc123",
"accountId": "acc_xyz789"
}
},
"rules": [],
"ips": []
}{
"$schema": "https://doorman.griffen.codes/schema.json",
"provider": "cloudflare",
"providers": {
"vercel": {
"projectId": "prj_abc123",
"teamId": "team_xyz789"
},
"cloudflare": {
"zoneId": "zone_abc123",
"accountId": "acc_xyz789"
}
},
"rules": [],
"ips": []
}| Property | Type | Required | Description |
|---|---|---|---|
$schema |
string | No | JSON Schema URL for validation |
provider |
string | No | Default provider ("vercel" or "cloudflare") |
projectId |
string | Vercel Only | Vercel project ID |
teamId |
string | Vercel Only | Vercel team ID (optional) |
providers |
object | Multi-Provider | Provider-specific configurations |
rules |
array | Yes | Array of firewall rules |
ips |
array | No | Array of IP blocking rules |
version |
number | No | Configuration version |
firewallEnabled |
boolean | No | Enable/disable firewall |
{
"id": "rule_block_bots",
"name": "Block Bad Bots",
"description": "Block malicious bots and crawlers",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "user_agent",
"op": "sub",
"value": "bot",
"neg": false
}
]
}
],
"action": {
"mitigate": {
"action": "deny"
}
}
}| Property | Type | Required | Description |
|---|---|---|---|
id |
string | No | Unique rule identifier |
name |
string | Yes | Human-readable rule name |
description |
string | No | Rule description |
active |
boolean | Yes | Whether rule is enabled |
conditionGroup |
array | Yes | Array of condition groups (OR logic) |
action |
object | Yes | Action to take when rule matches |
Condition groups use OR logic between groups and AND logic within groups:
{
"conditionGroup": [
{
"conditions": [
{ "type": "path", "op": "pre", "value": "/admin" },
{ "type": "method", "op": "eq", "value": "POST" }
]
},
{
"conditions": [
{ "type": "ip_address", "op": "eq", "value": "192.168.1.1" }
]
}
]
}This translates to: (path starts with "/admin" AND method equals "POST") OR (IP equals "192.168.1.1")
| Type | Description | Vercel | Cloudflare |
|---|---|---|---|
host |
Hostname | ✅ | ✅ |
path |
URL path | ✅ | ✅ |
method |
HTTP method | ✅ | ✅ |
header |
HTTP header | ✅ | ✅ |
query |
Query parameter | ✅ | ✅ |
cookie |
Cookie value | ✅ | ✅ |
user_agent |
User agent string | ✅ | ✅ |
ip_address |
IP address | ✅ | ✅ |
geo_country |
Country code | ✅ | ✅ |
geo_continent |
Continent code | ✅ | ✅ |
geo_city |
City name | ✅ | ✅ |
protocol |
Protocol | ✅ | ✅ |
scheme |
URL scheme | ✅ | ✅ |
environment |
Deployment environment | ✅ | ❌ |
region |
Vercel region | ✅ | ❌ |
| Operator | Description | Vercel | Cloudflare |
|---|---|---|---|
eq |
Equals | ✅ | ✅ |
pre |
Starts with | ✅ | ✅ |
suf |
Ends with | ✅ | ✅ |
sub |
Contains | ✅ | ✅ |
inc |
Is any of (array) | ✅ | ✅ |
re |
Regex match | ✅ | |
ex |
Exists | ✅ | ✅ |
nex |
Does not exist | ✅ | ✅ |
| Action | Description | Vercel | Cloudflare |
|---|---|---|---|
log |
Log only | ✅ | ✅ |
deny |
Block request | ✅ | ✅ |
allow |
Allow request | ❌ (use bypass) |
✅ |
challenge |
CAPTCHA challenge | ✅ | ✅ |
bypass |
Skip other rules | ✅ | ✅ |
rate_limit |
Rate limiting | ✅ | ✅ |
redirect |
HTTP redirect | ✅ | ✅ |
{
"action": {
"mitigate": {
"action": "rate_limit",
"rateLimit": {
"requests": 100,
"window": "60s"
}
}
}
}{
"action": {
"mitigate": {
"action": "redirect",
"redirect": {
"location": "https://example.com/blocked",
"permanent": false
}
}
}
}{
"ips": [
{
"id": "ip_block_suspicious",
"ip": "192.168.1.100/32",
"hostname": "suspicious-host",
"action": "deny",
"notes": "Blocked due to suspicious activity"
}
]
}| Property | Type | Required | Description |
|---|---|---|---|
ip |
string | Yes | IP address or CIDR range |
hostname |
string | No | Hostname for documentation |
action |
string | Yes | Action (currently only "deny") |
notes |
string | No | Notes about the block |
VERCEL_TOKEN="your_vercel_token"
VERCEL_PROJECT_ID="prj_abc123"
VERCEL_TEAM_ID="team_xyz789"CLOUDFLARE_API_TOKEN="your_api_token"
CLOUDFLARE_ZONE_ID="zone_abc123"
CLOUDFLARE_ACCOUNT_ID="acc_xyz789"DOORMAN_PROVIDER="cloudflare" # or "vercel"- Use descriptive names for rules and IPs
- Add descriptions to explain rule purposes
- Group related conditions logically
- Use CIDR notation for IP ranges
- Order rules by frequency (most common first)
- Test rules in staging before production
- Start with log actions before blocking
- Keep backups of working configurations
- Getting Started — Quick setup guide
- Commands Overview — CLI command reference
- Examples — Real-world configuration examples
Getting Started
Configuration
Commands
Guides