Skip to main content
Anubis is designed as a modular reverse proxy with pluggable components for storage, policy evaluation, and external integrations.

System Components

Core Components

Reverse Proxy

Location: lib/anubis.go:Server The main HTTP handler that intercepts all requests:
Responsibilities:
  • 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
Key Methods:
  • ServeHTTP(): Main request handler
  • maybeReverseProxy(): Core request flow logic
  • check(): Policy evaluation orchestration

Policy Engine

Location: lib/policy/ Evaluates incoming requests against configured rules:
Checker Implementations:

RemoteAddrChecker

CIDR-based IP matching using gaissmai/bart prefix tables.Location: lib/policy/checker.go:20

HeaderMatchesChecker

Regex matching against HTTP headers.Location: lib/policy/checker.go:66

PathChecker

Regex matching against request paths.Location: lib/policy/checker.go:96

CELChecker

Common Expression Language for complex conditions.Location: lib/policy/celchecker.go
Flow:
  1. Load and parse YAML policy configuration
  2. Compile regex patterns and CEL expressions
  3. Build checker chain for each bot rule
  4. Evaluate rules sequentially on each request
  5. Return CheckResult with action and weight

Challenge Engine

Location: lib/challenge/ Pluggable challenge system with multiple implementations:
Registered Implementations: Challenge Lifecycle:
  1. issueChallenge(): Generate UUID, random data, store metadata
  2. Issue(): Render challenge page with embedded solver
  3. Client solves challenge and submits solution
  4. Validate(): Verify solution, mark as spent
  5. signJWT(): Generate authentication token

Storage Backends

Location: lib/store/ Unified interface for data persistence:
Implementations:
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 deployments
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 persistence
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 deployments
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
Stored Data:

JWT Validator

Location: lib/anubis.go:getTokenKeyfunc() Supports two signing algorithms:
JWT Claims:
Validation Checks:
  • 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:
Features:
  • ASN lookup and matching
  • GeoIP country detection
  • IP reputation data
  • Cached responses (configurable TTL)
Configuration:
Policy Integration:
Thoth is optional. ASN/GeoIP rules are skipped (with warnings) if Thoth is not configured.

Deployment Patterns

Single Instance

Configuration:
Pros: Simple, no external dependencies Cons: Single point of failure, limited scalability

Multi-Instance (Shared State)

Configuration:
Pros: High availability, horizontal scaling Cons: Redis as dependency, network latency

Kubernetes Deployment

Nginx Integration

Nginx as TLS terminator:
Required Headers: Anubis depends on X-Real-Ip being set. Without it, all requests will fail with misconfiguration errors.

Caddy Integration

Request Headers

Anubis requires from upstream proxy: Anubis adds to upstream requests:

Performance Characteristics

Latency Impact

Cold path (no cookie):
  • Policy evaluation: ~1-5ms
  • Challenge rendering: ~10-50ms
  • Total: 11-55ms overhead
Warm path (valid cookie):
  • JWT validation: ~0.5-2ms
  • Total: less than 2ms overhead
Challenge solving:
  • 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)
With 10,000 active challenges:
  • Memory store: ~120 MB total
  • BBolt: ~30 MB on disk
  • Valkey: Negligible (external)

Throughput

Benchmark results (Intel i7, 8 cores):
Use ANUBIS_LOG_LEVEL=warn in production to reduce logging overhead.

Monitoring and Observability

Prometheus Metrics

Anubis exposes metrics at /.within.website/metrics:

Structured Logging

Anubis uses log/slog for structured logging:
Log Levels:
  • DEBUG: Policy evaluation details, JWT validation
  • INFO: Challenge issuance, successful validations
  • WARN: Configuration warnings, deprecated features
  • ERROR: Validation failures, store errors

Health Checks

Anubis doesn’t expose a dedicated health endpoint, but you can:
  1. Check metrics endpoint: GET /.within.website/metrics
  2. Use upstream health (after ALLOW rule)
  3. Monitor store connectivity

Security Considerations

JWT signature validation and challenge hash comparison use crypto/subtle.ConstantTimeCompare to prevent timing attacks.
Challenges marked as Spent=true after first successful validation. Store atomicity prevents reuse.
JWT contains policy rule hash. Config changes automatically invalidate all existing tokens.
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=None without Secure

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