Self-Hosting
The Quickstart gets a single instance running in one command. This page is the production view: the three ways to run Truss — Docker Compose for a single box, the Helm chart for Kubernetes, and the operator for declarative / fleet management — plus the first-login flow and the hardening you should do before exposing it to the internet.
None of these paths needs a repo clone. All pull the published (cosign-signed)
ghcr.io/binarysquadd/truss-* images and bring up the full stack: the API, the dashboard,
Postgres, the Ory services (Kratos, Keto, Hydra, Oathkeeper), MinIO, flagd, and Valkey. The
current release is v0.3.0.
Docker Compose
Section titled “Docker Compose”For a single host. Download the Compose file and an env template, fill in secrets, and start:
curl -fsSLO https://raw.githubusercontent.com/binarysquadd/truss/main/docker-compose.selfhosted.ymlcurl -fsSL https://raw.githubusercontent.com/binarysquadd/truss/main/.env.selfhosted.example -o .env.selfhosted
# fill in every GENERATE_* value, e.g. with: openssl rand -hex 32
docker compose -f docker-compose.selfhosted.yml --env-file .env.selfhosted up -dThe dashboard is served at http://localhost:3000. (Prefer one command? The
Quickstart installer does the download + secret generation for you.)
The MCP server is an optional add-on, off by default. Turn it on with
docker compose -f docker-compose.selfhosted.yml --profile mcp up -d; it listens at
http://localhost:8765/mcp.
By default the Compose file uses the published ghcr.io/binarysquadd/truss-* images. To build
from source instead, clone the repo and uncomment the build: blocks in the file.
Kubernetes (Helm)
Section titled “Kubernetes (Helm)”The chart is published (and cosign-signed) as an OCI artifact, so one helm install pulls it
directly. No operator, no clone. Secrets you leave unset are auto-generated on first install
and reused across upgrades, so a bare install just works:
helm install truss oci://ghcr.io/binarysquadd/charts/truss --version 0.3.0 \ -n truss --create-namespace
kubectl -n truss port-forward svc/truss-dashboard 3000:80 # → http://localhost:3000Bring your own secrets with --set secrets.encryptionKey=… (or from an external secret manager);
any left blank are generated. Images are pinned in the chart and overridable via images.*. For
production set publicUrl + corsAllowedOrigins and front it with TLS. Toggle optional components
with their flags (e.g. --set mcp.enabled=false), and turn on the bundled 4-signal observability
stack (Grafana / Prometheus / Loki / Tempo) with --set observability.backends.enabled=true.
Kubernetes (Operator)
Section titled “Kubernetes (Operator)”The operator is the declarative, fleet-friendly path: you apply a TrussInstance custom resource
and a controller reconciles the app tier to match — healing drift, reporting status conditions, and
(optionally) emitting a ServiceMonitor + multi-window burn-rate SLO PrometheusRule for your
Prometheus stack. It manages the app tier (API + dashboard) and expects you to bring the
backing dependencies (starting with Postgres).
Install the controller + CRD from the release bundle, provide a Postgres connection Secret (a key
named database-url), then apply an instance:
kubectl apply -f https://github.com/binarysquadd/truss/releases/download/v0.3.0/install.yaml
kubectl create namespace trusskubectl -n truss create secret generic truss-db \ --from-literal=database-url='postgres://user:pass@your-postgres:5432/truss'
kubectl apply -f - <<'EOF'apiVersion: apps.truss.binarysquad.org/v1alpha1kind: TrussInstancemetadata: { name: truss, namespace: truss }spec: version: "0.3.0" publicURL: https://truss.example.com # required when ingress.enabled scaling: { profile: small } # small | medium | large dependencies: postgres: { mode: byo, existingSecret: truss-db } observability: serviceMonitor: true # created only if the Prometheus-operator CRDs exist prometheusRule: true otlpEndpoint: http://otel-collector.monitoring:4318 # optional: push traces/metrics/logsEOF
kubectl -n truss get trussinstance truss -o jsonpath='{.status.phase}' # → ReadyFirst login
Section titled “First login”On first boot, with no account yet, Truss seeds a default admin so you can sign in immediately, the same way Grafana and Argo CD do. It only ever runs when the identity store is empty, so it never overwrites real users.
-
Email:
[email protected](override withTRUSS_BOOTSTRAP_ADMIN_EMAIL). -
Password: set
TRUSS_BOOTSTRAP_ADMIN_PASSWORDfor a known value, or leave it blank and a random one is printed once to the API logs:Terminal window docker compose -f docker-compose.selfhosted.yml logs truss-api | grep "Default admin" # Composekubectl -n truss logs deploy/truss-api | grep "Default admin" # Kubernetes
Change it right after logging in under Settings → Account → Change Password. To opt out
entirely, set TRUSS_BOOTSTRAP_ADMIN=false and register the first user yourself.
See Configuration for the full list of environment variables.
Hardening (read before exposing to the internet)
Section titled “Hardening (read before exposing to the internet)”CORS_ALLOWED_ORIGINS— set to your dashboard origin(s). CORS fails closed; if unset, the browser app cannot reach the API (intentional).ENCRYPTION_KEY— a random 32+ char string used to encrypt saved connection passwords. If you lose it, those are unrecoverable. The Helm chart and operator auto-generate and persist it (in thetruss-secretsSecret); on Compose you set it yourself. Either way, back it up — and note the app refuses to start in production with a placeholder (change-me…) value.COOKIE_SECURE— the session cookie is markedSecureonly when you serve over HTTPS. Serving over plain HTTP keeps it off so the cookie is not dropped; setCOOKIE_SECURE=truebehind an HTTPS-terminating proxy the API cannot detect.TRUSS_ADMIN_IDENTITY_IDS— admin-only features (DB roles, migrations, backups, authz rules) are gated. Grant admin by setting this to your Kratos identity ID(s), comma-separated.- Put the API behind TLS, run Postgres with backups (PITR), and never run with dev defaults.
Ready to stop running it yourself?
Section titled “Ready to stop running it yourself?”If self-hosting has done its job and you would rather hand off the ops, Truss Cloud is the same platform, hosted and managed, with multi-org, metering, and managed backups. Your client code and API surface stay the same.