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.The CLI does not build a container image. You bring your own process manager (systemd, supervisord, Kubernetes, etc.) and production build pipeline.
cd workforce/<name>uv syncuv run -m timbal.server.http --port <port> --import_spec <fqn>
<fqn> comes from timbal.yaml (e.g. agent.py::agent). The HTTP server exposes:
POST http://localhost:<port>/run # collect (returns final OutputEvent)POST http://localhost:<port>/stream # SSE event streamGET http://localhost:<port>/healthcheck
An Agent also exposes /voice, /voice/ws, and /voice/rtc. Install timbal[server,voice] for browser voice and WebRTC, or add voice-livekit for LiveKit rooms. Voice connections are long-lived: configure WebSocket upgrades, connection timeouts, and the appropriate media networking in your reverse proxy. See Voice transports for carrier routes and ICE/TURN configuration.
The API and UI need to know where workforce members live. timbal start injects these — set them yourself when self-hosting:
Variable
Example
Purpose
TIMBAL_START_WORKFORCE
a1b2c3d4-...:4455,b5c6d7e8-...:4456
Manifest _id → port map (comma-separated)
TIMBAL_START_API_PORT
3000
API port (for services that call back to API)
TIMBAL_START_UI_PORT
3737
UI port
PORT
per-service
Port each Bun service binds to
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.
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.
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.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Timbal","colors":{"primary":"#000000","light":"#ffffff","dark":"#000000"},"logo":{"light":"https://mintcdn.com/timbaltechsl/pt3LfpScmY2Go19A/logo/light-small-1.svg?fit=max\u0026auto=format\u0026n=pt3LfpScmY2Go19A\u0026q=85\u0026s=fd26b0ce39e9e46d6dd08d81b611a9ea","dark":"https://mintcdn.com/timbaltechsl/pt3LfpScmY2Go19A/logo/dark-small-1.svg?fit=max\u0026auto=format\u0026n=pt3LfpScmY2Go19A\u0026q=85\u0026s=5739e93ab19cd4f38a7794d947cb547f"},"favicon":"https://mintcdn.com/timbaltechsl/SFKYoQkLzl5EA6mF/favicon.png?fit=max\u0026auto=format\u0026n=SFKYoQkLzl5EA6mF\u0026q=85\u0026s=426b0689f2269536b56cad9d7b4a8b2f","api":{"openapi":"api-reference/openapi.json"},"navbar":{"primary":{"type":"github","href":"https://github.com/timbal-ai/timbal"}},"footer":{"socials":{"website":"https://timbal.ai","github":"https://github.com/timbal-ai","linkedin":"https://linkedin.com/company/timbal-ai"}},"styling":{"codeblocks":"dark","latex":false},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"timbaltechsl","hasAudioNarration":false,"actualSubdomain":"timbaltechsl","customDomains":["docs.timbal.ai"],"gitSource":{"type":"github","owner":"timbal-ai","repo":"timbal","deployBranch":"main","contentDirectory":"docs","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae231c7fdcdc020a5fca4a3","collectionId":"8adbc99a-3b4b-43e6-8b0b-20828dd5e854","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae231c7fdcdc020a5fca4a3"},"entitlements":{},"buildId":"6ae231c7fdcdc020a5fca4a3","clientVersion":"0.0.4054","searchFilterCounts":[{"language":"default","tag":"API Reference","count":210},{"language":"default","tag":"Docs","count":56},{"language":"default","tag":"Organizations","count":54},{"language":"default","tag":"Projects","count":45},{"language":"default","tag":"Knowledge Bases","count":36},{"language":"default","tag":"Agents","count":31},{"language":"default","tag":"Examples","count":29},{"language":"default","tag":"Model Reference","count":28},{"language":"default","tag":"Connectors","count":26},{"language":"default","tag":"Evals","count":22}]},"assistantConfig":{"enableStarterQuestions":false},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"deployment/self-hosted","slug":"/deployment/self-hosted","pageMetadata":{"title":"Self-Hosted","description":"Run Timbal projects on your own infrastructure","href":"/deployment/self-hosted"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Run Timbal projects on your own infrastructure\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Self-hosting means you run the same three layers a `,_jsx(_components.code,{children:`timbal create`}),` project contains — `,_jsx(_components.strong,{children:`UI`}),`, `,_jsx(_components.strong,{children:`API`}),`, and `,_jsx(_components.strong,{children:`workforce`}),` — without `,_jsx(_components.code,{children:`timbal start`}),` managing them. You own process lifecycle, port allocation, env wiring, restarts, and log aggregation.`]}),`\n`,_jsx(_components.p,{children:`The CLI does not build a container image. You bring your own process manager (systemd, supervisord, Kubernetes, etc.) and production build pipeline.`}),`\n`,_jsx(Heading,{level:`2`,id:`prerequisites`,children:`Prerequisites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A project created with `,_jsx(_components.a,{href:`/quickstart#create-a-timbal-project`,children:_jsx(_components.code,{children:`timbal create`})})]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://bun.sh`,children:`Bun`}),` for `,_jsx(_components.code,{children:`api/`}),` and `,_jsx(_components.code,{children:`ui/`})]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://docs.astral.sh/uv/`,children:`uv`}),` for workforce Python deps`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`timbal[server]`}),` installed in each workforce member’s venv`]}),`\n`]}),`\n`,_jsxs(Heading,{level:`2`,id:`what-timbal-start-does-that-you-must-replicate`,children:[`What `,_jsx(_components.code,{children:`timbal start`}),` does (that you must replicate)`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`timbal start`}),` is the reference implementation. When self-hosting, reproduce the same wiring:`]}),`\n`,_jsx(Heading,{level:`3`,id:`1-workforce-members`,children:`1. Workforce members`}),`\n`,_jsxs(_components.p,{children:[`For each `,_jsx(_components.code,{children:`workforce/\u003cname>/`}),` with a `,_jsx(_components.code,{children:`timbal.yaml`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`cd`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` workforce/`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`nam`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`e`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`uv`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` sync`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`uv`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#569CD6`,\"--shiki-dark\":`#569CD6`},children:` -m`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` timbal.server.http`}),_jsx(_components.span,{style:{color:`#569CD6`,\"--shiki-dark\":`#569CD6`},children:` --port`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`por`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`t`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`> `}),_jsx(_components.span,{style:{color:`#569CD6`,\"--shiki-dark\":`#569CD6`},children:`--import_spec`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`fq`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`n`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`\u003cfqn>`}),` comes from `,_jsx(_components.code,{children:`timbal.yaml`}),` (e.g. `,_jsx(_components.code,{children:`agent.py::agent`}),`). The HTTP server exposes:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#C586C0`,\"--shiki-dark\":`#C586C0`},children:`POST`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` http://localhost:\u003cport>/run # collect (returns final OutputEvent)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#C586C0`,\"--shiki-dark\":`#C586C0`},children:`POST`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` http://localhost:\u003cport>/stream # SSE event stream`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#C586C0`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` http://localhost:\u003cport>/healthcheck`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`An Agent also exposes `,_jsx(_components.code,{children:`/voice`}),`, `,_jsx(_components.code,{children:`/voice/ws`}),`, and `,_jsx(_components.code,{children:`/voice/rtc`}),`. Install `,_jsx(_components.code,{children:`timbal[server,voice]`}),` for browser voice and WebRTC, or add `,_jsx(_components.code,{children:`voice-livekit`}),` for LiveKit rooms. Voice connections are long-lived: configure WebSocket upgrades, connection timeouts, and the appropriate media networking in your reverse proxy. See `,_jsx(_components.a,{href:`/voice/transports`,children:`Voice transports`}),` for carrier routes and ICE/TURN configuration.`]}),`\n`,_jsx(Heading,{level:`3`,id:`2-api`,children:`2. API`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`cd`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` api`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`bun`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` install`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#9CDCFE`,\"--shiki-dark\":`#9CDCFE`},children:`PORT`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`=\u003c`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`api_port`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`> `}),_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`bun`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` dev`}),_jsx(_components.span,{style:{color:`#6A9955`,\"--shiki-dark\":`#6A9955`},children:` # dev; use your production start command in prod`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`3-ui-if-present`,children:`3. UI (if present)`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`cd`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` ui`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`bun`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` install`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`bun`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` dev`}),_jsx(_components.span,{style:{color:`#569CD6`,\"--shiki-dark\":`#569CD6`},children:` --port`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`ui_por`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:`t`}),_jsx(_components.span,{style:{color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},children:`> `}),_jsx(_components.span,{style:{color:`#6A9955`,\"--shiki-dark\":`#6A9955`},children:`# dev; use your production build/serve in prod`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`4-cross-service-env-vars`,children:`4. Cross-service env vars`}),`\n`,_jsxs(_components.p,{children:[`The API and UI need to know where workforce members live. `,_jsx(_components.code,{children:`timbal start`}),` injects these — set them yourself when self-hosting:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Variable`}),_jsx(_components.th,{children:`Example`}),_jsx(_components.th,{children:`Purpose`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`TIMBAL_START_WORKFORCE`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`a1b2c3d4-...:4455,b5c6d7e8-...:4456`})}),_jsxs(_components.td,{children:[`Manifest `,_jsx(_components.code,{children:`_id`}),` → port map (comma-separated)`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`TIMBAL_START_API_PORT`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`3000`})}),_jsx(_components.td,{children:`API port (for services that call back to API)`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`TIMBAL_START_UI_PORT`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`3737`})}),_jsx(_components.td,{children:`UI port`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`PORT`})}),_jsx(_components.td,{children:`per-service`}),_jsx(_components.td,{children:`Port each Bun service binds to`})]})]})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`TIMBAL_START_WORKFORCE`}),` uses the `,_jsx(_components.code,{children:`_id`}),` from each member’s `,_jsx(_components.code,{children:`timbal.yaml`}),`, not the directory name.`]}),`\n`,_jsxs(_components.p,{children:[`Also pass through model keys and integration secrets (`,_jsx(_components.code,{children:`OPENAI_API_KEY`}),`, etc.). Locally, `,_jsx(_components.code,{children:`timbal start`}),` auto-loads `,_jsx(_components.code,{children:`\u003cproject>/.env`}),` and `,_jsx(_components.code,{children:`workforce/\u003cname>/.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 `,_jsx(_components.a,{href:`/deployment#environment-variables`,children:`Environment variables`}),`.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`If any of `,_jsx(_components.code,{children:`TIMBAL_START_*`}),` are missing, platform SDK helpers that resolve service URLs will fail. Mirror what `,_jsx(_components.code,{children:`timbal start`}),` sets before debugging routing issues.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`production-considerations`,children:`Production considerations`}),`\n`,_jsx(Heading,{level:`3`,id:`process-management`,children:`Process management`}),`\n`,_jsx(_components.p,{children:`Run each component under a supervisor that restarts on crash:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`One process per workforce member`}),`\n`,_jsx(_components.li,{children:`One for API`}),`\n`,_jsx(_components.li,{children:`One for UI (if used)`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Use health checks against `,_jsx(_components.code,{children:`/healthcheck`}),` on workforce HTTP servers.`]}),`\n`,_jsx(Heading,{level:`3`,id:`logging`,children:`Logging`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`timbal start`}),` multiplexes stdout/stderr into one terminal with per-service prefixes and `,_jsx(_components.code,{children:`f`}),`/`,_jsx(_components.code,{children:`m`}),` focus controls. Self-hosted, you need your own approach:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Separate log files or streams per component`}),`\n`,_jsx(_components.li,{children:`Structured logging if shipping to Datadog / CloudWatch / etc.`}),`\n`,_jsx(_components.li,{children:`Correlate by request ID if the API fans out to multiple workforce members`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`networking`,children:`Networking`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Put a reverse proxy (nginx, Caddy, etc.) in front of UI and API for TLS`}),`\n`,_jsx(_components.li,{children:`Workforce members can stay internal — only the API needs to reach them`}),`\n`,_jsx(_components.li,{children:`Lock down ports so workforce HTTP servers aren’t exposed publicly`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`builds`,children:`Builds`}),`\n`,_jsxs(_components.p,{children:[`The scaffold uses `,_jsx(_components.code,{children:`bun run dev`}),` for API/UI. For production, use whatever production build your scaffolded `,_jsx(_components.code,{children:`api/`}),` and `,_jsx(_components.code,{children:`ui/`}),` packages define (static UI build + API server, etc.). The workforce side stays `,_jsx(_components.code,{children:`uv run -m timbal.server.http`}),` with a pinned `,_jsx(_components.code,{children:`uv sync`}),` environment.`]}),`\n`,_jsx(Heading,{level:`3`,id:`observability`,children:`Observability`}),`\n`,_jsxs(_components.p,{children:[`Platform tracing still works from self-hosted runtimes — configure a `,_jsx(_components.a,{href:`/core-concepts/tracing`,children:`tracing provider`}),` to export spans to Timbal or your own OTLP endpoint.`]}),`\n`,_jsx(Heading,{level:`2`,id:`when-to-self-host`,children:`When to self-host`}),`\n`,_jsxs(_components.p,{children:[`Self-hosting makes sense when you need full control over networking, data residency, or custom orchestration. For most teams, the `,_jsx(_components.a,{href:`/deployment/platform`,children:`Timbal Platform`}),` is less operational overhead — same project layout, no component wiring to maintain.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":"dark","config":{},"pageMetadata":{"title":"Self-Hosted","description":"Run Timbal projects on your own infrastructure","href":"/deployment/self-hosted"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Prerequisites","slug":"prerequisites","depth":2,"children":[]},{"title":"What timbal start does (that you must replicate)","slug":"what-timbal-start-does-that-you-must-replicate","depth":2,"children":[{"title":"1. Workforce members","slug":"1-workforce-members","depth":3,"children":[]},{"title":"2. API","slug":"2-api","depth":3,"children":[]},{"title":"3. UI (if present)","slug":"3-ui-if-present","depth":3,"children":[]},{"title":"4. Cross-service env vars","slug":"4-cross-service-env-vars","depth":3,"children":[]}]},{"title":"Production considerations","slug":"production-considerations","depth":2,"children":[{"title":"Process management","slug":"process-management","depth":3,"children":[]},{"title":"Logging","slug":"logging","depth":3,"children":[]},{"title":"Networking","slug":"networking","depth":3,"children":[]},{"title":"Builds","slug":"builds","depth":3,"children":[]},{"title":"Observability","slug":"observability","depth":3,"children":[]}]},{"title":"When to self-host","slug":"when-to-self-host","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"timbaltechsl","siteName":"Timbal","title":"Self-Hosted - Timbal","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-28T13:57:08.839Z","originalFileLocation":"deployment/self-hosted.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Run Timbal projects on your own infrastructure\">\u003cmeta data-mint-head name=\"application-name\" content=\"Timbal\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Self-Hosted - Timbal\">\u003cmeta data-mint-head property=\"og:description\" content=\"Run Timbal projects on your own infrastructure\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Timbal\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.timbal.ai/deployment/self-hosted\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://timbaltechsl.mintlify.app/_mintlify/api/og/v2?division=Deployment\u0026amp;title=Self-Hosted\u0026amp;description=Run+Timbal+projects+on+your+own+infrastructure\u0026amp;theme=259c386eb829de58cc6638f3\u0026amp;signature=246386539c79e8e3a73e8388724f1d5dd66c6327646f4c180280ce3668d14f39\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Self-Hosted - Timbal\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Run Timbal projects on your own infrastructure\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://timbaltechsl.mintlify.app/_mintlify/api/og/v2?division=Deployment\u0026amp;title=Self-Hosted\u0026amp;description=Run+Timbal+projects+on+your+own+infrastructure\u0026amp;theme=259c386eb829de58cc6638f3\u0026amp;signature=246386539c79e8e3a73e8388724f1d5dd66c6327646f4c180280ce3668d14f39\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/timbaltechsl/HA5uMpfE6Se4k3W2/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Timbal\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#000000\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.timbal.ai/deployment/self-hosted\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/deployment/self-hosted.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.timbal.ai/#organization\",\"name\":\"Timbal\",\"url\":\"https://docs.timbal.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/timbaltechsl/pt3LfpScmY2Go19A/logo/light-small-1.svg?fit=max\u0026auto=format\u0026n=pt3LfpScmY2Go19A\u0026q=85\u0026s=fd26b0ce39e9e46d6dd08d81b611a9ea\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.timbal.ai#website\",\"name\":\"Timbal\",\"url\":\"https://docs.timbal.ai\",\"publisher\":{\"@id\":\"https://docs.timbal.ai/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.timbal.ai/deployment/self-hosted#webpage\",\"url\":\"https://docs.timbal.ai/deployment/self-hosted\",\"name\":\"Self-Hosted\",\"description\":\"Run Timbal projects on your own infrastructure\",\"dateModified\":\"2026-10-28T13:57:08.839Z\",\"isPartOf\":{\"@id\":\"https://docs.timbal.ai#website\"},\"breadcrumb\":{\"@id\":\"https://docs.timbal.ai/deployment/self-hosted#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.timbal.ai/deployment/self-hosted#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Deployment\",\"item\":\"https://docs.timbal.ai/deployment/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Self-Hosted\",\"item\":\"https://docs.timbal.ai/deployment/self-hosted\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.timbal.ai/deployment/self-hosted#article\",\"headline\":\"Self-Hosted\",\"name\":\"Self-Hosted\",\"description\":\"Run Timbal projects on your own infrastructure\",\"url\":\"https://docs.timbal.ai/deployment/self-hosted\",\"mainEntityOfPage\":{\"@id\":\"https://docs.timbal.ai/deployment/self-hosted#webpage\"},\"dateModified\":\"2026-10-28T13:57:08.839Z\",\"publisher\":{\"@id\":\"https://docs.timbal.ai/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.timbal.ai#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Timbal\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Timbal","nav":{"global":null,"tabs":[{"tab":"Docs","groups":[{"group":"Getting started","pages":[{"title":"Introduction","href":""},{"title":"Installation","href":"/installation"},{"title":"Quickstart","href":"/quickstart"}]},{"group":"Core Concepts","pages":[{"title":"Runnables","href":"/core-concepts/runnables"},{"title":"Events \u0026 Streaming","href":"/core-concepts/events"},{"title":"Tracing \u0026 Observability","href":"/core-concepts/tracing"},{"title":"Context \u0026 State Management","href":"/core-concepts/context"}]},{"group":"Agents","pages":[{"title":"Agents","sidebarTitle":"Overview","href":"/agents/index"},{"title":"Adding Tools","href":"/agents/tools"},{"title":"MCP Servers","href":"/agents/mcp"},{"title":"Structured Output","href":"/agents/structured-output"},{"title":"Memory","href":"/agents/memory"},{"title":"Memory Compaction","href":"/agents/memory-compaction"},{"title":"Guardrails","href":"/agents/guardrails"},{"title":"Skills","href":"/agents/skills"},{"title":"Dynamic Agents","href":"/agents/dynamic"},{"title":"Background Tasks","href":"/agents/background-tasks"},{"title":"Commands","href":"/agents/commands"}]},{"group":"Voice Agents","pages":[{"title":"Voice Agents","href":"/voice/index"},{"title":"Your First Voice Agent","href":"/voice/quickstart"},{"group":"Conversation","pages":[{"title":"Greetings","href":"/voice/greetings"},{"title":"Using Tools","href":"/voice/tools"},{"title":"Thinking Sounds","href":"/voice/thinking-sounds"},{"title":"Spoken Fillers","href":"/voice/fillers"},{"title":"Background Audio","href":"/voice/background-audio"},{"title":"Turn-Taking and Interruptions","href":"/voice/turn-taking"},{"title":"Silence and Timeouts","href":"/voice/silence"}]},{"group":"Connecting and operating","pages":[{"title":"Recording Calls","href":"/voice/recording"},{"title":"Voice Transports","href":"/voice/transports"},{"title":"Voice Events and Usage","href":"/voice/observability"}]},{"group":"Reference and extensions","pages":[{"title":"Providers and Configuration","href":"/voice/configuration"},{"title":"Custom Voice Pipelines","href":"/voice/custom-pipelines"}]}]},{"group":"Workflows","pages":[{"title":"Workflows","sidebarTitle":"Overview","href":"/workflows/index"},{"title":"Control Flow","href":"/workflows/control-flow"},{"title":"Branching","href":"/workflows/branching"},{"title":"Errors \u0026 Failure","href":"/workflows/errors-and-failure"},{"title":"Agents \u0026 LLMs","href":"/workflows/agents-and-llms"},{"title":"Human in the Loop","href":"/workflows/human-in-the-loop"}]},{"group":"Human in the Loop","pages":[{"title":"Human-in-the-loop","sidebarTitle":"Overview","href":"/human-in-the-loop/index"},{"title":"Approval gates","href":"/human-in-the-loop/approval-gates"},{"title":"Suspend \u0026 interaction tools","href":"/human-in-the-loop/suspend"},{"title":"Resuming a paused run","href":"/human-in-the-loop/resuming"},{"title":"Client integration (HTTP)","href":"/human-in-the-loop/client-integration"},{"title":"Observability","href":"/human-in-the-loop/observability"}]},{"group":"Evals","pages":[{"title":"Evals","sidebarTitle":"Overview","href":"/evals/index"},{"title":"Writing Evals","href":"/evals/writing-evals"},{"group":"Validators","pages":[{"title":"Validators","sidebarTitle":"Overview","href":"/evals/validators/index"},{"title":"Comparison Validators","href":"/evals/validators/comparison"},{"title":"Type Validators","href":"/evals/validators/type"},{"title":"Length Validators","href":"/evals/validators/length"},{"title":"LLM Validators","href":"/evals/validators/llm"},{"title":"Flow Validators","href":"/evals/validators/flow"}]},{"title":"Running Evals","href":"/evals/running-evals"}]},{"group":"Deployment","pages":[{"title":"Deployment","sidebarTitle":"Overview","href":"/deployment/index"},{"title":"Timbal Platform","description":"Deploy Timbal projects to managed hosting","href":"/deployment/platform"},{"title":"Self-Hosted","href":"/deployment/self-hosted"}]}]},{"tab":"Examples","pages":[{"title":"Examples","href":"/examples"}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/introduction"}]},{"tab":"Model Reference","pages":[{"title":"Model Reference","href":"/models/overview"}]},{"tab":"MCP Integration","pages":[{"title":"MCP Integration","href":"/mcp-integration"}]}]},"basePath":"","title":"Self-Hosted - Timbal","buildId":"dpl_345ReqzYaAjzS9QpeJemsKdb7KDj","deploymentId":"dpl_345ReqzYaAjzS9QpeJemsKdb7KDj","dynamics":[],"chunks":[]}