Self-hosted runtime
Run a Botyard bot's runtime in your own Kubernetes cluster: how it connects, what it needs, what happens while it is offline, and who can use it.
A self-hosted bot is a Botyard bot whose runtime, botyardd, runs in your Kubernetes cluster
instead of on Botyard's infrastructure. It has the same chat, schedules and skills as a hosted
bot, and most of the same tools; the few that aren't available yet are listed under
Known limitations. You use and manage it in the Botyard app as usual.
The exception is tools that act on the runtime's own host, such as reading files or starting processes. Which host tools the bot is offered depends on what it is assigned in Botyard, not on the runtime. The runtime's local host policy decides what it will actually perform, and a default install's empty policy performs none: an assigned host tool can still be offered, but the runtime refuses the call and audits it. The Host policy and security page in this section covers this.
Enabled per organization
The self-hosted runtime is available only to organizations that Botyard has enabled. If your organization doesn't offer a self-hosted option when you create a bot, contact Botyard to request access. Kubernetes is the only supported platform today. Linux VM and macOS installs are not yet available.
In this section
| Page | What it covers |
|---|---|
| Install on Kubernetes | Install the Helm chart, verify the signed image and chart, and configure a proxy or private registry. |
| Enrollment | Enrollment tokens, how the device identity works, and replacing or moving a device. |
| Host policy and security | What the runtime may do on your cluster, the pod's security posture, and audit logs. |
| Operations | Status, upgrades, lost volumes, uninstalling, and troubleshooting. |
How it works
- Outbound-only control plane. For its own control-plane traffic, the runtime opens HTTPS
and WebSocket (WSS) connections to Botyard and listens on no network port for Botyard, so it
needs no Service, Ingress or inbound firewall rule. This covers the runtime's own transport
only. Commands it starts through
exec, and services it supervises, can open listeners and connect on other ports, and having no Service or Ingress does not stop direct connections to the Pod IP. Use the chart's NetworkPolicy (off by default) or your own ingress controls. - No model credentials in your cluster. The runtime sends model requests to Botyard's model broker over its authenticated connection. Botyard makes the provider call with the LLM credential configured in Botyard, so no provider key is stored in your cluster.
- Secrets on demand. When a bot needs a secret from its Runtime Vault, the runtime requests a short-lived lease from Botyard over the same connection. The bot's secrets aren't copied into your cluster's configuration.
- Device identity. You install the runtime with a single-use enrollment token, minted on the bot's page in Botyard. On first start, the runtime enrolls and creates a device key on its persistent volume. From then on, that key identifies the runtime. The volume is the device: if you lose it, you revoke the device in Botyard and enroll again. The Enrollment page in this section covers this in detail.
Botyard allows one active device per bot, so a bot runs as exactly one replica.
Requirements
In Botyard
- Your organization is enabled for the self-hosted runtime.
- An LLM provider credential, added under User menu › Settings › Credentials › LLM Providers or on User menu › Settings › Bots › ‹your bot› › Credentials, before the bot's first turn. Without one, every turn fails with "No credential is configured for provider scope 'llm'". The app can show the bot as ready even when no credential exists, so don't rely on that as a check.
Cluster and tools
- Kubernetes 1.25 or later.
- Helm 3.8 or later. The chart is published to an OCI registry.
- A storage class that can provision a ReadWriteOnce persistent volume.
- The pod runs under the
restrictedPod Security Standard. It runs as a non-root user with a read-only root filesystem and no privilege escalation.
Resources (chart defaults, all adjustable)
| Resource | Default |
|---|---|
| Replicas | 1 (fixed) |
| Persistent volume | 10Gi, ReadWriteOnce |
| CPU request | 250m |
| Memory request / limit | 512Mi / 2Gi |
Scratch space (/tmp) | 1Gi |
Network egress (HTTPS, TCP 443)
| Destination | Used for |
|---|---|
api.botyard.io | Enrollment and session setup |
runtime.botyard.io | The runtime's live connection (WSS): chat, tools, model calls and secret leases |
hel1.your-objectstorage.com and botyard-api.hel1.your-objectstorage.com | File transfers through presigned URLs |
ghcr.io | Pulling the image and chart, unless you mirror them to your own registry |
The runtime also needs DNS. If your egress goes through a proxy, the runtime supports an HTTP
CONNECT proxy with NO_PROXY exceptions, and can trust an extra CA bundle for TLS-inspecting
proxies. The Install on Kubernetes page in this section covers the settings.
When the runtime is offline
A self-hosted bot can only work while its runtime is connected. If the pod is stopped, restarting or has lost its network:
- Chat. Botyard waits a few seconds for the runtime to reconnect. If it doesn't, your message is not sent. Instead, a card under it says The bot's machine is offline, with when the runtime was last seen. Choose Retry once the runtime is back.
- Scheduled messages and awakes. Botyard keeps trying to deliver the message for a reconnect window: the schedule's own wait, or 3 minutes if it sets none, up to a maximum of 1 hour. For a recurring schedule, the window also ends when the next occurrence is due, whichever comes first. If the runtime is back within the window, the run happens late. If not, the run is recorded as missed and isn't caught up later, even when the schedule is set to Run once when it's back.
- Scheduled commands are not retried. A command that falls due while the runtime is offline is missed.
- The bot itself is unaffected. It stays enrolled and authorized. On the bot's page, its device shows as offline with when it was last seen. When the runtime reconnects, it picks up new messages and runs normally.
Known limitations
- Kubernetes only. Linux VM and macOS installs are not yet available.
- No high availability. A bot runs as one replica. Restarts are covered by the runtime reconnecting, not by failover.
- Enrollment token only. Workload identity federation (for example IRSA or service account OIDC) is not supported yet, and the device key is stored on the volume rather than in a KMS or TPM.
- No customer SPIRE mesh. Don't inject a SPIRE socket (
SPIFFE_ENDPOINT_SOCKET) into the runtime pod. The runtime would treat it as Botyard's hosted identity path and fail to connect. - No self-update. You upgrade by changing the chart and image version you pin.
- No background services or Bot Pages. The bot can't register or supervise long-running
services on the runtime (the
service_*tools), and it can't publish a Bot Page from it.
Hosting apps
Run web apps inside a Botyard bot and share them through authenticated Bot Page URLs: persistent hosting, temporary previews, Streamlit, WebSockets, and caching.
Install on Kubernetes
Install a self-hosted Botyard bot on Kubernetes: verify the signed image and chart, keep the enrollment token in a Secret, run helm install, check it is online.