Available for self-hosted Business plan and above
Teable Agent Runtime provides the sandbox and app runtime services used by AI Chat and App Builder. This guide deploys the complete stack on a single Linux server with Docker Compose.
The deployment includes the AI sandbox engine, App Runtime, git repository service, artifact storage, and TLS gateway. Kubernetes and an additional source repository are not required because every configuration file is included below.
Self-hosted Agent Runtime is still in an early stage. This guide is intended for early adopters and will continue to evolve based on deployment feedback. The current runtime uses OpenSandbox through Teable Infra and does not use Vercel Sandbox or Vercel snapshots. For deployment assistance, contact support@teable.ai.
Use the complete stack when you need App Builder previews and deployed apps. Running only opensandbox-server does not provide the app runtime, git registry, artifact storage, or gateway required by App Builder.
Architecture
Only the Caddy gateway exposes ports 80 and 443 to the public network. All other services stay inside internal Docker networks.
| Service | Description | Internal port |
|---|
| caddy | TLS termination and routing for the console, sandbox and app previews, S3, and git | Public 80/443 |
| opensandbox-server | AI sandbox engine in Docker mode. It uses the host docker.sock to create sandbox containers on demand. | 8090 |
| infra-service | Console UI, Infra API, App Runtime Docker backend, and built-in app gateway | 8080 |
| git-registry | Git smart-http service for App Builder. It uses the same image as infra-service. | 8080 |
| minio (optional) | Built-in S3-compatible artifact storage. Can be replaced with external S3. See Choose Artifact Storage. | 9000 / 9001 |
| minio-init (optional) | One-time task that waits for MinIO to become ready and creates the artifact bucket | N/A |
Domain routes are derived from the root BASE_DOMAIN.
| Address | Purpose |
|---|
https://<BASE_DOMAIN> | Console UI, Infra API, and sandbox engine API under /v1/* |
https://{appId}.app.<BASE_DOMAIN> | Entry point for deployed apps |
https://{sandboxId}-{port}.sandbox.<BASE_DOMAIN> | Sandbox port preview |
https://s3.<BASE_DOMAIN> | Artifact storage in built-in MinIO mode. Presigned URLs point here. |
https://git.<BASE_DOMAIN> | Git smart-http endpoint, optional for manual external clone |
Before You Begin
Server Requirements
| Minimum | Recommended |
|---|
| vCPU | 4 | 8 |
| Memory | 8 GB | 16 GB |
| Disk | 80 GB NVMe | 120+ GB NVMe |
| OS | Ubuntu 22.04/24.04 (x86_64) | Ubuntu 22.04/24.04 (x86_64) |
| Software | Docker Engine 24+, Docker Compose v2.24+, OpenSSL | Docker Engine 24+, Docker Compose v2.24+, OpenSSL |
Capacity notes: each active build session runs one sandbox container with a limit of 2 vCPU and 4 GiB. Each deployed app also has a limit of 2 vCPU and 4 GiB, though typical usage is only a few hundred MB. The base services use about 1 to 1.5 GiB of memory. Disk usage mainly comes from container images, about 15 to 20 GB after warm-up, plus writable layers for sandboxes and apps. Monitor free disk space.
DNS and Firewall
Add 4 A records at your DNS provider. All records must point to the server public IP. A wildcard certificate only covers one subdomain level, so all 4 records are required.
If the domain is hosted on Cloudflare, set these 4 records to DNS only (gray cloud), not Proxied (orange cloud).
Only allow inbound 22 (SSH), 80, and 443 in the firewall. Do not expose other ports.
Container Images
This deployment uses GHCR + Docker Hub by default. All images are public and do not require docker login. For Teable images, <tag> is not a fixed value. Open each corresponding GHCR package page and use the release tag shown in that package page’s Installation command. Confirm the tag for each image separately. Do not assume the tags are the same across images.
Images Managed by Docker Compose
These images are pulled and started by docker compose up.
| Purpose | Image template | Package page |
|---|
Console, Infra API, and App Runtime. infra-service and git-registry use the same image. The latter only uses a different startup entry point. | ghcr.io/teableio/teable-infra-service:<tag> | GHCR |
| AI sandbox engine, OpenSandbox in Docker runtime mode, Teable build | ghcr.io/teableio/opensandbox-server:<tag> | GHCR |
| TLS edge gateway. The official image is used for static certificate mode. Cloudflare mode requires a local build, see Choose a TLS Mode. | caddy:2.9.1 | Docker Hub |
| Built-in artifact storage, only used in built-in MinIO mode. Pinning by digest is recommended for production. | minio/minio:latest | Docker Hub |
| One-time bucket creation tool, only used in built-in MinIO mode | minio/mc:latest | Docker Hub |
Runtime Images
These images are not started by compose directly. The services use the host docker.sock to create containers from them on demand. They are public images and can be pulled anonymously by the Docker daemon. Pre-pulling them as described in Pre-pull Runtime Images is recommended to avoid first-use latency when creating the first sandbox or deploying the first app.
| Purpose | Image template | Package page |
|---|
| Sandbox base image. Each AI build session runs inside this image. | ghcr.io/teableio/teable-sandbox-agent:<tag> | GHCR |
| App runtime base image. Each deployed app container uses this image. Apps cannot be deployed if this is not configured. | ghcr.io/teableio/teable-app-runtime:<tag> | GHCR |
Sandbox execution agent execd, injected by the engine into each sandbox container | ghcr.io/teableio/opensandbox-execd:v1.0.19-fix-1064 | GHCR |
| Sandbox outbound network sidecar, egress in DNS mode, created by the engine for each sandbox as needed | opensandbox/egress:v1.0.12 | Docker Hub |
Use the Teable-built fixed version of execd shown above, opensandbox-execd:v1.0.19-fix-1064. Do not replace it with the upstream opensandbox/execd image.
Choose Artifact Storage
| Mode | Configuration | Notes |
|---|
| Built-in MinIO (default) | Leave S3_ENDPOINT empty in .env, keep COMPOSE_PROFILES=minio | MinIO starts automatically and the bucket is created. Presigned URLs use https://s3.<BASE_DOMAIN>. |
| External S3 | Set S3_ENDPOINT to the provider URL and set COMPOSE_PROFILES= to empty | Built-in MinIO no longer starts. S3_ACCESS_KEY, S3_SECRET_KEY, and S3_BUCKET must use provider-issued values. The bucket must already exist. If the provider only supports virtual-host style, set S3_FORCE_PATH_STYLE=false. |
Create the Deployment Files
Deployment Directory
Create a deployment directory on the server. This guide uses teable-runtime/ as the example directory. The Configuration Files section contains the full contents of the first four files.
The files containing secrets are .env and compose.override.yaml. Do not share them externally or commit them to a repository.
Configuration Files
.env
compose.yaml
Copy this file as is. All environment-specific values are loaded from .env.
Caddyfile
The file is written for static certificate mode by default. For cloudflare mode, make the two changes described in the file header and under Choose a TLS Mode.
opensandbox.toml
Copy this file as is.
Deploy Agent Runtime
Edit the .env file from Configuration Files. Required items:
BASE_DOMAIN / INFRA_HOST: your root domain. INFRA_HOST is usually the same as BASE_DOMAIN.
- Images: fill the image list under Container Images. For each Teable image, copy the
<tag> from the Installation command on that image’s GHCR package page.
- Secrets: generate and fill them with the commands below.
Choose a TLS Mode
| Mode | Preparation | Certificate renewal |
|---|
| static (self-provided certificate, default) | Put fullchain.pem and privkey.pem into certs/. The certificate must be a single multi-SAN certificate covering <BASE>, *.<BASE>, *.app.<BASE>, and *.sandbox.<BASE>, and the private key must match it. Wildcards cover only one level. | Manual. Replace files in certs/, then run docker compose exec caddy caddy reload -c /etc/caddy/Caddyfile. |
| cloudflare (DNS-01 automatic issuance) | DNS must be hosted on Cloudflare. Prepare an API token with Zone:Read + DNS:Edit permissions. | Fully automatic through Caddy |
static mode: the configuration files above are already written for this mode. Put the certificate files in place. No other change is needed.
Use the following commands to check certificate SAN coverage and whether the certificate matches the private key:
cloudflare mode requires 4 changes:
-
The official Caddy image does not include the DNS plugin. Save the following content as
Dockerfile.caddy and build it locally:
-
In
.env, set CADDY_IMAGE=teable-caddy-cloudflare:2.9.1, and fill ACME_EMAIL and CLOUDFLARE_API_TOKEN.
-
In
Caddyfile, follow the file header and uncomment the global block, including email and acme_dns cloudflare.
-
In
Caddyfile, delete the tls /certs/... line inside the (site_tls) snippet. Certificates will be managed automatically by ACME.
In Cloudflare mode, the caddy-data volume must be persistent. It stores certificates and the ACME account. If it is lost, Caddy will request certificates again after rebuilds, which can trigger Let’s Encrypt rate limits.
Generate the Git Service Signing Key
The git service uses an Ed25519 key pair to sign and verify access tokens. Multi-line PEM values cannot be stored cleanly in .env, so they are injected through compose.override.yaml, which Docker Compose loads automatically.
Run this in the deployment directory:
The generated compose.override.yaml will have this structure. The PEM content is your generated key:
To rotate the key, run this section again.
If openssl genpkey reports Algorithm ed25519 not found, for example on macOS with LibreSSL, use Docker to generate the key pair, then run the same assembly command above:
Create the Shared Workspace Volume
The Agent shared workspace uses an external volume. Since compose declares it as external, compose will not create or delete it automatically.
Pre-pull Runtime Images
All images are public. docker login is not required.
The execd and egress image addresses must exactly match the values configured in opensandbox.toml.
Start the Services
Verify the Deployment
Check Service Health
Console UI: open https://<BASE_DOMAIN> in a browser, or the host configured in INFRA_HOST. Log in with api-key. The key is the OPENSANDBOX_API_KEY value in .env.
Connect Teable
Add these environment variables to the Teable deployment:
Use the same value for TEABLE_INFRA_API_KEY as OPENSANDBOX_API_KEY in the Agent Runtime .env file. The SANDBOX_OPENSANDBOX_IMAGE value must also match the sandbox image configured for Agent Runtime.
TEABLE_INFRA_API_URL must point to the Teable Infra root URL without a path. Restart Teable after updating the variables.
Troubleshooting
| Problem | What to check |
|---|
| Teable reports that Agent Runtime is not configured | Confirm all four Teable environment variables above are set, then restart Teable. |
| Sandbox or app previews return DNS, TLS, or 404 errors | Confirm all four DNS records point to the server and the certificate covers every required hostname. |
| The first sandbox or app deployment is slow | Pre-pull all runtime images before the first use. |
| A service is unhealthy | Run docker compose ps, then inspect the affected service with docker compose logs <service>. |
If you need deployment assistance, contact support@teable.ai and include the output of docker compose ps and the relevant service logs.
Operations
View Logs and Manage Services
Upgrade
Update the image tags in .env, then run docker compose pull && docker compose up -d.
After updating the sandbox or app base image, or execd / egress, pre-pull the images again as described in Pre-pull Runtime Images.
Back Up Data
Back up these volumes regularly, especially minio-data and caddy-data.
| Volume | Content |
|---|
opensandbox-state | Sandbox engine state, SQLite |
infra-state | App Runtime state and drafts |
git-registry-data | Git repository data |
minio-data | Artifact files, built-in MinIO mode |
teable-agent-juicefs | Agent shared workspace, external volume created during deployment |
caddy-data / caddy-config | TLS certificates, ACME account, and Caddy configuration |
docker compose down -v deletes data volumes too, including artifacts, Git repositories, and certificates. Use it carefully.
Security and Limitations
Security
- The only files containing secrets are
.env and compose.override.yaml. Do not commit them to a repository or share them externally.
- The whole stack uses one shared
OPENSANDBOX_API_KEY. If you need separate permissions, replace the corresponding environment variables for each service separately.
docker.sock is mounted into opensandbox-server and infra-service. This is required for the Docker backend and is equivalent to host root access. Deploy only on a dedicated and trusted host.
- The only public entry point is Caddy on ports 80 and 443. The MinIO console on 9001 is not exposed. Use an SSH tunnel if access is needed.
- Sandboxes share the host kernel. This is not a strong multi-tenant isolation boundary. For public multi-tenant scenarios, configure a stronger isolation runtime for the sandbox engine, such as gVisor or Kata.
Capability Boundaries
Available: full sandbox engine functionality; the main app lifecycle, including create, activate, gateway access, delete, dashboard, logs, and S3 artifacts; git push and pull; console api-key login and Infra API; file browser and S3-compatible API.
Unavailable or limited due to Docker mode tradeoffs: app host-prefix rename returns 501; scale-to-zero idle scaling is a no-op; engine key rotation and server rolling upgrade are not supported; Kubernetes observability pages in the console are empty, which is expected.