Deployment
knomit’s first goal is to be a plain HTTP server deployable anywhere. The Docker image is fully self-contained: every dependency — the native libraries (ONNX Runtime, graphqlite, tokenizers) and the embedding model — is fetched at build time and baked in. The running container performs no network downloads at startup.
Building the image
Section titled “Building the image”The Dockerfile is a three-stage build: node builds the web UI, a CGO Go
stage builds the binary + fetches native libs + bakes the model with
knomit warm-models, and a slim Debian runtime stage assembles the final image.
-
Build for your host architecture:
Terminal window make docker# → knomit:<semver>.<sha> and knomit:latest -
Or cross-build for
linux/amd64from a non-amd64 host (Apple Silicon, etc.). Requires a buildx-capable Docker (Docker Desktop / OrbStack provide it):Terminal window make docker-amd64# → knomit:<semver>.<sha>-amd64 and knomit:latest-amd64
Both targets tag the image with the full <semver>.<sha> version string (the
same string the binary reports as its version) and a moving latest. The
Dockerfile itself is architecture-agnostic — fetchlibs pulls the per-platform
native libraries and the runtime stage globs dist/linux-*/lib.
Running the container
Section titled “Running the container”docker run -d --name knomit \ -p 19278:19278 \ -v knomit-data:/data \ knomit:latestOpen http://localhost:19278/. The container starts with no repositories —
create your first from Manage in the web UI, or with POST /api/v1/repos.
Container environment
Section titled “Container environment”The image ships these defaults (set in the Dockerfile):
| Variable | Value | Why |
|---|---|---|
KNOMIT_HOST | 0.0.0.0 | Listen on all interfaces (vs. localhost locally) |
KNOMIT_PORT | 19278 | Exposed port |
KNOMIT_HOME | /data | Data root — mount a volume here |
ORT_LIB_PATH | /opt/knomit/lib/libonnxruntime.so | Baked ONNX Runtime |
Common additions for a container deployment:
KNOMIT_LOG_FORMAT=json— structured logs on stdout for your log driver. LeaveKNOMIT_CRASH_LOGunset; the driver already captures fd 2.- Synthesis credentials — synthesis is the only LLM-backed feature. If you
run it, pass a provider key (e.g.
GOOGLE_AI_API_KEY); a read-only or browse-only instance needs none. See LLM configuration. - Metrics/pprof — set
KNOMIT_RUNTIME_ADDRto a loopback address and reach it via a port-forward; never expose it. See Observability.
Running a read-only / demo instance
Section titled “Running a read-only / demo instance”Set KNOMIT_READ_ONLY=true to serve a public, browse-only instance of your
own repo. (The /explore page on this site takes a different path
to the same read-only result — a static, build-time snapshot rather than a
live KNOMIT_READ_ONLY server — but the guarantees below are what “read-only”
means either way.) Read-only is startup-only (it cannot be toggled at
runtime) and, across every surface:
- HTTP — all mutating methods (
POST/PUT/PATCH/DELETE) return403, and the built-in git smart-HTTP endpoint is not mounted — so a read-only instance cannot serve an OKF export, which reads that endpoint. Pointknomit-okfat a writable instance, or at the repo on disk. Both MCP dispatch routes (/repos/{repo}/branches/{branch}/mcpand/lenses/{lens}/mcp) are exempt from the method gate, because MCP reads arePOSTs; read-only-ness there is enforced by tool filtering instead. The lens REST endpoints (/lenses,/lenses/{lens}) stay gated, so lens CRUD is blocked. - MCP — only the read tools are exposed (
knomit_query,knomit_explain,knomit_repos); the write tools (knomit_learn,knomit_update,knomit_retract,knomit_hypothesize,knomit_review) are omitted from the tool list. - Origin sync — pull-only: it fetches and fast-forwards from origin but never pushes back.
docker run -d --name knomit-demo \ -e KNOMIT_READ_ONLY=true \ -p 19278:19278 -v knomit-demo:/data \ knomit:latestThere is no environment variable for the origin URL: a repo is created from a
remote through POST /api/v1/repos (mode: "clone"), and the [remote] /
KNOMIT_REMOTE_* settings supply only the credentials that call uses. For a
demo instance, create the repo once against the mounted volume; the origin is
recorded in control.db and survives restarts.