Deploy AI agent memory anywhere — Docker, Kubernetes, or Helm.
Production-ready infrastructure for the Dakera memory platform.
| Dakera server | Where | |
|---|---|---|
Latest (this branch, main) |
v0.12.1 | main: compose files, Kubernetes manifests and guides in this repo target v0.12.1 (Dashboard 0.5.0) |
| Previous | v0.11.x (last: v0.11.108) | the release/0.11 branch, kept unchanged |
On v0.11? Use the release/0.11
branch (git clone -b release/0.11 https://github.com/Dakera-AI/dakera-deploy): everything in it
keeps working as before. Its Helm counterpart is the 0.11.x chart on the
release/0.11 branch of dakera-helm.
On v0.12.0? Follow Upgrading from v0.12.0 to v0.12.1: a single node
just pulls the new image; a cluster needs DAKERA_CLUSTER_SECRET on every node and, if it ran without one,
an upgrade in one window.
Moving from v0.11? Follow Upgrading from v0.11. Going back is supported (Rolling back to v0.11).
Dakera is the agent-native memory platform — purpose-built for AI agents that need persistent, session-aware, cross-agent memory. A single self-hosted Rust binary gives you vector search, hybrid retrieval (BM25 + HNSW), knowledge graphs, session management, and built-in embeddings. No external dependencies. Your data stays on your infrastructure.
88.2% on the LoCoMo benchmark — 1,540 questions testing long-conversation memory across temporal reasoning, multi-hop retrieval, and event ordering. This is the highest score for a self-hosted memory system.
| Use Case | What Dakera Provides |
|---|---|
| Multi-agent pipelines | Shared cross-agent memory, session isolation per agent, importance-ranked recall |
| RAG with long-term context | Hybrid BM25 + vector search over agent history; knowledge graph for entity relationships |
| Code review / DevOps agents | Persistent memory of past decisions, PR patterns, and repo-specific context across runs |
| Customer support bots | Per-user session history, conversation continuity, semantic recall of past resolutions |
| Personal AI assistants | Long-term preference and context storage, temporal decay, knowledge graph connections |
| Research / data agents | Cross-session fact accumulation, importance-weighted memory, structured entity extraction |
All use cases deploy identically — the profiles below configure storage backend and scale.
No config required. Dakera runs in-memory by default — great for local testing and development.
git clone https://github.com/dakera-ai/dakera-deploy
cd dakera-deploy/docker
docker compose -f docker-compose.local.yml up -dThat's it. Dakera is now running at http://localhost:3000.
# Verify it's healthy
curl http://localhost:3000/healthTo persist data across restarts, use the Development profile (MinIO-backed) or the Default profile (production-grade).
For IDE-integrated development, see the VS Code / Cursor Devcontainer below.
The fastest way to get a full Dakera dev environment — no local installs required.
Prerequisites: Docker + VS Code with the Dev Containers extension, or Cursor.
git clone https://github.com/dakera-ai/dakera-deploy
# Open the folder in VS Code / Cursor, then:
# "Reopen in Container" when prompted (or Ctrl+Shift+P → Dev Containers: Reopen in Container)That's it. The container build will:
- Pull the Dakera server image and MinIO
- Initialize the storage bucket
- Install Python, Node, Go, and Rust SDKs
- Open VS Code/Cursor with Rust Analyzer, REST Client, and other extensions pre-configured
Service endpoints (available on localhost):
| Service | URL | Notes |
|---|---|---|
| Dakera REST API | http://localhost:3000 | Main API |
| Dakera gRPC | localhost:50051 | gRPC endpoint |
| MinIO Console | http://localhost:9001 | minioadmin / minioadmin |
| MinIO S3 API | http://localhost:9000 | S3-compatible |
Auth is disabled for local dev. See docker-compose deployment for production auth setup.
| Profile | Description | Use Case |
|---|---|---|
| devcontainer | VS Code/Cursor one-click setup | SDK development, local testing |
| local | Single instance, in-memory storage | Quick testing, no dependencies |
| dev | MinIO storage backend for development | Local development with persistence |
| default | Dakera + MinIO with full configuration | Staging / single-node production |
| ha | 3-node cluster with Traefik load balancer | Production high availability |
| monitoring | Prometheus + Grafana observability stack | Metrics and dashboards |
| kubernetes | kubectl manifests or Helm chart | Production (cloud-native) |
Fastest way to get Dakera running. No external dependencies.
cd docker
docker compose -f docker-compose.local.yml up -d- REST API: http://localhost:3000
- gRPC API: localhost:50051
- Health check: http://localhost:3000/health
Includes MinIO for S3-compatible persistent storage.
cd docker
docker compose -f docker-compose.dev.yml up -d- MinIO Console: http://localhost:9001 (minioadmin/minioadmin)
Production-grade single-node deployment with MinIO, caching, and health checks.
Version pinning: The default Dakera image tag is pinned to v0.12.1 (v0.11:
release/0.11). To run a specific version, setDAKERA_IMAGEandDASHBOARD_IMAGEin your.env:DAKERA_IMAGE=ghcr.io/dakera-ai/dakera:0.12.1 DASHBOARD_IMAGE=ghcr.io/dakera-ai/dakera-dashboard:0.5.0Pinning to explicit versions prevents unexpected upgrades in production.
First-time setup — configure credentials before starting:
cd docker
cp .env.example .env
# Edit .env — set DAKERA_ROOT_API_KEY and MinIO credentials
# Generate a strong key: openssl rand -hex 32docker compose up -d- REST API: http://localhost:3000
- gRPC API: localhost:50051
- MinIO Console: http://localhost:9001
Production HA deployment with Traefik load balancer, 3 Dakera nodes, gossip-based clustering, and MinIO storage (one bucket per node).
cd docker
docker compose -f docker-compose.ha.yml up -d- REST API (load balanced): http://localhost:3100
- gRPC API (load balanced): localhost:50151
- Traefik Dashboard: http://localhost:8080
- MinIO Console: http://localhost:9101
- Cluster status: http://localhost:3100/admin/cluster/status
Set DAKERA_CLUSTER_SECRET first: at least 16 characters, the same on every node, generated with
openssl rand -hex 32, in the env file you start the stack with (.env, or .env.ha with
--env-file .env.ha). From v0.12.1 a cluster node without it exits with code 78, fresh install or upgraded,
so the file has no development default and refuses to start without it. Each node uses its own MinIO bucket.
Authentication is on (DAKERA_AUTH_ENABLED
defaults to true here too: the load balancer port is published on every interface). The nodes share no
Redis: with one Redis shared by the three nodes, v0.12.0's replication applied nothing on some peers
(measured: 3 of 6 node pairs never converged); without it every write reached the two other nodes within
0.1 s.
Dashboard 0.5.0 deploys exactly like 0.4.0: same image name, same variables (DAKERA_API_UPSTREAM,
optional DAKERA_SESSION_TTL_HOURS), port 3000, healthcheck /_session/healthz. Coming from 0.4.0, change
the image tag and nothing else (DASHBOARD_IMAGE, or docker compose pull dashboard). The navigation is
regrouped into six areas and every 0.4 URL redirects to its new home, so bookmarks keep working. 0.5.0 also
adds the Operations hub (background jobs, re-embedding, indexes, consolidation), analytics and metrics pages,
and the server audit log, and serves a strict Content-Security-Policy. Release notes: the dashboard's
CHANGELOG.
The dashboard (docker compose --profile dashboard up -d, or always on in the HA file) no longer carries an API key.
Operators open /login and sign in with their own Dakera API key; the dashboard's session service keeps it in
server memory behind an HttpOnly, SameSite=Strict cookie, and nginx adds Authorization: Bearer <key> to API
calls itself. Until 0.3.x the container wrote DAKERA_API_KEY into every served page (#296).
Upgrading from 0.3.x (breaking for deployments; introduced in 0.4.0):
- Remove
DAKERA_API_KEYandDAKERA_CLIENT_URLfrom the dashboard service. Both are ignored with a startup warning. Rotate any key the old dashboard carried (the compose files usedDAKERA_ROOT_API_KEY) if the dashboard was reachable by people who should not hold it: that key was readable in every page it served. - Keep
DAKERA_API_UPSTREAM(unchanged; the compose files set it).DAKERA_SESSION_TTL_HOURSis new and optional (default12, the longest a sign-in lasts; idle sessions end after 2 hours). - Sessions are in memory: restarting the dashboard signs everyone out, and it needs no volume. Run one replica (or sticky sessions), otherwise a request landing on another replica asks for a new sign-in.
- The container serves on port
3000(the session service listens on loopback3001inside the container; do not publish it). The healthcheck is/_session/healthz;/health/liveand/health/readystay public. - The image is a little larger (about 40 MB for
python3, used by the session service).
TLS in front. The session cookie is marked Secure (and __Host- prefixed) only when the request arrives with
X-Forwarded-Proto: https, and state-changing requests are accepted only when their Origin matches the Host (or
X-Forwarded-Host) the proxy forwards. So the proxy in front must terminate TLS, forward X-Forwarded-Proto and keep
the original Host. The compose files publish the dashboard on 127.0.0.1 (single node) so a proxy on the same
host can reach it; do not expose the plain-HTTP port to the internet (the API key is typed into the login form).
# Caddy: sets X-Forwarded-Proto/-For and keeps Host by default
dashboard.example.com {
reverse_proxy 127.0.0.1:3002
}# nginx
server {
listen 443 ssl;
server_name dashboard.example.com;
# ssl_certificate / ssl_certificate_key ...
client_max_body_size 200m; # backup uploads
location / {
proxy_pass http://127.0.0.1:3002;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off; # live feed (SSE)
proxy_read_timeout 300s;
}
}Traefik and ingress-nginx forward both headers by default; behind a cloud load balancer that terminates TLS, make
sure the controller trusts and passes its X-Forwarded-Proto (ingress-nginx: use-forwarded-headers: "true").
Add observability to any deployment profile.
# Start Dakera with monitoring (standalone monitoring compose)
cd docker
docker compose up -d
cd ..
docker compose -f docker/docker-compose.yml -f monitoring/docker-compose.yml up -dOr use the monitoring profile in the HA stack:
cd docker
docker compose -f docker-compose.ha.yml --profile monitoring up -d- Prometheus: http://localhost:9090
- Grafana: http://localhost:3003 (admin/dakera)
The "Dakera Overview" dashboard is the server's v0.12 dashboard: request rates and latency percentiles,
HTTP statuses and errors, health and configuration (config warnings, degraded components, WAL and
memory-read failures, backups), models and memory admission, recall and ingest stage latencies, derived caches
and late interaction, tiered storage, cluster replication, encryption and the RocksDB hot tier. Prometheus loads
the server's alert rules (monitoring/dakera.rules.yml) next to the deploy-side ones
(monitoring/alerting-rules.yml); the HA stack scrapes its three nodes (monitoring/prometheus.ha.yml) and alerts
on the node count. Every expression reads a metric the v0.12 server emits.
Production deployment via kubectl or Helm. See Kubernetes Deployment below.
Once Dakera is running, connect with the official CLI and MCP server:
# dk CLI — inspect memory, run queries, manage namespaces
brew install dakera-ai/tap/dk # macOS
# or: curl -fsSL https://dakera-ai.github.io/apt-repo/install.sh | sh # Linux
dk store --namespace myagent "User prefers concise replies"
dk recall --namespace myagent "communication style"
# dakera-mcp — expose Dakera tools to AI agents via Model Context Protocol
npx @dakera-ai/dakera-mcp # zero-install, latest version
# or: brew install dakera-ai/tap/dakera-mcp
# Add to Claude Desktop: { "mcpServers": { "dakera": { "command": "npx", "args": ["@dakera-ai/dakera-mcp"] } } }See dakera-cli and dakera-mcp for full documentation.
Stop v0.12.0 and start v0.12.1 on the same data and environment; nothing is migrated by hand (the stored formats are v0.12.0's). The server's guide: UPGRADE.md, "Upgrading from v0.12.0 to v0.12.1".
-
Back up (
POST /admin/backups). -
Take the new files (
git pullonmain): imageghcr.io/dakera-ai/dakera:0.12.1(dashboard0.5.0). If you pinDAKERA_IMAGE/DASHBOARD_IMAGEin.env, change them there. -
Clusters only (
docker-compose.ha.yml):DAKERA_CLUSTER_SECRETis required on every node. A 0.12.1 cluster node without it exits with code 78 before serving, fresh install or upgraded (v0.12.0 let an upgraded node run without it, which leftPOST /internal/sync/key/addopen to anyone reaching the API port). Nodes with and without the secret do not see each other, so:- the cluster already has a secret: upgrade as usual, keeping the same value;
- the cluster ran without one (an upgraded v0.12.0 or v0.11.108 cluster): upgrade in one window.
Generate one secret, put it in the env file you start the stack with, pull and check with the new
image, then restart every node together:
The cluster is down for the restart only; each node keeps its data. Then, on every node,
cd docker openssl rand -hex 32 # -> DAKERA_CLUSTER_SECRET=<value> in .env (or .env.ha, with --env-file .env.ha) docker compose -f docker-compose.ha.yml pull docker compose -f docker-compose.ha.yml run --rm --no-deps dakera-1 --check-config # exit 0 docker compose -f docker-compose.ha.yml down # volumes kept docker compose -f docker-compose.ha.yml up -d
GET /admin/cluster/statuslists the two others as healthy members and the same leader. Rotating the secret later needs the same one-window restart.
Single nodes are not affected, nor are the
k8s/manifests (one server, no cluster mode); a cluster built from them (one release per node) needs the same secret on every node, from thedakera-secretsSecret. -
Start v0.12.1:
docker compose pull && docker compose up -d(Kubernetes:kubectl apply -k k8s/). On the first start, with nothing to do:- Full-text indexes still on the v0.11 analyzer are re-analysed in the background while they keep
serving (log:
Full-text index re-analysed under the configured analyzer). The v0.12.0 manualPOST /admin/fulltext/reindex {"rebuild": true}step is no longer needed; if you already ran it, nothing is left to do. - A changed
DAKERA_MODELis no longer refused: the store is re-embedded in the background, each namespace answered with its own model until its turn (progress:/healthembedding_model_change). Still refused, as on v0.12.0, withDAKERA_TIERED=1(the quick-start files' default), late-interaction scoring, the visual lane, or a recorded model the build does not know.
- Full-text indexes still on the v0.11 analyzer are re-analysed in the background while they keep
serving (log:
-
Memory and session counts change meaning. Memory totals stop counting sentence sub-memories and drop; session totals count ended sessions too and rise (
GET /v1/agentsmemory_count/session_count,GET /v1/agents/{id}/statstotal_memories/total_sessions,GET /admin/memory-type-statstotal,GET /v1/kpissession_count_weekly). The oldGET /v1/agentsfigure is the newvector_count. Data, recall and quotas are unchanged. The Prometheus rules and Grafana dashboards inmonitoring/read none of these fields (dakera_memories_totalanddakera_sessions_activekeep their meaning); annotate the step in any report or alert of your own built on them.
Check: /health is ready, GET /v1/agents lists every agent, and a keyword search returns hits.
Going back to v0.12.0 is not part of the server's release checks: restore the backup from step 1.
An unchanged v0.11.108 deployment upgrades in place: stop v0.11, start v0.12.1 on the same data and the same environment. It starts, keeps its data and answers as before, except for the defects v0.12 fixes on purpose. The full guide is the server's docs/v0.12/UPGRADE.md (release notes: RELEASE_NOTES.md). Summary for the files in this repo:
- Back up (
POST /admin/backups). - Check the configuration with the new image, against your environment and data volumes. It
lists every warning the first start will give, starts nothing, and exits
0(would start) or78(would refuse):cd docker docker compose run --rm --no-deps dakera --check-config # single node docker compose -f docker-compose.ha.yml run --rm --no-deps dakera-1 --check-config # HA
- Take the new files (
git pullonmain) and review what changed for your setup:- image
ghcr.io/dakera-ai/dakera:0.12.1; DAKERA_L2_CACHE_PATHis gone (v0.12 reads no such name; an upgraded deployment warns, a fresh install refuses): the data root isDAKERA_STORAGE_PATH(/data), and every local path derives from it. The compose files mount the data volume there and keep your old volumes where the tiers expect them (/data/cachefor the warm tier,/data/hotfor the hot tier);DAKERA_CACHE_REDIS_URLis gone (useDAKERA_REDIS_URL),DAKERA_NODE_IDis nowDAKERA_CLUSTER_NODE_ID(the old name is still honoured as an alias),DAKERA_S3_ACCESS_KEY/DAKERA_S3_SECRET_KEYare not read (useAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY),DAKERA_LOG_LEVELis not read (useRUST_LOG);- health checks read
/health/readywith a 10-minute start period (the port answers while models load; Kubernetes uses/health/livefor liveness and/health/readyfor readiness); - a model volume (
dakera-modelsat/app/models): the image ships bge-large and the reranker itself; any other model downloads there on first use. A model volume kept from v0.11 can be freed withdocker compose run --rm dakera models pruneonce you are staying on v0.12; - clusters (
docker-compose.ha.yml): setDAKERA_CLUSTER_SECRET(>= 16 characters, the same on every node; the file refuses to start without it). Each node now has its own bucket (dakera,dakera-2,dakera-3); nodes sharing one bucket are refused on a fresh install.dakera-1keepsdakera;dakera-2/dakera-3fill from their peers at start. v0.11 nodes send no secret and 0.12.1 nodes require one, so they do not see each other: upgrade every node in one window (see Upgrading from v0.12.0 to v0.12.1, step 3).
- image
- Things to know before the first start: gRPC clients need an API key when authentication is on;
keys pinned to namespaces lose node-wide routes; namespace quotas are now enforced; a stored,
enabled backup schedule starts running; clients that cut on
smart_scoreshould re-check their threshold. Details: the server UPGRADE.md, "Before you upgrade". - Start v0.12.1:
docker compose pull && docker compose up -d(Kubernetes:kubectl apply -k k8s/). WatchGET /health(config_warnings,embed_migration). - Full-text indexes: nothing to do on v0.12.1, see the next section.
v0.12.1: nothing to do. Full-text indexes built by v0.11 (without stemming, so release missed
released and keyword-style recall could return nothing) are re-analysed under the configured analyzer in
the background at startup, one namespace at a time, while they keep serving; a restart resumes, and each
cluster node does its own. Watch the log for Full-text index re-analysed under the configured analyzer.
An index holding documents that exist only in the index (POST /v1/namespaces/<ns>/fulltext/index) keeps
its analyzer instead of dropping them (logged).
Still on v0.12.0 with data from v0.11.108: rebuild them by hand, once, with a global admin key, after
GET /health/ready answers 200 (about 18 s for 18,000 memories; memories are not touched):
DAKERA_URL=http://localhost:3000 DAKERA_ROOT_API_KEY=... scripts/post-upgrade-reindex.sh
# or: curl -X POST $DAKERA_URL/admin/fulltext/reindex -H "x-api-key: <global admin key>" \
# -H "content-type: application/json" -d '{"rebuild": true}'Without namespace it covers every agent memory namespace; add "namespace": "<ns>" (or
DAKERA_NAMESPACE) for one. On Kubernetes, kubectl port-forward svc/dakera 3000:3000 first.
Check it: a keyword search (POST /v1/namespaces/<ns>/fulltext/search with a common word) returns
hits, and a short keyword recall returns memories.
Going back from v0.12 (v0.12.0 or v0.12.1) to v0.11.108 is supported (every v0.11 embedding model, encrypted or not),
except for a store that uses a v0.12-only feature: dakera downgrade refuses (exit 78, nothing changed)
a store on bge-m3 (multilingual), colbert-small / late interaction or the visual lane. Move such a
store to a v0.11 model under v0.12 first, or restore a backup taken before you turned the feature on.
dakera downgrade converts the data back, and must run as a one-off job after the server has
stopped (it refuses, exit 78 with nothing changed, while a server runs on the data):
cd docker
docker compose stop dakera-watchdog dakera
docker compose run --rm -T dakera downgrade > downgrade-report.json # JSON report on stdout (the log goes to stderr); exit 0 = data is v0.11.108's
# then start v0.11.108 with the v0.11 files (git checkout release/0.11):
DAKERA_IMAGE=ghcr.io/dakera-ai/dakera:0.11.108 docker compose up -d- Exit
0: done. Exit1: not yet (do not start v0.11; fix the cause and rerun). Exit78: refused, nothing changed: a server still runs on the data (its marker is refreshed every few seconds; a killed one stays live up to 120 s), the store uses a v0.12-only feature, or no data was found where the configuration looks (an empty or wrong volume / bucket). - Kubernetes:
kubectl apply -f k8s/dakera/downgrade-job.yamlafter scaling the Deployment to 0. - Docker run:
docker run --rm <same env and volumes> ghcr.io/dakera-ai/dakera:0.12.1 downgrade. - Clusters: roll back the whole cluster, not one node (HA recipe in the header of
docker/docker-compose.ha.yml). - Air-gapped, after
dakera models prune: re-seed the model volume first (server UPGRADE.md, "Going back to v0.11").
v0.12.0 adds multilingual search, multimodal memory, multi-vector records, late interaction, a RaBitQ search mode, rerank controls, a model store, a keyring for encryption keys, and a reworked reliability and observability layer. Every new feature is off by default: the files above deploy a server that behaves like v0.11.108's. Each feature is switched on by an overlay file, a Kustomize component or a Helm value, and is described, with its variables, resources, constraints and how to verify it, in docs/features-v0.12.md.
| Feature | Compose overlay (docker/) |
HA twin | Kubernetes (k8s-features/overlays/) |
|---|---|---|---|
Multilingual (bge-m3, per-language full-text, CJK, lang) |
docker-compose.multilingual.yml |
docker-compose.ha.multilingual.yml |
multilingual |
| Attachments + speech to text | docker-compose.multimodal.yml |
docker-compose.ha.multimodal.yml |
multimodal |
| Image / page indexing + visual recall (dedicated stack) | docker-compose.vision.yml |
n/a | vision |
| Multi-vector records | docker-compose.records.yml |
docker-compose.ha.records.yml |
records |
| Late interaction (colbert-small) | docker-compose.late-interaction.yml |
docker-compose.ha.late-interaction.yml |
late-interaction |
| RaBitQ search mode | docker-compose.rabitq.yml |
docker-compose.ha.rabitq.yml |
rabitq |
cd docker
docker compose -f docker-compose.yml -f docker-compose.multilingual.yml -f docker-compose.multimodal.yml up -d
docker compose -f docker-compose.ha.yml -f docker-compose.ha.multilingual.yml up -d
kubectl apply -k k8s-features/overlays/multilingual-multimodalThings to know before you switch one on:
- Multilingual, late interaction and vision change the embedding model or the lane. The store records
its model. From v0.12.1 an existing store started with the multilingual overlay is re-embedded in the
background (recall stays correct; progress in
/healthembedding_model_change). Late interaction and vision are still refused on a store embedded otherwise: use a fresh store, or migrate (DAKERA_ALLOW_MODEL_CHANGE=1for one start, thenPOST /admin/namespaces/migrate-dimensions). They setDAKERA_TIERED=0: the tiered embedding engine, which the quick-start files enable, pinsbge-largeand refuses late interaction. - Vision is a store of its own (a dedicated data root and bucket): never over an existing text store.
- RaBitQ saves latency, not memory.
- Models other than
bge-largeand the reranker are not in the image: they download into thedakera-modelsvolume on first use (docker compose run --rm dakera models pull bge-m3 whisper visionahead of time;HF_ENDPOINT,HTTPS_PROXYandHF_HUB_OFFLINEin.envfor mirrors, proxies and air-gapped hosts). - Check what a running server has on with
GET /v1/capabilities, andGET /health.
Step-by-step guides in the examples/ directory:
- Quickstart — Store and recall your first memory in 5 minutes
- REST API Integration Guide — Building a client directly against the API: auth & scopes, conventions, the full memory lifecycle (store/recall/update/forget), sessions, the consolidation family, scoring, error/retry handling, and a worked example
- Features in v0.12.0 — Multilingual, multimodal, records, late interaction, RaBitQ, the model store, security, reliability, observability: variables, resources, constraints, verification, sizing
- Environment Variables — Complete reference for all configuration options
- Production Checklist — Security, storage, HA, and monitoring checklist
- Backup & Restore — MinIO backup procedures and disaster recovery
dakera-deploy/
├── .devcontainer/ # VS Code / Cursor devcontainer
│ ├── devcontainer.json # Container config (extensions, ports, env)
│ └── docker-compose.yml # Dakera + MinIO dev services
├── docker/ # Docker deployment configs
│ ├── Dockerfile # Production multi-stage build
│ ├── Dockerfile.dev # Dev build with fast incremental compilation
│ ├── Dockerfile.local # Lightweight build from pre-built binary
│ ├── docker-compose.yml # Default: Dakera + MinIO
│ ├── docker-compose.dev.yml # Dev: MinIO only (run Dakera locally)
│ ├── docker-compose.local.yml # Local: single instance, in-memory
│ ├── docker-compose.ha.yml # HA: 3-node cluster + Traefik LB
│ ├── docker-compose.<feature>.yml # v0.12 opt-in overlays: multilingual, multimodal, vision,
│ │ # late-interaction, records, rabitq
│ ├── docker-compose.ha.<feature>.yml # their HA twins (all but vision)
│ └── traefik-dynamic.yml # Traefik routing and load balancer config
├── k8s/ # Kubernetes manifests (production)
│ ├── namespace.yaml # dakera namespace
│ ├── configmap.yaml # Non-secret server configuration
│ ├── secret.example.yaml # Secret template (never commit secrets)
│ ├── dakera/ # Dakera server
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ ├── hpa.yaml # Horizontal Pod Autoscaler (not applied by default in v0.12)
│ │ ├── check-config-job.yaml # One-off: pre-upgrade `dakera --check-config`
│ │ └── downgrade-job.yaml # One-off: rollback `dakera downgrade`
│ ├── dashboard/ # Dashboard UI
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── mcp/ # MCP server manifests (not applied: dakera-mcp is stdio-only)
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── minio/ # MinIO (use native S3 in cloud)
│ │ ├── statefulset.yaml
│ │ └── service.yaml
│ ├── monitoring/ # Prometheus + Grafana
│ │ ├── prometheus.yaml
│ │ └── grafana.yaml
│ ├── ingress.yaml # Nginx ingress (edit hostnames)
│ └── kustomization.yaml # kubectl apply -k k8s/
├── k8s-features/ # v0.12 opt-in features for Kubernetes (Kustomize)
│ ├── components/ # models-cache, multilingual, multimodal, vision, records,
│ │ # late-interaction, rabitq
│ └── overlays/ # ready-made combinations: kubectl apply -k k8s-features/overlays/<name>
├── docs/
│ └── features-v0.12.md # What v0.12.0 adds, per feature: variables, resources, constraints, verify
├── monitoring/ # Observability stack
│ ├── docker-compose.yml # Standalone monitoring compose
│ ├── prometheus.yml # Prometheus scrape configuration (single node)
│ ├── prometheus.ha.yml # ... and for the 3-node HA stack
│ ├── alerting-rules.yml # Deploy-side alert rules (latency, resources, MinIO)
│ ├── alerting-rules.ha.yml # HA node-count alerts
│ ├── dakera.rules.yml # The server's v0.12 alert rules (copied verbatim)
│ └── grafana/ # Grafana provisioning
│ └── provisioning/
│ ├── datasources/
│ │ └── datasources.yml # Prometheus + Jaeger datasources
│ └── dashboards/
│ ├── dashboards.yml # Dashboard auto-provisioning config
│ └── json/
│ ├── dakera-overview.json # The server's v0.12 dashboard
│ └── dakera-memory-api.json # Memory API throughput and latency
├── examples/ # Deployment guides and references
│ ├── quickstart.md # Zero-to-running tutorial
│ ├── environment-variables.md # Complete env var reference
│ ├── production-checklist.md # Pre-production checklist
│ └── backup-restore.md # Backup and restore procedures
├── LICENSE
├── CHANGELOG.md
└── README.md
| Variable | Default | Description |
|---|---|---|
DAKERA_HOST |
0.0.0.0 |
Bind address for the server |
DAKERA_PORT |
3000 |
REST API port |
DAKERA_GRPC_PORT |
50051 |
gRPC API port |
DAKERA_STORAGE |
memory |
Storage backend (memory, filesystem, s3) |
DAKERA_STORAGE_PATH |
/data |
Data root: write-ahead log, knowledge graph, filesystem backend, hot and warm tiers all derive from it |
RUST_LOG |
info |
Log verbosity level |
DAKERA_TELEMETRY |
enabled |
Product telemetry (hostname and IP included; see below). Set to 0/off to disable (see Telemetry) |
Dakera sends product telemetry by default, to count how many engines run and how they run. In v0.12 it is lifecycle events (engine_started, engine_stopped, engine_crashed, engine_version_changed) and a heartbeat every 6 hours: version, platform, deployment kind, storage topology, resource use, request counts and latency bands by type, memory / agent / namespace counts, the names of the configuration variables that are set and the values of the non-text ones. It also sends the machine's hostname, and PostHog keeps the connecting IP address and derives a coarse location from it, so it is not anonymous at the network level. Memory content, queries, ids, keys, secrets, paths and URLs are never transmitted, and there is no license check against a remote server. Everything sent is listed in the server's docs/telemetry.md.
To disable it, set either of:
DAKERA_TELEMETRY=off # or 0 / false / no
DO_NOT_TRACK=1 # honored as an unconditional opt-outFully air-gapped operation is supported (a failed send is one debug log line). Inspect the exact payload before it is sent with DAKERA_TELEMETRY_DEBUG=1.
| Variable | Default | Description |
|---|---|---|
DAKERA_S3_ENDPOINT |
- | S3-compatible endpoint URL |
DAKERA_S3_BUCKET |
dakera |
Storage bucket name |
DAKERA_S3_REGION |
us-east-1 |
S3 region |
AWS_ACCESS_KEY_ID |
- | S3 access key (there is no DAKERA_S3_ACCESS_KEY) |
AWS_SECRET_ACCESS_KEY |
- | S3 secret key (there is no DAKERA_S3_SECRET_KEY) |
| Variable | Default | Description |
|---|---|---|
DAKERA_L1_CACHE_SIZE |
100000 vectors |
Hot-tier budget of tiered storage (no effect without DAKERA_TIERED_STORAGE). A unit suffix (512MB, 1g) makes it bytes; a bare number below 10 million is a vector count. The compose files set 512MB, the Kubernetes ConfigMap 1GB |
DAKERA_DISK_CACHE_DIR |
- | Enables the L2 on-disk read cache (replaces v0.11's ignored DAKERA_L2_CACHE_PATH) |
DAKERA_CACHE_DIR |
{root}/cache/warm |
The warm tier's directory (tiered storage only) |
The image ships bge-large and the reranker and loads them in seconds with no network. Any other
model (DAKERA_MODEL=bge-m3, whisper, vision, GLiNER) downloads on first use into the model cache
(/app/models, the dakera-models volume). Pre-pull / air-gapped:
docker compose run --rm dakera models pull <model>; inspect with models list; free space with
models prune. Mirrors, proxies and offline hosts: HF_ENDPOINT, HTTPS_PROXY / HTTP_PROXY / ALL_PROXY / NO_PROXY and HF_HUB_OFFLINE in .env. See docs/features-v0.12.md and the server's models-and-docker.md.
Set by the overlay files listed under Features in v0.12.0; the variables, their defaults
and constraints are in docs/features-v0.12.md and docker/.env.example.
| Variable | Default | Feature |
|---|---|---|
DAKERA_MODEL |
bge-large |
Embedding model: bge-m3 (multilingual), colbert-small (late interaction) |
DAKERA_FULLTEXT_LANGUAGE / DAKERA_FULLTEXT_CJK_BIGRAMS / DAKERA_QUERY_LANG / DAKERA_MAX_SEQ_LENGTH |
en / follows the language / en / model maximum (bge-m3: 2048) |
Multilingual |
DAKERA_ATTACHMENTS / DAKERA_ATTACHMENT_MAX_BYTES / DAKERA_WHISPER_MODEL |
off / 26214400 / whisper-base |
Attachments and speech to text; DAKERA_WHISPER_MODEL is one of whisper-base (multilingual, language auto-detected, default and recommended), whisper-tiny.en (English, lightest), whisper-base.en (English), whisper-tiny (multilingual, lightest) or whisper-small (multilingual, quality; with no value set, speech now transcribes with whisper-base; see features-v0.12) |
DAKERA_VISION / DAKERA_VISION_MODEL |
off / colmodernvbert |
Image indexing and visual recall |
DAKERA_RECORDS / DAKERA_RECORD_MAX_VECTORS / DAKERA_RECORD_MAX_BYTES |
off / 4096 / 8388608 | Multi-vector records |
DAKERA_SCORING_STRATEGY |
single-vector |
late-interaction (with DAKERA_MODEL=colbert-small) |
DAKERA_SEARCH_MODE / DAKERA_RABITQ_BITS |
hybrid / 1 |
rabitq: latency, not memory |
DAKERA_RERANK_MAX_CANDIDATES |
unset (whole pool) | Caps the candidates the cross-encoder scores |
DAKERA_MEM_HIGH_WATER_FRACTION |
0.85 |
Memory budget media jobs reserve against (503 + Retry-After when full) |
| Variable | Default | Description |
|---|---|---|
DAKERA_CLUSTER_MODE |
false |
Enable cluster mode |
DAKERA_CLUSTER_ROLE |
- | Node role (primary, replica) |
DAKERA_CLUSTER_SEEDS |
- | Comma-separated seed nodes (host:port) |
DAKERA_CLUSTER_SECRET |
- | Shared secret of the node-to-node routes and gossip: required in cluster mode, >= 16 characters, identical on every node |
DAKERA_CLUSTER_NODE_ID |
generated once | Stable node identifier (DAKERA_NODE_ID is its legacy alias) |
DAKERA_GOSSIP_PORT |
7946 |
Gossip protocol port |
DAKERA_GOSSIP_BIND |
0.0.0.0:7946 |
Gossip bind address |
DAKERA_API_ADVERTISE |
- | Advertised API URL for the node |
| Variable | Default | Description |
|---|---|---|
DAKERA_TIERED_STORAGE |
false |
Enable L1→L2→L3 tiered storage (needs DAKERA_STORAGE=s3). The hot tier is RocksDB by default in v0.12 (DAKERA_HOT_TIER, fsynced writes: DAKERA_ROCKSDB_SYNC) |
DAKERA_HOT_TO_WARM_SECS |
3600 |
Seconds before hot data moves to warm (RocksDB) |
DAKERA_WARM_TO_COLD_SECS |
86400 |
Seconds before warm data moves to cold (S3) |
DAKERA_AUTO_TIER |
true |
Automatic tier promotion/demotion (no effect without DAKERA_TIERED_STORAGE) |
DAKERA_TIER_CHECK_INTERVAL_SECS |
300 |
Interval for tier check sweep |
| Variable | Default | Description |
|---|---|---|
DAKERA_MAX_BODY_SIZE |
10485760 (10 MiB) |
Max request body size in bytes. The compose files and the ConfigMap set 524288000 (500 MB) |
DAKERA_REQUEST_TIMEOUT |
300 |
Request timeout in seconds (the outer ceiling). docker-compose.yml sets 600, the HA file and the ConfigMap 120 |
| Variable | Default | Description |
|---|---|---|
DAKERA_REDIS_URL |
- | Redis URL for the L1.5 cache, rate-limit counters and SSE fan-out (replaces DAKERA_CACHE_REDIS_URL, which v0.12 no longer reads). Not set by any file here: do not point the nodes of one cluster at one shared Redis with v0.12.0 (replicated writes were not applied on some nodes, see "High Availability (3-Node Cluster)") |
| Variable | Default | Description |
|---|---|---|
DAKERA_AUTH_ENABLED |
true |
Enable API authentication (default on). With it on and no key configured the server still starts, logs an error and rejects every authenticated request: set DAKERA_ROOT_API_KEY |
DAKERA_ROOT_API_KEY |
- | Root API key (required in production compose) |
DAKERA_ENCRYPTION_KEY |
- | AES-256-GCM at rest: 64 hex characters (a raw 256-bit key) or a passphrase of at least 8 characters; the same on every node. Keys rotate through a keyring (see the features guide) |
| Variable | Default | Description |
|---|---|---|
DAKERA_GRPC_ENABLED |
true |
Enable the gRPC endpoint. v0.12 requires an API key in the call metadata (x-api-key or authorization: Bearer) whenever authentication is on |
┌─────────────────────────────────────────────┐
│ Client Applications │
└──────────────────┬──────────────────────────┘
│
┌────────▼────────┐
│ Traefik LB │
│ :3100 (HTTP) │
│ :50151 (gRPC) │
│ :8080 (Admin) │
└───┬────┬────┬───┘
│ │ │
┌─────────────┼────┼────┼─────────────┐
│ │ │ │ │
┌─────▼─────┐ ┌────▼────▼┐ ┌▼──────────┐ │
│ Dakera-1 │ │ Dakera-2 │ │ Dakera-3 │ │
│ (primary) │ │ (replica)│ │ (replica) │ │
│ :3000 │ │ :3000 │ │ :3000 │ │
│ :50051 │ │ :50051 │ │ :50051 │ │
│ :7946 │ │ :7946 │ │ :7946 │ │
└─────┬─────┘ └────┬─────┘ └─────┬─────┘ │
│ │ │ │
│ Gossip Protocol │ │
│ (cluster membership) │ │
│ │ │ │
└────────────┼──────────────┘ │
│ │
┌───────▼───────┐ │
│ MinIO │ │
│ (bucket/node) │ │
│ :9000 / :9001 │ │
└───────────────┘ │
│
┌──────────────────────────────────────┘
│ Monitoring (optional)
│
┌─────▼──────┐ ┌────────────┐
│ Prometheus │───▶│ Grafana │
│ :9190 │ │ :3203 │
└─────────────┘ └────────────┘
Key HA Features:
- Load Balancing: Traefik distributes HTTP and gRPC traffic across all healthy nodes
- Health Checks: Automatic removal of unhealthy nodes from the load balancer pool
- Gossip Protocol: Nodes discover and monitor each other via port 7946
- Per-Node Storage: each node keeps its own bucket and data root; writes are replicated to the peers (nodes must not share one bucket)
- Per-Node Tiers: Each node keeps its own L1 (memory) hot budget, its durable RocksDB hot tier (acknowledged writes the background flush still owes S3) and its warm tier
- Automatic Failover: Traefik routes around failed nodes transparently
All three build from a dakera source checkout (run them from its root); the published image,
ghcr.io/dakera-ai/dakera:0.12.1, is what the compose files and manifests here use.
| Dockerfile | Base Image | Purpose |
|---|---|---|
Dockerfile |
rust:1.95-slim-trixie → debian:trixie-slim |
The engine's own Dockerfile at v0.12.1 (builds the released image, models baked in); re-synced each server release |
Dockerfile.dev |
rust:1.95-trixie → debian:trixie-slim |
Dev build with BuildKit cache for fast incremental rebuilds (~30-120s after first build) |
Dockerfile.local |
debian:trixie-slim |
Lightweight runtime from a pre-built binary |
curl http://localhost:3000/health
curl http://localhost:3000/admin/cluster/status# All services
docker compose -f docker-compose.ha.yml logs -f
# Specific node
docker compose -f docker-compose.ha.yml logs -f dakera-1docker compose -f docker-compose.ha.yml stop dakera-3
docker compose -f docker-compose.ha.yml start dakera-3docker compose -f docker-compose.dev.yml up -d --buildProduction-grade deployment on Kubernetes. Covers the Dakera server, the Dashboard, MinIO and monitoring (the MCP server is stdio-only and runs next to the MCP client; k8s/mcp/ is not applied). Use docker-compose for local/development; use Kubernetes for production.
- Kubernetes 1.27+
- kubectl configured for your cluster
- nginx ingress controller (for external access)
- Helm 3 (optional — for Helm-based deploy)
# 1. Create secrets (replace values)
kubectl create namespace dakera
kubectl create secret generic dakera-secrets \
--from-literal=DAKERA_ROOT_API_KEY=$(openssl rand -hex 32) \
--from-literal=MINIO_ROOT_USER=minioadmin \
--from-literal=MINIO_ROOT_PASSWORD=$(openssl rand -hex 16) \
--from-literal=AWS_ACCESS_KEY_ID=minioadmin \
--from-literal=AWS_SECRET_ACCESS_KEY=<minio-password> \
--namespace dakera
# Cluster mode only: add --from-literal=DAKERA_CLUSTER_SECRET=$(openssl rand -hex 32)
# 2. Edit ingress hostnames
# Edit k8s/ingress.yaml — replace yourdomain.com with your real domain
# 3. Apply all resources
kubectl apply -k k8s/
# 4. Verify pods are running
kubectl get pods -n dakera
# 5. Check Dakera health
kubectl port-forward -n dakera svc/dakera 3000:3000
curl http://localhost:3000/health/ready # 503 while models load, then 200The Helm chart has moved to the dedicated dakera-helm repository, which publishes to ArtifactHub and GHCR OCI. Helm 3.8+ required.
# Install from GHCR OCI
helm install dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera --version 0.12.1 \
--namespace dakera --create-namespace \
--set dakera.rootApiKey=$(openssl rand -hex 32) \
--set minio.rootPassword=$(openssl rand -hex 16)
# Install from ArtifactHub index
helm repo add dakera https://dakera-ai.github.io/dakera-helm
helm install dakera dakera/dakera \
--namespace dakera --create-namespace \
--set dakera.rootApiKey=$(openssl rand -hex 32) \
--set minio.rootPassword=$(openssl rand -hex 16)
# Upgrade to a new version
helm upgrade dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera --version <new-version> --reuse-values
# Uninstall
helm uninstall dakera -n dakeraSee dakera-ai/dakera-helm for chart source and full documentation.
| Component | CPU Request | Memory Request | Default Replicas |
|---|---|---|---|
| Dakera server | 500m | 512Mi | 1 (one server per data root; no HPA) |
| Dashboard | 100m | 64Mi | 1 |
| MinIO | 250m | 256Mi | 1 (StatefulSet) |
| Prometheus | 250m | 256Mi | 1 |
| Grafana | 100m | 128Mi | 1 |
- Use native S3 (AWS S3, GCS) instead of MinIO in cloud environments: set
DAKERA_S3_ENDPOINTto your provider's endpoint and disable MinIO (minio.enabled=falsein Helm) - Scaling: a server locks its data root and the volume is ReadWriteOnce, so one Deployment is one server and
k8s/dakera/hpa.yamlis not applied by default. Scale out with cluster mode (one release per node: own bucket, own volume, sharedDAKERA_CLUSTER_SECRET) - Dashboard 0.5.0: the Deployment has no API key (operators sign in with their own key;
DAKERA_API_KEYis gone, rotate any key the old dashboard carried). Keepreplicas: 1(sessions are in memory, or add sticky sessions), enable TLS on the dashboard host ink8s/ingress.yaml(ingress-nginx forwardsX-Forwarded-ProtoandHost), probes use/_session/healthz. See Dashboard 0.5.0 - TLS: add cert-manager annotations to
k8s/ingress.yamloringress.annotationsin Helm values - Secrets management: use an external secrets operator (External Secrets, Vault) instead of
kubectl create secretfor production - Metrics: Dakera exposes Prometheus metrics at
GET /metrics— pods haveprometheus.io/scrape: "true"annotations for auto-discovery
Before deploying to a production or internet-facing environment:
| Requirement | How |
|---|---|
| Enable authentication | DAKERA_AUTH_ENABLED=true (default in production compose) |
| Set a strong root API key | DAKERA_ROOT_API_KEY=$(openssl rand -hex 32) |
| Change MinIO credentials | Set MINIO_ROOT_USER and MINIO_ROOT_PASSWORD in .env |
| Network isolation | Do not expose MinIO ports (9000, 9001) publicly |
| TLS termination | Use a reverse proxy (nginx, Traefik, Caddy) with HTTPS |
See the Configuration Reference for the full authentication and security documentation.
| Repository | Description |
|---|---|
| dakera-docs | Full documentation |
| dakera-mcp | MCP Server for AI agent memory (14 core tools, 86+ via profiles) |
| dakera-cli | Command-line interface |
| dakera-py | Python SDK |
| dakera-js | TypeScript/JavaScript SDK |
| dakera-go | Go SDK |
| dakera-rs | Rust SDK |
| dakera-helm | Helm chart |
| Package | Framework | Install |
|---|---|---|
| langchain-dakera | LangChain (Python) | pip install langchain-dakera |
| @dakera-ai/langchain | LangChain.js | npm install @dakera-ai/langchain |
| crewai-dakera | CrewAI | pip install crewai-dakera |
| autogen-dakera | AutoGen | pip install autogen-dakera |
| llamaindex-dakera | LlamaIndex | pip install llamaindex-dakera |
See the integration guides on dakera.ai for setup walkthroughs.
dakera.ai · Documentation · Benchmarks
Copyright 2026 Dakera AI · MIT License