MemtraceDOCS

Deploy MemDBEnterprise

Operator guide for self-hosted MemDB: Docker, Docker Compose, Helm on Kubernetes, Azure and Google Cloud, plus how engineers connect local memtrace clients.

MemDB is the shared graph database behind Memtrace on the Teams plan. You run one MemDB cluster per org on infrastructure you control. Every engineer's local memtrace connects as a pure gRPC client — graph data, embeddings, and episode history live on your cluster, not on laptops. This page is the operator guide; engineer onboarding is Self-hosted MemDB (connect).

Overview#

Self-hosted topologyFLOW
deploy + bootstrap ownerissued user file → startexternal mode
Platform team
MemDB (memcore-server)gRPC :2424
Engineer laptop
Engineer laptop
EXTERNALSERVICEAGENT / AI
DO NOT AUTOSCALE MEMDB HORIZONTALLY

MemDB is stateful with a local data directory and HNSW index. Azure VMSS autoscale, Kubernetes HPA, and elastic node pools will split or corrupt state. Scale vertically (more RAM, faster disk) or run a fixed 3-node raft cluster — never an elastic replica pool.

Choose a deployment path#

PathBest forHA
Docker on one Linux VMAzure VM, GCP Compute Engine, on-prem — no Kubernetes team. Start here.Crash recovery via WAL; disk loss → restore from backup
Kubernetes + HelmAKS, GKE, EKS — production with PVC snapshots and ingress TLSOptional 3-replica raft (fixed replica count)
Docker Compose HAThree containers on one host — process failover only3-node raft; not separate machines

Your provisioning bundle's cluster/INSTALL.md is rendered with your org's database name, vector dimensions, and image tag — follow that file first when it disagrees with generic examples here.

Provisioning bundle#

Teams customers receive a tarball with two halves. The cluster/ half is for platform engineers (secrets). The engineer/ half is distributed to developers.

bundle layout
bundle/
├── cluster/                    # platform team — treat as secrets
│   ├── imagePullSecret.yaml    # ghcr.io pull credential (image + OCI Helm chart)
│   ├── tokens.store            # server token store (BLAKE3 hashes, no plaintext)
│   ├── enrollment.secret       # organization assertion verification secret
│   ├── owner-connect.json      # bootstrap admin bearer — owner only
│   ├── values.enterprise.yaml  # pre-rendered Helm values for your org
│   └── INSTALL.md              # org-specific install steps
└── engineer/
    └── connect.json            # endpoint/license metadata — no admin bearer

tokens.store is the read-only bootstrap source. enrollment.secret lets MemDB verify short-lived organization assertions issued after member login. The owner's bootstrap bearer remains in cluster/owner-connect.json for recovery. Do not distribute the cluster half to engineers.

Prerequisites#

All paths require:

  • Registry access to ghcr.io/syncable-dev/memcore (private image) via cluster/imagePullSecret.yaml
  • cluster/tokens.store and cluster/enrollment.secret — auth is on
  • cluster/owner-connect.json kept in your secret manager until the owner workstation is connected
  • Outbound HTTPS to memtrace.io from engineer machines for online license validation (offline licenses available — see memtrace connect)
  • Immutable vector dimensions: default 768 (jina-embeddings-v2-base-code). Set --vector-dims=768 on first boot; changing later requires a fresh empty data volume.

Docker on a VM (Azure, GCP, on-prem)#

Recommended first deploy when you do not run Kubernetes. Works on an Azure VM, a GCP Compute Engine instance, or any Linux host with Docker Engine 24+.

Pull the image

terminal
# Extract GHCR credentials from cluster/imagePullSecret.yaml, then:
docker pull ghcr.io/syncable-dev/memcore:<version-from-your-bundle>

Run single-node MemDB

terminal
docker volume create memcore-data

docker run -d --name memcore \
  --restart unless-stopped \
  -p 2424:2424 -p 2480:2480 \
  -v memcore-data:/var/lib/memcore \
  -v "$(pwd)/cluster/tokens.store:/etc/memcore/tokens/tokens.store:ro" \
  -v "$(pwd)/cluster/enrollment.secret:/etc/memcore/tokens/enrollment.secret:ro" \
  ghcr.io/syncable-dev/memcore:<version> \
  --bind 0.0.0.0:2424 \
  --rest-bind 0.0.0.0:2480 \
  --data-dir /var/lib/memcore \
  --default-db=<your-database-from-bundle> \
  --vector-dims=768 \
  --require-auth \
  --auth-token-store /etc/memcore/tokens/tokens.store \
  --auth-enrollment-secret-file /etc/memcore/tokens/enrollment.secret \
  --auth-enrollment-org <organization-id-from-bundle>

Ports: 2424 gRPC (authenticated), 2480 REST /health and /ready (no auth). Restrict gRPC to your VPN or engineer subnet — avoid exposing it on the public internet without TLS.

The memcore-data volume also persists the live user registry at /var/lib/memcore/auth/managed_tokens.toml. Keep tokens.store mounted read-only; adding, rotating, or revoking a user does not modify that mount or restart the container.

BACKUPS ON DOCKER

Stop the container before copying the data directory — live copies of LSM + WAL can be inconsistent. Pattern: docker stop memcoretar the volume → docker start memcore.

Docker Compose#

The single-node Compose file ships in the MemDB repository under deploy/. Copy both auth files next to it before up; missing files fail fast.

Single node

terminal
cp <bundle>/cluster/tokens.store deploy/tokens.store
cp <bundle>/cluster/enrollment.secret deploy/enrollment.secret

MEMCORE_IMAGE=ghcr.io/syncable-dev/memcore:<version> \
MEMCORE_ENROLLMENT_ORG=<organization-id-from-bundle> \
  docker compose -f deploy/docker-compose.single.yml up -d

# Health from the host (distroless image — no in-container curl):
curl -fsS http://localhost:2480/health
curl -fsS http://localhost:2480/ready

Three-node raft (one host)

terminal
cp <bundle>/cluster/tokens.store deploy/tokens.store

MEMCORE_IMAGE=ghcr.io/syncable-dev/memcore:<version> \
  docker compose -f deploy/docker-compose.ha.yml \
                 -f deploy/docker-compose.ha.publish-all.yml up -d

# Engineers use ordered failover — writes must reach the leader:
export MEMTRACE_MEMDB_ENDPOINTS=http://<host>:2424,http://<host>:2425,http://<host>:2426

Compose HA adds replication on a single machine — you get leader failover between containers, not separate fault domains. Organization enrollment is currently a single-replica feature because managed bearer state is local; keep static bootstrap credentials coordinated for raft deployments.

Kubernetes + Helm#

The canonical chart lives at memcore-rs/helm/memcore in the MemDB repo and publishes as oci://ghcr.io/syncable-dev/charts/memcore. Your bundle's values.enterprise.yaml pins image, auth, and pull secrets.

terminal
kubectl create namespace memcore
kubectl -n memcore apply -f cluster/imagePullSecret.yaml

kubectl -n memcore create secret generic memcore-auth \
  --from-file=tokens.store=cluster/tokens.store \
  --from-file=enrollment.secret=cluster/enrollment.secret

helm registry login ghcr.io --username <user> --password <token>

helm install memcore oci://ghcr.io/syncable-dev/charts/memcore \
  --version <chart-version-from-bundle> \
  --namespace memcore \
  -f cluster/values.enterprise.yaml \
  --set auth.existingSecret=memcore-auth

For HA with raft consensus (fixed 3 or 5 replicas, not autoscaling):

terminal
helm upgrade --install memcore oci://ghcr.io/syncable-dev/charts/memcore \
  --namespace memcore \
  -f cluster/values.enterprise.yaml \
  --set replicas=3 \
  --set memcore.replication=raft \
  --set networkPolicy.enabled=true \
  --set auth.existingSecret=memcore-auth

In-cluster gRPC endpoint: http://memcore:2424 (Service name follows the Helm release). Engineers outside the cluster need an ingress, VPN, or port-forward — see TLS below.

In the default single-replica deployment, the managed user registry lives on the pod's MemDB PVC and survives rescheduling or upgrades. The memcore-auth Secret remains the bootstrap credential only; normal user changes do not require a Secret update or StatefulSet rollout.

LIVE TOKEN ADMINISTRATION IS SINGLE-REPLICA TODAY

Managed token mutations are not yet raft-replicated. Use memtrace access with Docker/single-node or a single-replica Helm deployment. For a multi-replica raft cluster, keep the static bootstrap store coordinated across replicas until replicated token state is available.

Azure quick reference#

ItemRecommendation
VM SKUStandard_D4s_v5 (4 vCPU / 16 GiB) or larger for production pilot
Data diskSeparate Premium SSD managed disk (≥ 100 GiB), not OS disk only
NSGAllow 2424/tcp from engineer VPN/subnet only; avoid public gRPC
Monitoring2480/tcp for /health and /ready from your monitor subnet
EgressHTTPS to memtrace.io for license validation
AutoscaleOff — scale vertically or use fixed 3-node raft on AKS

Path A on Azure: provision a Linux VM, attach a Premium SSD data disk, install Docker, run the single-node command above. Set engineer/connect.json endpoint to http://<vm-private-ip>:2424 or your internal DNS name.

Path B on AKS: create a dedicated node pool (no cluster autoscaler on the MemDB pool), install via Helm as above, expose gRPC through an internal load balancer or gRPC-capable ingress.

Google Cloud quick reference#

ItemRecommendation
Compute Enginee2-standard-4 (4 vCPU / 16 GiB) or larger; pd-ssd data disk ≥ 100 GiB
FirewallAllow tcp:2424 from engineer VPC/subnet only; tcp:2480 for health checks
GKEStandard cluster, dedicated node pool, Helm Path B — no HPA on MemDB StatefulSet
EgressHTTPS to memtrace.io from engineer workstations

Path A on GCP: same Docker flow as Azure — one Compute Engine VM with Docker Engine, persistent disk for /var/lib/memcore, NSG-equivalent firewall rules.

Path B on GKE: identical Helm steps to AKS/EKS. Use a regional persistent disk StorageClass for PVCs; snapshot backups via GCE volume snapshots or your CSI driver.

Verify the cluster#

terminal
# REST probes (no auth):
curl -fsS http://<host>:2480/health
curl -fsS http://127.0.0.1:2480/ready   # via kubectl port-forward on K8s

# Auth enforcement (grpcurl + memcore.proto — server has no reflection):
# Must REJECT without token:
grpcurl -plaintext -proto memcore.proto \
  <host>:2424 memcore.v1.Memcore/Ping

# Must SUCCEED with writer token:
grpcurl -plaintext -proto memcore.proto \
  -H "authorization: Bearer ${MEMCORE_TOKEN}" \
  <host>:2424 memcore.v1.Memcore/Ping

On Kubernetes: kubectl -n memcore rollout status statefulset/memcore and confirm pods are 2/2 Ready when Studio sidecar is enabled (off by default in current chart).

Connect local memtrace instances#

After MemDB is up, pin its endpoint in the organization enterprise settings and add members on memtrace.io/account. Each member then enrolls with their own signed-in identity:

Organization member onboarding

terminal
memtrace auth login
memtrace connect <organization-slug>
memtrace connect --status    # verify endpoint + token + probe
memtrace start               # external mode — no env vars needed

connect verifies the active organization member, exchanges a signed assertion with this MemDB, writes secretless .memtrace/team.toml, and stores the expiring bearer in the member's own credentials.json. No administrator copies or distributes user tokens. Full walkthrough: Self-hosted MemDB and memtrace access.

Environment-variable fallback (CI / scripts)

VariableDefaultDescription
MEMTRACE_MEMDB_MODESet to external (aliases hosted, remote). Also inferred when the endpoint is non-loopback.
MEMTRACE_MEMDB_ENDPOINTRemote gRPC URL, e.g. http://memdb.corp.example:2424 or ingress https:// when TLS is configured.
MEMTRACE_MEMDB_ENDPOINTSComma-separated failover list for compose HA or multi-port publish — replaces singular MEMTRACE_MEMDB_ENDPOINT.
MEMTRACE_MEMDB_DBDatabase name from your bundle (not always memtrace).
MEMTRACE_MEMDB_AUTH_TOKENWriter bearer token — attached to every RPC.
MEMTRACE_MEMDB_TLS_CAPath to private CA for https:// endpoints with ingress or native TLS.
WHAT CHANGES ON THE LAPTOP

In external mode the machine runs only the watcher, indexer, and MCP tools as gRPC clients — no local memcore-server sidecar. memtrace reset clears local lock/cache only; it cannot wipe the shared cluster.

TLS, sizing, and operations#

TLS (ingress): enable chart ingress with a gRPC-capable controller (nginx by default) and cert-manager. Only the gRPC port is routed; REST probes stay cluster-internal. Set ingress.enabled=true, ingress.host=memdb.example.com, networkPolicy.enabled=true.

Sizing (planning guidance):

TierIndexed codeRAMDisk
S — pilot≤ ~0.5 MLOC4–8 GB50 Gi
M — typical org~0.5–3 MLOC16 GB100 Gi
L — large monorepo3–10+ MLOC64 GB250–500 Gi

Day-two ops: add or remove normal users through organization membership. Removed users cannot renew and their local bearer expires within 24 hours. Use memtrace access revoke for urgent immediate removal and memtrace access add for offline/service accounts. Reserve memcore-auth Secret changes for bootstrap rotation. Upgrade MemDB with a fresh backup first. Prometheus metrics are on :9090/metrics (no auth). Detailed runbooks ship in the MemDB repo under docs/ops/.

Troubleshooting#

SymptomLikely causeFix
helm install fails: auth.existingSecret requiredAuth-on is mandatoryCreate memcore-auth Secret from tokens.store and enrollment.secret (§ Helm)
ImagePullBackOffPrivate registryApply imagePullSecret in the release namespace; match values.enterprise.yaml
Every RPC UNAUTHENTICATEDMissing, expired, or wrong organization credentialRun memtrace auth login, then memtrace connect <organization-slug>
Engineer cannot connectNetwork / TLS / tokenVPN, firewall on 2424, http vs https, memtrace connect --status
Vector dimension error on first indexClient embed model mismatchAlign MEMTRACE_EMBED_MODEL / 768 dims across all clients

Next: engineer onboarding, user access management, memtrace connect flags, and Teams plan quotas.