Documentation Index
Fetch the complete documentation index at: https://mintlify.com/TecharoHq/Anubis/llms.txt
Use this file to discover all available pages before exploring further.
Anubis requires persistent storage for tracking challenges, cookies, and DNS cache. Choose a storage backend based on your deployment architecture.
Available Backends
| Backend | Persistence | Multi-Instance | Use Case |
|---|
memory | No | No | Development/testing |
bbolt | Yes | No | Single-instance production |
valkey | Yes | Yes | Multi-instance deployments |
s3api | Yes | Yes | Cloud/serverless |
Memory Backend
In-memory hashmap storage. Data is lost on restart.
Configuration
store:
backend: memory
parameters: {}
This is the default if no store is configured.
When to Use
β
Use for:
- Local development
- Testing
- Single-instance with low traffic
- Ephemeral environments
π« Donβt use for:
- Production with high traffic
- Multi-instance deployments
- When you need persistence across restarts
Limitations
- No size limits (memory grows unbounded)
- Data lost on process restart
- Cannot share state between instances
BoltDB Backend
Embedded key-value database using bbolt. Data persists to disk.
Configuration
store:
backend: bbolt
parameters:
path: /data/anubis.bdb
| Parameter | Type | Required | Description |
|---|
path | string | Yes | Filesystem path to database file |
When to Use
β
Use for:
- Single-instance production deployments
- High-traffic single-instance setups
- When persistent storage is required
- VPS/dedicated server deployments
π« Donβt use for:
- Multi-instance deployments (Kubernetes, etc.)
- Environments without persistent filesystem
- Multiple Anubis instances sharing a backend
File System Requirements
Anubis requires:
- Write access to the directory containing the database file
- Exclusive lock on the database file (one process only)
# Create directory
mkdir -p /var/lib/anubis
# Set permissions
chown anubis:anubis /var/lib/anubis
chmod 750 /var/lib/anubis
Configuration:
store:
backend: bbolt
parameters:
path: /var/lib/anubis/anubis.bdb
Cleanup
BoltDB runs hourly cleanup to remove expired entries. No manual maintenance required.
Docker Example
services:
anubis:
image: ghcr.io/techarohq/anubis:latest
volumes:
- anubis-data:/data
- ./policy.yaml:/etc/anubis/policy.yaml:ro
environment:
- POLICY_FNAME=/etc/anubis/policy.yaml
volumes:
anubis-data:
Policy file:
store:
backend: bbolt
parameters:
path: /data/anubis.bdb
Valkey/Redis Backend
Remote key-value store using Valkey or Redis compatible servers.
Configuration
Standalone
store:
backend: valkey
parameters:
url: redis://valkey.example.com:6379/0
Cluster
store:
backend: valkey
parameters:
url: redis://valkey.example.com:6379/0
cluster: true
Sentinel (High Availability)
store:
backend: valkey
parameters:
sentinel:
masterName: mymaster
addr:
- sentinel1.example.com:26379
- sentinel2.example.com:26379
- sentinel3.example.com:26379
username: anubis
password: ${VALKEY_PASSWORD}
clientName: anubis-prod
Parameters
| Parameter | Type | Required | Description |
|---|
url | string | Yes* | Redis connection URL |
cluster | bool | No | Enable cluster mode |
sentinel | object | No | Sentinel configuration (see below) |
*Either url or sentinel must be provided.
Sentinel Parameters
| Parameter | Type | Required | Description |
|---|
masterName | string | Yes | Sentinel master name |
addr | string or list | Yes | Sentinel server addresses |
username | string | No | Auth username |
password | string | No | Auth password |
clientName | string | No | Client identifier |
When to Use
β
Use for:
- Multi-instance deployments
- Kubernetes/Docker Swarm
- High-availability requirements
- Shared state across instances
π« Donβt use for:
- Single-instance deployments (use bbolt instead)
- If you donβt already have Redis/Valkey
- Low-traffic sites (overhead not justified)
redis://[username:password@]host[:port][/database]
Examples:
# Basic
url: redis://localhost:6379/0
# With auth
url: redis://user:pass@valkey.internal:6379/0
# TLS (rediss://)
url: rediss://valkey.internal:6380/0
Kubernetes Example
apiVersion: v1
kind: ConfigMap
metadata:
name: anubis-policy
data:
policy.yaml: |
store:
backend: valkey
parameters:
url: redis://valkey-service:6379/0
bots:
- name: browsers
user_agent_regex: Mozilla
action: CHALLENGE
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: anubis
spec:
replicas: 3 # Multiple instances share Valkey
template:
spec:
containers:
- name: anubis
image: ghcr.io/techarohq/anubis:latest
env:
- name: POLICY_FNAME
value: /etc/anubis/policy.yaml
volumeMounts:
- name: policy
mountPath: /etc/anubis
volumes:
- name: policy
configMap:
name: anubis-policy
S3 API Backend
Object storage backend using S3-compatible APIs.
Configuration
store:
backend: s3api
parameters:
bucketName: anubis-production
pathStyle: false
Environment Variables
S3 credentials are read from environment:
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1
AWS_ENDPOINT_URL_S3=https://s3.amazonaws.com # Optional
Parameters
| Parameter | Type | Required | Description |
|---|
bucketName | string | Yes | S3 bucket name |
pathStyle | bool | No | Use path-style URLs (default: false) |
When to Use
β
Use for:
- Serverless deployments (AWS Lambda, Cloud Run)
- Multi-instance without managing Redis
- Cloud-native deployments
- When object storage is already available
π« Donβt use for:
- High-frequency traffic (S3 API calls are expensive)
- Latency-sensitive applications
- If you can use Redis/Valkey instead
Supported Providers
- AWS S3
- Cloudflare R2
- Minio
- Tigris
- Backblaze B2
- DigitalOcean Spaces
- Any S3-compatible service
Lifecycle Policy
Configure bucket lifecycle to auto-delete old objects:
{
"Rules": [
{
"Status": "Enabled",
"Expiration": {
"Days": 7
}
}
]
}
Anubis stores expiry metadata but doesnβt auto-cleanup. Lifecycle policies prevent unbounded growth.
Example: Cloudflare R2
# Environment
AWS_ACCESS_KEY_ID=<r2-access-key>
AWS_SECRET_ACCESS_KEY=<r2-secret>
AWS_ENDPOINT_URL_S3=https://<account-id>.r2.cloudflarestorage.com
store:
backend: s3api
parameters:
bucketName: anubis-data
pathStyle: false
Storage Interface
All backends implement the same interface:
type Interface interface {
Get(ctx context.Context, key string) ([]byte, error)
Set(ctx context.Context, key string, value []byte, expiry time.Duration) error
Delete(ctx context.Context, key string) error
IsPersistent() bool
}
Choosing a Backend
Decision Tree
Are you running multiple Anubis instances?
ββ Yes β Use valkey or s3api
β ββ Already have Redis/Valkey? β Use valkey
β ββ Using serverless/cloud? β Use s3api
ββ No β Single instance
ββ Production? β Use bbolt
ββ Development? β Use memory
Comparison
| Feature | memory | bbolt | valkey | s3api |
|---|
| Persistence | β | β
| β
| β
|
| Multi-instance | β | β | β
| β
|
| Setup complexity | None | Low | Medium | Medium |
| Performance | Fastest | Fast | Fast | Slower |
| Operational overhead | None | Low | Medium | Low |
| Cost | Free | Free | $-$$ | $$-$$$ |
Key Generation Warning
When using persistent storage (bbolt, valkey, s3api), always configure a signing key to prevent challenge invalidation on restart:
# Generate Ed25519 key
openssl rand -hex 32 > /etc/anubis/ed25519.key
# Use it
anubis --ed25519-private-key-hex-file /etc/anubis/ed25519.key
See Security for details.
Validation Errors
store:
backend: bbolt
parameters: {} # Error: ErrMissingPath
Fix: Provide path:
store:
backend: bbolt
parameters:
path: /data/anubis.bdb
store:
backend: valkey
parameters: {} # Error: ErrNoURL
Fix: Provide URL:
store:
backend: valkey
parameters:
url: redis://localhost:6379/0
store:
backend: s3api
parameters: {} # Error: ErrNoBucketName
Fix: Provide bucket:
store:
backend: s3api
parameters:
bucketName: anubis-data
Next Steps