Self-hosting means you run the same three layers a timbal create project contains — UI, API, and workforce — without timbal start managing them. You own process lifecycle, port allocation, env wiring, restarts, and log aggregation.
There is no timbal build or CLI-generated Docker image. You bring your own process manager (systemd, supervisord, Kubernetes, etc.) and production build pipeline.
Prerequisites
- A project created with
timbal create
- Bun for
api/ and ui/
- uv for workforce Python deps
timbal[server] installed in each workforce member’s venv
What timbal start does (that you must replicate)
timbal start is the reference implementation. When self-hosting, reproduce the same wiring:
1. Workforce members
For each workforce/<name>/ with a timbal.yaml:
<fqn> comes from timbal.yaml (e.g. agent.py::agent). The HTTP server exposes:
2. API
3. UI (if present)
4. Cross-service env vars
The API and UI need to know where workforce members live. timbal start injects these — set them yourself when self-hosting:
TIMBAL_START_WORKFORCE uses the _id from each member’s timbal.yaml, not the directory name.
Also pass through model keys and integration secrets (OPENAI_API_KEY, etc.). Locally, timbal start auto-loads <project>/.env and workforce/<name>/.env into each process; when self-hosting you must export or inject those variables yourself (e.g. via your process manager or a secrets store). See Environment variables.
If any of TIMBAL_START_* are missing, platform SDK helpers that resolve service URLs will fail. Mirror what timbal start sets before debugging routing issues.
Production considerations
Process management
Run each component under a supervisor that restarts on crash:
- One process per workforce member
- One for API
- One for UI (if used)
Use health checks against /healthcheck on workforce HTTP servers.
Logging
timbal start multiplexes stdout/stderr into one terminal with per-service prefixes and f/m focus controls. Self-hosted, you need your own approach:
- Separate log files or streams per component
- Structured logging if shipping to Datadog / CloudWatch / etc.
- Correlate by request ID if the API fans out to multiple workforce members
Networking
- Put a reverse proxy (nginx, Caddy, etc.) in front of UI and API for TLS
- Workforce members can stay internal — only the API needs to reach them
- Lock down ports so workforce HTTP servers aren’t exposed publicly
Builds
The scaffold uses bun run dev for API/UI. For production, use whatever production build your scaffolded api/ and ui/ packages define (static UI build + API server, etc.). The workforce side stays uv run -m timbal.server.http with a pinned uv sync environment.
Observability
Platform tracing still works from self-hosted runtimes — configure a tracing provider to export spans to Timbal or your own OTLP endpoint.
When to self-host
Self-hosting makes sense when you need full control over networking, data residency, or custom orchestration. For most teams, the Timbal Platform is less operational overhead — same project layout, no component wiring to maintain.