Deployment
Docker (single node)
docker run -d \
--name dakera \
--restart unless-stopped \
-p 3300:3300 \
-e DAKERA_PORT=3300 \
-e DAKERA_ROOT_API_KEY=your-secret \
-e DAKERA_STORAGE=filesystem \
-e DAKERA_STORAGE_PATH=/data \
-v dakera-data:/data \
ghcr.io/dakera-ai/dakera:latest
Docker Compose (recommended)
The recommended way to run Dakera in production. This compose file includes Dakera, MinIO for S3 storage, and optional Dashboard UI and monitoring.
# docker-compose.yml
version: "3.8"
services:
dakera:
image: ghcr.io/dakera-ai/dakera:latest
restart: unless-stopped
ports:
- "3300:3300"
environment:
DAKERA_PORT: 3300
DAKERA_ROOT_API_KEY: ${DAKERA_ROOT_API_KEY}
DAKERA_STORAGE: s3
DAKERA_S3_ENDPOINT: http://minio:9000
DAKERA_S3_BUCKET: dakera
AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER}
AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD}
DAKERA_ENCRYPTION_KEY: ${DAKERA_ENCRYPTION_KEY}
DAKERA_AUDIT_ENABLED: "true"
RUST_LOG: info
volumes:
- dakera-data:/data
depends_on:
minio:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:3300/health"]
interval: 30s
timeout: 5s
retries: 3
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- minio-data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 10s
timeout: 5s
retries: 5
volumes:
dakera-data:
minio-data:
# Generate secrets and start
printf "DAKERA_ROOT_API_KEY=%s\nDAKERA_ENCRYPTION_KEY=%s\nMINIO_ROOT_USER=minioadmin\nMINIO_ROOT_PASSWORD=%s\n" \
"$(openssl rand -hex 32)" "$(openssl rand -hex 32)" "$(openssl rand -hex 16)" > .env
docker compose up -d
Kubernetes
helm install dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera \
--namespace dakera --create-namespace \
--set dakera.rootApiKey="$(openssl rand -hex 32)" \
--set minio.rootPassword="$(openssl rand -hex 16)"
Full values: charts/dakera/values.yaml · ArtifactHub. Kustomize manifests available in dakera-deploy/k8s/.
Reverse proxy & TLS termination
Nginx
# /etc/nginx/sites-available/dakera
server {
listen 443 ssl http2;
server_name dakera.example.com;
ssl_certificate /etc/letsencrypt/live/dakera.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dakera.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:3300;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSE support (required for event streaming)
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
}
}
# Redirect HTTP → HTTPS
server {
listen 80;
server_name dakera.example.com;
return 301 https://$host$request_uri;
}
# Obtain certificate with certbot
sudo certbot --nginx -d dakera.example.com
Caddy
# Caddyfile — automatic HTTPS with Let's Encrypt
dakera.example.com {
reverse_proxy localhost:3300 {
flush_interval -1 # required for SSE streaming
}
}
Caddy automatically provisions and renews TLS certificates via Let's Encrypt — no additional setup required.
Self-hosted VPS
Run Dakera directly on a VPS (Ubuntu/Debian) with systemd for process management. Avoids Docker overhead — ideal for single-node deployments with dedicated hardware.
# /etc/systemd/system/dakera.service
[Unit]
Description=Dakera Agent Memory Engine
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=dakera
Group=dakera
WorkingDirectory=/opt/dakera
ExecStart=/opt/dakera/dakera
Restart=always
RestartSec=5
LimitNOFILE=65535
# Environment
EnvironmentFile=/opt/dakera/.env
[Install]
WantedBy=multi-user.target
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable dakera
sudo systemctl start dakera
# Check status
sudo systemctl status dakera
curl http://localhost:3300/health
Cloud deployment
| Platform | Service | Quick start |
|---|---|---|
| AWS | ECS Fargate | Task definition with ghcr.io/dakera-ai/dakera:latest, EFS volume for /data, ALB for TLS |
| GCP | Cloud Run | gcloud run deploy dakera --image ghcr.io/dakera-ai/dakera:latest --port 3300 |
| Azure | Container Instances | az container create --image ghcr.io/dakera-ai/dakera:latest --ports 3300 |
| Fly.io | fly launch | fly launch --image ghcr.io/dakera-ai/dakera:latest with persistent volume |
| Railway | Template | One-click deploy from GHCR image |
Resource sizing guide
| Workload | Memories | CPU | RAM | Disk | Disk IOPS |
|---|---|---|---|---|---|
| Starter | <100K | 1 vCPU | 1 GB | 10 GB SSD | 500+ |
| Medium | <1M | 2 vCPU | 4 GB | 50 GB SSD | 1,000+ |
| Large | <10M | 4 vCPU | 8 GB | 200 GB NVMe | 3,000+ |
| Enterprise | 10M+ | 8+ vCPU | 16+ GB | 500+ GB NVMe | 5,000+ |
RocksDB benefits from high random-read IOPS. Use NVMe SSDs for workloads above 1M memories. RAM should comfortably hold the L1 hot cache — configure DAKERA_L1_CACHE_SIZE based on your active memory working set.
Health checks
Dakera exposes a /health endpoint that returns the server status, version, and storage backend. Use this for container orchestration probes.
# Response format
curl http://localhost:3300/health
# {"service":"dakera","status":"healthy","version":"0.11.56","storage":"s3"}
Docker
# In Dockerfile or docker-compose.yml
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:3300/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
Kubernetes
# In pod spec
livenessProbe:
httpGet:
path: /health
port: 3300
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe:
httpGet:
path: /health
port: 3300
initialDelaySeconds: 5
periodSeconds: 10
Backup & restore
Dakera provides full backup and restore via the admin API. Backups are compressed bundles containing all memories, namespaces, keys, and vector indexes.
# Create a backup
curl -X POST http://localhost:3300/admin/backups \
-H "Authorization: Bearer $DAKERA_ROOT_API_KEY"
# {"id":"bk_20260515_143022","status":"completed","size_bytes":4521984}
# List backups
curl http://localhost:3300/admin/backups \
-H "Authorization: Bearer $DAKERA_ROOT_API_KEY"
# Download a backup
curl -o backup.tar.zst \
http://localhost:3300/admin/backups/bk_20260515_143022/download \
-H "Authorization: Bearer $DAKERA_ROOT_API_KEY"
# Restore from backup
curl -X POST http://localhost:3300/admin/backups/restore \
-H "Authorization: Bearer $DAKERA_ROOT_API_KEY" \
-F "[email protected]"
Scheduled backups
# Configure automatic daily backups with 30-day retention
curl -X PUT http://localhost:3300/admin/backups/schedule \
-H "Authorization: Bearer $DAKERA_ROOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cron":"0 2 * * *","retention_days":30,"compression":"zstd"}'
Monitoring & observability
Dakera exposes Prometheus-compatible metrics at /metrics. Key metrics to monitor:
| Metric | Type | Description |
|---|---|---|
dakera_memory_count | Gauge | Total stored memories across all namespaces |
dakera_recall_latency_seconds | Histogram | Recall response time (p50, p95, p99) |
dakera_store_latency_seconds | Histogram | Store response time |
dakera_vector_search_seconds | Histogram | ANN search duration |
dakera_decay_cycle_seconds | Histogram | Decay engine cycle duration |
dakera_autopilot_dedup_count | Counter | Memories deduplicated by AutoPilot |
dakera_http_requests_total | Counter | Total HTTP requests by method and status |
Prometheus scrape config
# prometheus.yml
scrape_configs:
- job_name: dakera
scrape_interval: 15s
static_configs:
- targets: ["dakera:3300"]
metrics_path: /metrics
Alert recommendations
| Alert | Condition | Severity |
|---|---|---|
| High recall latency | dakera_recall_latency_seconds{quantile="0.99"} > 2 | Warning |
| Health check failing | up{job="dakera"} == 0 | Critical |
| Disk usage high | dakera_storage_bytes / dakera_storage_capacity > 0.85 | Warning |
| Rate limit exhausted | rate(dakera_rate_limited_total[5m]) > 10 | Warning |
OpenTelemetry tracing
# Enable OTLP trace export
DAKERA_TRACING_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317
OTEL_SERVICE_NAME=dakera
Log management
Dakera uses structured logging via RUST_LOG. In production, set info level. Logs are emitted as structured JSON when a JSON subscriber is configured.
# Log levels
RUST_LOG=info # production (recommended)
RUST_LOG=debug # development / troubleshooting
RUST_LOG=info,tower_http=debug # verbose HTTP logging only
Logrotate
# /etc/logrotate.d/dakera
/var/log/dakera/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
postrotate
systemctl reload dakera 2>/dev/null || true
endscript
}
Upgrading
Dakera supports zero-downtime upgrades. Data is backward-compatible across minor versions. For Docker deployments:
# 1. Pull the latest image
docker pull ghcr.io/dakera-ai/dakera:latest
# 2. Restart the container
docker compose down && docker compose up -d
# 3. Verify health and version
curl http://localhost:3300/health
# {"service":"dakera","status":"healthy","version":"0.11.56"}
For systemd deployments: replace the binary at /opt/dakera/dakera, then sudo systemctl restart dakera. Always verify the health endpoint after upgrade.
Production checklist
| Item | Priority | Notes |
|---|---|---|
Set DAKERA_ROOT_API_KEY | Required | Use a cryptographically random 32+ char secret |
| TLS via reverse proxy | Required | Nginx or Caddy in front — never expose port 3300 directly |
| Persistent volume | Required | SSD-backed storage for DAKERA_STORAGE_PATH |
| S3 storage backend | Required | MinIO or AWS S3 for durability and cold tier |
| Encryption at rest | Recommended | Set DAKERA_ENCRYPTION_KEY for AES-256-GCM |
Scrape /metrics | Recommended | Prometheus with alert rules for latency and health |
| Audit logging | Recommended | Enable DAKERA_AUDIT_ENABLED=true |
| Health check probes | Recommended | Docker HEALTHCHECK or K8s liveness/readiness probes |
| Scheduled backups | Recommended | Daily with 30-day retention via admin API |
| Set resource limits | Recommended | CPU/RAM limits per sizing guide above |
| Enable ML classifier | Recommended | DAKERA_ML_CLASSIFIER=true for improved recall |
Set RUST_LOG=info | Recommended | Avoid debug in production — verbose and slow |
Environment variable reference
Complete reference of all configuration options, grouped by category.
Core
| Variable | Default | Description |
|---|---|---|
DAKERA_HOST | 0.0.0.0 | Server bind address |
DAKERA_PORT | 3300 | REST API port |
DAKERA_ROOT_API_KEY | — | Root authentication key (required) |
DAKERA_GRPC_ENABLED | true | Enable gRPC API |
DAKERA_GRPC_PORT | 50051 | gRPC server port |
DAKERA_REQUEST_TIMEOUT | 30 | Request timeout in seconds (0 = disabled) |
DAKERA_MAX_BODY_SIZE | 10485760 | Max request body size in bytes (10 MB) |
DAKERA_EVENT_BUS_CAPACITY | 256 | SSE broadcast channel capacity |
RUST_LOG | info | Log level filter |
Storage
| Variable | Default | Description |
|---|---|---|
DAKERA_STORAGE | memory | Backend: memory, filesystem, or s3 |
DAKERA_STORAGE_PATH | ./data | Filesystem storage path |
DAKERA_S3_BUCKET | — | S3 bucket name (required for S3 backend) |
DAKERA_S3_REGION | — | S3 region |
DAKERA_S3_ENDPOINT | — | S3/MinIO endpoint URL |
DAKERA_TIERED_STORAGE | false | Enable hot → warm → cold tiering |
DAKERA_L1_CACHE_SIZE | 100000 | L1 hot cache capacity (vector count) |
DAKERA_HOT_TO_WARM_SECS | 3600 | Age threshold for hot → warm demotion |
DAKERA_WARM_TO_COLD_SECS | 86400 | Age threshold for warm → cold demotion |
DAKERA_CACHE_DIR | /data/cache/warm | Warm tier local disk path |
Security
| Variable | Default | Description |
|---|---|---|
DAKERA_ENCRYPTION_KEY | — | AES-256-GCM key (64 hex chars or passphrase ≥8 chars) |
DAKERA_CORS_ORIGINS | * | Comma-separated allowed origins |
DAKERA_CORS_CREDENTIALS | false | Allow credentials in CORS |
DAKERA_CSP_ENABLED | true | Enable Content Security Policy |
DAKERA_CSP_DIRECTIVES | default-src 'none' | CSP directive string |
DAKERA_HSTS_ENABLED | true | Enable HSTS header |
DAKERA_HSTS_MAX_AGE | 31536000 | HSTS max-age (1 year) |
DAKERA_FRAME_OPTIONS | DENY | X-Frame-Options value |
RATE_LIMIT_RPS | 100 | Rate limit: requests per second |
RATE_LIMIT_BURST | 50 | Rate limit: burst capacity |
Audit & tracing
| Variable | Default | Description |
|---|---|---|
DAKERA_AUDIT_ENABLED | true | Enable audit logging |
DAKERA_AUDIT_REQUEST_BODY | false | Log request bodies |
DAKERA_AUDIT_RESPONSE_BODY | false | Log response bodies |
DAKERA_AUDIT_MAX_BODY_SIZE | 4096 | Max body size to log (bytes) |
DAKERA_AUDIT_EXCLUDE_PATHS | /health,/metrics | Paths excluded from audit |
DAKERA_TRACING_ENABLED | false | Enable OpenTelemetry OTLP export |
OTEL_EXPORTER_OTLP_ENDPOINT | http://localhost:4317 | OTLP exporter endpoint |
OTEL_SERVICE_NAME | dakera | Service name for traces |
Clustering
| Variable | Default | Description |
|---|---|---|
DAKERA_CLUSTER_MODE | false | Enable multi-node cluster |
DAKERA_NODE_ID | auto | Unique node identifier |
DAKERA_CLUSTER_SEEDS | — | Comma-separated seed addresses |
DAKERA_GOSSIP_PORT | 7946 | SWIM gossip port |
DAKERA_GOSSIP_BIND | 0.0.0.0:7946 | Gossip bind address |
DAKERA_REDIS_URL | — | Redis URL for distributed cache |
Inference & retrieval
| Variable | Default | Description |
|---|---|---|
DAKERA_ML_CLASSIFIER | false | Enable ML query classifier |
DAKERA_TEMPORAL_BOOST | — | Temporal scoring boost factor |
DAKERA_TEMPORAL_WINDOW_DAYS | — | Temporal window for recency scoring |
DAKERA_RRF_K | 60 | Reciprocal Rank Fusion k parameter |
DAKERA_ANN_THRESHOLD | — | ANN search threshold |
DAKERA_HNSW_CACHE_MAX | — | HNSW index cache max entries |
AutoPilot & decay
| Variable | Default | Description |
|---|---|---|
DAKERA_AUTOPILOT_ENABLED | true | Enable AutoPilot background tasks |
DAKERA_AUTOPILOT_DEDUP_INTERVAL_HOURS | 1 | Deduplication cycle interval |
DAKERA_AUTOPILOT_CONSOLIDATION_INTERVAL_HOURS | 6 | Consolidation cycle interval |
DAKERA_AUTOPILOT_DEDUP_THRESHOLD | 0.93 | Cosine similarity threshold for dedup |
DAKERA_DECAY_STRATEGY | exponential | Decay strategy: exponential, linear, step |
DAKERA_DECAY_HALF_LIFE_HOURS | — | Half-life for exponential decay |
DAKERA_DECAY_INTERVAL_SECS | — | Decay engine cycle interval |
DAKERA_DECAY_MIN_IMPORTANCE | — | Minimum importance before memory is forgotten |