Deploy
Run a server for real.
Observe
Collect metrics and traces.
Manage a fleet
Read the worker census and drive fleet-wide operations.
Plugin setup
Backends, storage, accounts, identity, and monitoring.
Self-host with the distribution bundle
tai-distribution packages the
whole platform as one batteries-included container image plus a Docker Compose
bundle and a Helm chart. The image installs the first-party plugin set and bakes
the built Studio in, so a self-hosted install is one image and the
services it talks to.
The image entrypoint is tai and its default command is serve. Three
long-lived processes come out of the same image:
A one-shot
db-init step runs tai db apply, and serve and backend wait for
it to complete before they start. The DDL is additive and IF NOT EXISTS, so
re-running it is safe.
The distribution’s first release is in preparation, so the published
docker.io/tai42/tai image (mirrored at ghcr.io/tai42ai/tai) is not on the
registries yet. Build it locally from the repo with the source build below until
it is.Boot the Compose bundle
config/ is bind-mounted at /app in the three long-lived services, so config/manifest.yml
is the manifest the runtime loads and config/.env is the
app-side environment. Create config/.env even when it is empty — the
config-reload path treats a missing file as an error.
Only serve publishes a port (${TAI_SERVE_PORT:-8000}). Postgres, Redis, and
the optional MinIO and RabbitMQ services stay on the Compose network.
Build the image from source
compose/docker-compose.local.yml layers a SOURCE=local build onto every app
service, building the image from sibling checkouts instead of pulling it:
siblings build context defaults to the parent of the checkouts (../..)
and is overridable with TAI_SIBLINGS. Because that context can hold untracked
secrets, the source build is for a local builder only — never CI, never a shared
registry.
Configure the bundle
The Compose bundle reads a small set of variables from.env; everything else is
fixed in the file and points the services at each other.
POSTGRES_PASSWORD has no default: Compose refuses to start until it is set.
The minio and celery service profiles add MINIO_ROOT_USER,
MINIO_ROOT_PASSWORD, STORAGE_S3_BUCKET, RABBITMQ_USER, and
RABBITMQ_PASSWORD.
Five Postgres-backed stores and every Redis-backed feature store are already
pointed at the bundled postgres and redis services, so the schema-admin
connection, the access-control store, the connector store, the marketplace store,
and the versioning store all resolve without further configuration.
Turn on access control
SetACCESS_CONTROL_ENABLE=true and register a provider in the manifest. The
bundled default is the Redis-backed API-key provider, which the image already
installs:
manifest.yml
tai keys and write the
policy that key resolves to — access control covers
the policy model, and the access-control guide walks
the first key end to end.
ACCESS_CONTROL_ALWAYS_PUBLIC_PATH_PREFIXES selects the paths served without a
key. The bundle’s default covers the login route and the Studio’s static assets:
/health and /ready are deliberately absent: the app already serves them
public by route-level declaration, and listing them here is rejected at boot as a
conflict.
For human sign-in — sessions, roles, invites, and the first admin — add the
accounts provider described in Accounts.
Run on Kubernetes
The repo ships a real Helm chart atcharts/tai. Its release publishes the chart
as an OCI artifact alongside the image, so the same “in preparation” caveat
applies — until then, install from the checkout with helm install tai ./charts/tai.
serve and backend as separate Deployments, each with the
metrics endpoint as a native sidecar, and installs Postgres and Redis
StatefulSets by default. Point it at managed datastores instead by disabling
both:
serve.replicaCount scales the API; running serve.workers above one requires
serve.statelessHttp=true, because a stateful HTTP transport refuses a
multi-worker boot. A schemaInit hook Job runs tai db apply around install and
upgrade.
The chart requires Kubernetes 1.29 or newer, because the metrics sidecar is a
native sidecar container. It integrates with cluster add-ons but never installs
them: an Ingress controller, cert-manager for ingress.tls, the
prometheus-operator for metrics.serviceMonitor, and a StorageClass for
persistence.
TLS and the front door
serve speaks plain HTTP on its published port, and the Compose bundle puts
nothing in front of it. Terminate TLS at your own reverse proxy or load balancer
and forward to that port.
On Kubernetes the chart’s Ingress is single-host, single-path — the Studio and
the /api surface share one origin, so there is nothing to split — and passes
ingress.tls straight through to the Ingress resource:
values.yaml
CONNECTORS_REDIRECT_URI_ALLOWLIST, and tai42-accounts-oidc
requires an https TAI_ACCOUNTS_OIDC_PUBLIC_BASE_URL.
See also
- Deploy — transports, workers, and the serving modes.
- Back up and restore — what state to capture.
- The layering — what the image actually contains.

