System Components
Core Components
Reverse Proxy
Location:lib/anubis.go:Server
The main HTTP handler that intercepts all requests:
- Cookie validation and JWT parsing
- Request routing to policy engine
- Static asset serving (JS/CSS for challenges)
- OpenGraph tag caching
- Proxying validated requests to upstream
ServeHTTP(): Main request handlermaybeReverseProxy(): Core request flow logiccheck(): Policy evaluation orchestration
Policy Engine
Location:lib/policy/
Evaluates incoming requests against configured rules:
RemoteAddrChecker
CIDR-based IP matching using
gaissmai/bart prefix tables.Location: lib/policy/checker.go:20HeaderMatchesChecker
Regex matching against HTTP headers.Location:
lib/policy/checker.go:66PathChecker
Regex matching against request paths.Location:
lib/policy/checker.go:96CELChecker
Common Expression Language for complex conditions.Location:
lib/policy/celchecker.go- Load and parse YAML policy configuration
- Compile regex patterns and CEL expressions
- Build checker chain for each bot rule
- Evaluate rules sequentially on each request
- Return
CheckResultwith action and weight
Challenge Engine
Location:lib/challenge/
Pluggable challenge system with multiple implementations:
| Algorithm | File | Description |
|---|---|---|
fast | lib/challenge/proofofwork/ | SHA256-based proof-of-work |
slow | lib/challenge/proofofwork/ | Deprecated alias for fast |
metarefresh | lib/challenge/metarefresh/ | HTML meta refresh redirect |
preact | lib/challenge/preact/ | Interactive Preact component |
issueChallenge(): Generate UUID, random data, store metadataIssue(): Render challenge page with embedded solver- Client solves challenge and submits solution
Validate(): Verify solution, mark as spentsignJWT(): Generate authentication token
Storage Backends
Location:lib/store/
Unified interface for data persistence:
Memory (memory)
Memory (memory)
Location:
lib/store/memory/In-memory map with TTL support using decaymap.Pros: Zero dependencies, instant accessCons: Not persistent, single-instance onlyUse case: Development, testing, single-server deploymentsBBolt (bbolt)
BBolt (bbolt)
Location:
lib/store/bbolt/Embedded key-value database.Pros: Persistent, ACID transactions, no networkCons: File locking (single process), slower than memoryUse case: Single-instance production with persistenceValkey/Redis (valkey)
Valkey/Redis (valkey)
Location:
lib/store/valkey/Network-based key-value store.Pros: Shared state across instances, high performance, native TTLCons: External dependency, network latencyUse case: Multi-instance production deploymentsS3 API (s3api)
S3 API (s3api)
Location:
lib/store/s3api/S3-compatible object storage.Pros: Unlimited capacity, durable, shared stateCons: High latency, not optimized for small objectsUse case: Very high-volume or compliance-driven deployments| Key Pattern | Type | TTL | Purpose |
|---|---|---|---|
challenge:<uuid> | challenge.Challenge | 30m | Challenge metadata and spent status |
dronebl:<ip> | dnsbl.DroneBLResponse | 24h | DNSBL lookup results |
ogtags:allow:<host><path> | bool | Variable | OpenGraph tag asset allowlist |
dns:forward:<ip> | []string | Configurable | Forward DNS cache |
dns:reverse:<hostname> | []string | Configurable | Reverse DNS cache |
JWT Validator
Location:lib/anubis.go:getTokenKeyfunc()
Supports two signing algorithms:
- Signature integrity
- Expiration time (
exp) - Not-before time (
nbf) - Policy rule hash match (detects config changes)
- Optional restriction header binding
Thoth Integration
Location:lib/thoth/
Optional gRPC service for enriched IP intelligence:
- ASN lookup and matching
- GeoIP country detection
- IP reputation data
- Cached responses (configurable TTL)
Thoth is optional. ASN/GeoIP rules are skipped (with warnings) if Thoth is not configured.
Deployment Patterns
Single Instance
Configuration:Multi-Instance (Shared State)
Configuration:Kubernetes Deployment
Nginx Integration
Nginx as TLS terminator:Caddy Integration
Request Headers
Anubis requires from upstream proxy:| Header | Required | Purpose |
|---|---|---|
X-Real-Ip | Yes | Client IP for policy evaluation |
X-Forwarded-For | Recommended | IP chain for logging |
X-Forwarded-Proto | For redirects | Protocol for redirect URLs |
X-Forwarded-Host | For redirects | Host for redirect URLs |
X-Forwarded-Uri | For redirects | Original URI for redirects |
| Header | Value | Purpose |
|---|---|---|
X-Anubis-Rule | bot/rule-name | Which rule matched |
X-Anubis-Action | ALLOW/CHALLENGE/etc | What action was taken |
X-Anubis-Status | PASS | Challenge validation status |
Performance Characteristics
Latency Impact
Cold path (no cookie):- Policy evaluation: ~1-5ms
- Challenge rendering: ~10-50ms
- Total: 11-55ms overhead
- JWT validation: ~0.5-2ms
- Total: less than 2ms overhead
- Difficulty 3: ~500ms client-side
- Difficulty 5: ~60s client-side
Memory Usage
Baseline:- Anubis process: ~50-100 MB
- Per challenge (memory store): ~2 KB
- Per JWT: 0 bytes (stateless)
- Memory store: ~120 MB total
- BBolt: ~30 MB on disk
- Valkey: Negligible (external)
Throughput
Benchmark results (Intel i7, 8 cores):| Scenario | Requests/sec | Latency p50 | Latency p99 |
|---|---|---|---|
| Valid JWT (proxy) | 25,000 | 1.2ms | 4.5ms |
| Policy eval (ALLOW) | 18,000 | 2.1ms | 8.2ms |
| Challenge render | 5,000 | 12ms | 35ms |
Monitoring and Observability
Prometheus Metrics
Anubis exposes metrics at/.within.website/metrics:
Structured Logging
Anubis useslog/slog for structured logging:
DEBUG: Policy evaluation details, JWT validationINFO: Challenge issuance, successful validationsWARN: Configuration warnings, deprecated featuresERROR: Validation failures, store errors
Health Checks
Anubis doesn’t expose a dedicated health endpoint, but you can:- Check metrics endpoint:
GET /.within.website/metrics - Use upstream health (after ALLOW rule)
- Monitor store connectivity
Security Considerations
Constant-Time Operations
Constant-Time Operations
JWT signature validation and challenge hash comparison use
crypto/subtle.ConstantTimeCompare to prevent timing attacks.Cookie Security
Cookie Security
Double-Spend Prevention
Double-Spend Prevention
Challenges marked as
Spent=true after first successful validation. Store atomicity prevents reuse.Policy Invalidation
Policy Invalidation
JWT contains policy rule hash. Config changes automatically invalidate all existing tokens.
XSS Protection
XSS Protection
Redirect URL validation prevents
javascript:, data:, and other dangerous schemes.Troubleshooting
X-Real-Ip not set
Error:
[misconfiguration] X-Real-Ip header is not setFix: Configure your reverse proxy to set this header from client IP.Policy doesn't match
Issue: Requests not triggering expected rulesDebug: Enable
ANUBIS_LOG_LEVEL=debug and check check_result logs.Cookies not persisting
Issue: Challenges loop indefinitelyCauses:
- Cookie domain mismatch
- Third-party cookie blocking
SameSite=NonewithoutSecure
Store connectivity
Issue:
can't fetch challenge errorsCheck: Store backend health, network connectivity, credentials.Next Steps
Configuration Guide
Learn about all configuration options and environment variables
Deployment Guide
Production deployment best practices and examples