Remote service
SOON. Server-side kache is the next milestone. The deployment model, auth integration, and HA behavior are still hardening — treat the planner service and Helm chart as a preview today.
The remote planner service warms the right artifacts before rustc asks for them. Where local kache reacts to cargo invoking rustc, the planner anticipates: it draws on build manifests (uploaded by kache save-manifest), dependency history, and the client's build intent, then advises clients which artifacts to prefetch from S3 at the start of a session.
The service lives in crates/kache-service. It persists planner state in an embedded SurrealDB database and serves three HTTP routes: POST /v1/prefetch-plan and POST /v2/prefetch-plan (both aliased to the same handler — clients default to /v2), plus GET /healthz and GET /readyz probes. It safely returns a use_fallback disposition when the database has no matching candidates — so clients always have a working code path even before the planner has data for them.
What it does
- Manifest upload. Clients call
kache save-manifestat the end of a build. This uploads a build manifest (and, with--namespace, sharded indexes keyed byCargo.lock) to the configured S3 remote — each entry records cache key, crate name, compile time, and artifact size. The planner service consumes that data out of band (it is seeded from a snapshot today; seeKACHE_PLANNER_SEED_STATE_FILE) —save-manifestdoes not POST to the service. - Prefetch hints. At the start of a new build session, the client
POSTs a build intent (crate names, namespace,Cargo.lockdeps) to the planner. The planner replies with a plan: adisposition(ExecuteorUseFallback) and, when executing, rankedcandidates(cache key + crate name) likely to be needed. - Use-fallback safety. If the planner has no service-side state, resolves no candidates, or hits an internal planning error, it returns a
UseFallbackplan rather than an HTTP error. Clients then fall back to filtering S3 prefetch byCargo.lock(the same path the daemon uses today without a planner).
Build and run
just build-service
just image-service
just image-service-release
cargo run -p kache-service
For local development, cargo run -p kache-service binds 0.0.0.0:8080 by default (override with --bind / KACHE_PLANNER_BIND) and persists the embedded SurrealDB planner database at /var/lib/kache/planner.db (override with --db-path / KACHE_PLANNER_DB_PATH). Pass --token / KACHE_PLANNER_TOKEN to enforce bearer auth on the standalone binary, and KACHE_LOG (default kache_service=info) to filter logs. For a containerized run, the image-service recipes produce a linux/amd64 image (override PLATFORM in docker-bake.hcl to target other architectures).
Helm chart
helm upgrade --install kache-service ./charts/kache-service
The chart in charts/kache-service is intentionally small: one Deployment, one Service, optional PersistentVolumeClaim, hardened security defaults (runAsNonRoot, UID/GID 65532, readOnlyRootFilesystem, all capabilities dropped — the writable DB path must live on a mounted volume), health probes, optional kunobi-auth bearer-token wiring through an existing Secret, and optional kunobi-ha Lease-based leader election. When ha.enabled, it also ships a ServiceAccount plus Role/RoleBinding granting the coordination.k8s.io Lease permissions leader election needs (and mounts the service-account token only under HA). It does not bundle ingress or cluster-level policy — bring your own.
Pointing clients at the planner
Clients only consult the planner when KACHE_PLANNER_ENDPOINT is set (or cache.planner.endpoint in config) — KACHE_PLANNER_TOKEN alone does nothing. Point clients at the in-cluster service:
KACHE_PLANNER_ENDPOINT=http://<svc>.<ns>.svc.cluster.local:8080
# optional: KACHE_PLANNER_TIMEOUT_MS to bound the planner round-trip
Bearer-token auth
Auth is enabled by pointing the chart at an existing secret. Clients must send the matching token through KACHE_PLANNER_TOKEN. The standalone binary enforces the same check when started with --token / KACHE_PLANNER_TOKEN; with no token configured, requests are accepted anonymously. A request that lacks valid auth when a token is set gets 401.
auth:
existingSecret: kache-planner-token
existingSecretKey: token
Planner state and persistence
The service stores its embedded planner database at /var/lib/kache/planner.db by default (planner.dbPath, also --db-path / KACHE_PLANNER_DB_PATH). The chart default is persistence.enabled: true with type: ephemeral — an emptyDir that does not survive pod restarts. Switch type to pvc for durable planner state:
planner:
dbPath: /var/lib/kache/planner.db
persistence:
enabled: true
type: pvc # default is `ephemeral` (emptyDir, lost on restart)
mountPath: /var/lib/kache
size: 10Gi
For bootstrap / migration only, the service can still import a legacy JSON planner snapshot on startup via KACHE_PLANNER_SEED_STATE_FILE. New installs should ignore this knob.
High availability
For HA deployments, enable leader election and raise the replica count. /healthz always returns 200, but /readyz (and prefetch-plan) return 503 until the repository is loaded and leadership is acquired — so followers stay live-but-not-ready until they win the Kubernetes Lease:
replicaCount: 2
ha:
enabled: true
leaseName: kache-service
The chart's ha.* keys map to the binary's --ha-enabled / --ha-namespace / --ha-lease-name flags (KACHE_HA_ENABLED / KACHE_HA_NAMESPACE / KACHE_HA_LEASE_NAME). The namespace resolves from ha.namespace, then POD_NAMESPACE, then the mounted service-account namespace file — startup fails if none resolve.
When combining HA with PVC-backed planner state, use storage that can be mounted by all scheduled replicas (e.g. ReadWriteMany), or keep replicaCount: 1. The Lease itself is fine across replicas — the constraint is the planner DB volume.
What you get without the service
Local caching, S3 sync, and cargo metadata-driven prefetch all work without the planner. The planner is purely additive: it raises the hit rate on the first build of a new branch or runner where cargo metadata alone would underprefetch. If you don't run the service, clients silently behave as they do today.