ORCHD

Deploying

The shape of a deployment

One Linux box:

                    DNS: wildcard A record  *.example.com  ->  box
                                    |
   +-------------------------------- Caddy (:80/:443) --------------------------------+
   |  admin.example.com   -> static admin panel  (+ same-origin /api proxy)           |
   |  api.example.com     -> control API :8080   (API key required)                   |
   |  *.example.com       -> gateway :8081       (Host -> route table -> workload)    |
   |  /w/<key>            -> gateway :8081       (subroute fallback, no DNS needed)   |
   +---------------------------------------------------------------------------------+
                                    |
                        orchd (systemd) + Docker + gVisor

The control API and the gateway both bind to loopback; Caddy is the only listener on a public port. That keeps TLS, HTTP/2 and certificate storage out of the orchestrator, and means a misconfigured firewall cannot expose the control plane directly.

Everything that runs on the box is tracked in the repository under deploy/ — the Caddyfile, both systemd units, and the scripts — so the server holds no untracked code. The only things that live only on the box are the API key file and the tenant data.

What is where

On the boxFrom the repoWhat
/etc/caddy/Caddyfiledeploy/Caddyfilefront door: TLS and routing
/etc/systemd/system/orchd.servicedeploy/orchd.servicethe daemon unit
/etc/systemd/system/caddy.servicedeploy/caddy.serviceCaddy unit
<app>/orchdbuilt from orchestrator/the binary (build artifact)
<app>/admin/admin/ (dist/ deployed)the panel, static
<app>/images/*/Dockerfileorchestrator/images/*workload image sources
<app>/secrets/admin.keynever trackedthe bootstrap API key
<app>/data/never trackedper-workload volumes plus control-plane state

Docker, gVisor (runsc) and the Caddy binary are installed by the bootstrap script from upstream, not tracked as files.

Provisioning a fresh box

# 1. sync files up (the daemon may not start yet — expected)
deploy/deploy.sh root@HOST || true

# 2. install Docker, gVisor and Caddy; generate the key; build images; start services
ssh root@HOST 'bash -s' < deploy/bootstrap.sh

Then point DNS at the box — one wildcard A record covers every workload subdomain — and the first HTTPS request to each host triggers certificate issuance, gated by /internal/tls-allow.

deploy/preflight.sh checks a box's prerequisites before you commit to it.

Deploying updates

deploy/deploy.sh root@HOST

Builds the daemon for linux/amd64, syncs configs, static files and image sources, restarts the daemon, and reloads Caddy in place. Tenant containers keep running across a restart and are re-attached — a deploy is not a fleet-wide outage.

It does not rebuild workload images. If a Dockerfile changed, rebuild it on the box (or build in CI and push to a registry, then pull from the Images page).

deploy/build-template.sh <path> [--push] builds a template's per-workspace images from its manifest — the scripted equivalent of the built image flow.

  • State store: ORCHD_STATE_SQLITE=<data>/orchd.db. Atomic and crash-safe; the JSON file default is fine for development but SQLite is the right answer for a single box. An existing projects.json beside it is migrated on first boot.
  • Backups: point the target at S3/R2 from Settings, and set ORCHD_BACKUP_INTERVAL. On-box backups are not off-box durability.
  • API key: always set ORCHD_API_KEY_FILE. With no key the API is open.
  • Rate limit: set ORCHD_RATE_LIMIT to something finite.
  • Isolation: leave ORCHD_DOCKER_RUNTIME=runsc unless you have measured that you need runc's syscall performance more than you need the boundary.
  • Idle timeout: the default 5 minutes is a reasonable start; workloads that must not cold-start get keep_warm.

Environment reference

Every setting is an environment variable; there is no config file.

Listeners and addressing

VariableDefaultMeaning
ORCHD_API_ADDR127.0.0.1:8080control-plane API listen address
ORCHD_GATEWAY_ADDR127.0.0.1:8081gateway listen address
ORCHD_BASE_DOMAINlvh.mesuffix new routes are minted under, and stripped from an incoming Host
ORCHD_ALT_DOMAINScomma-separated additional base domains this server fronts
ORCHD_PUBLIC_URLexternally reachable base, used to build /w/<key> subroute endpoints
ORCHD_PUBLIC_SCHEMEhttphttps behind Caddy; displayed endpoints then omit the port
ORCHD_PORT_BASE0 (off)enable port-per-workload addressing, counting up from here
ORCHD_LOCALturnkey local defaults (localhost base domain, local public URL)

Substrate

VariableDefaultMeaning
ORCHD_DRIVERlocallocal, docker or mock
ORCHD_IMAGEtinbase:0.10.0default container image for the Docker driver
ORCHD_DOCKER_RUNTIMErunsccontainer runtime; empty means runc
ORCHD_DOCKER_HOSTlocal daemonpoint the Docker client at a remote daemon
ORCHD_TINBASE_BINtinbasethe database executable the process driver spawns
ORCHD_ENGINEdriver defaultdatabase engine selector for the process driver
ORCHD_REGIONlocalthe region id this daemon serves

Lifecycle and limits

VariableDefaultMeaning
ORCHD_IDLE_TIMEOUT5midle time before scale-to-zero; 0 disables the reaper
ORCHD_TINBASE_MEM_MB / ORCHD_TINBASE_CPUS384 / 0.5default caps for database workloads
ORCHD_DEV_MEM_MB / ORCHD_DEV_CPUS512 / 1.0default caps for dev/runner workloads
ORCHD_PIDS_LIMIT512max processes per container
ORCHD_RATE_LIMIT0 (off)control-API requests per key per minute

State, data and templates

VariableDefaultMeaning
ORCHD_DATA_ROOT~/.tinbase-cloudper-workload volumes and control-plane state
ORCHD_STATE_SQLITEpath to a SQLite database for control-plane state (WAL)
ORCHD_STATE_DSNPostgres DSN for control-plane state (takes precedence)
ORCHD_TEMPLATES_DIRscanned at startup; every subdir with an orchd.json is auto-registered
ORCHD_API_KEY_FILEfile holding the bootstrap API key; unset means the API is open

Backups and telemetry

VariableDefaultMeaning
ORCHD_BACKUP_DIR<data-root>/backupslocal backup store root
ORCHD_BACKUP_INTERVAL0 (off)scheduled backup interval, e.g. 24h
ORCHD_BACKUP_RETAIN5snapshots kept per workload
ORCHD_METRICS_INTERVAL60show often the fleet snapshot is published

Backup target, event webhook, metrics sink, registry prefix, instance name and templates are runtime settings, changed from the panel or PUT /v1/settings/* with no redeploy. See Adaptors.

Operating notes

  • Health: GET /healthz is the only unauthenticated status endpoint and never requires a key.
  • Fleet snapshot: GET /v1/info reports the driver, region, base domain, idle timeout, default limits, rate limit, backup and metrics status, and the preset list — the fastest way to confirm what a box is actually running.
  • Instance name: PUT /v1/settings/name names the deployment in the panel. ORCHD is the engine; the name is per instance.
  • Upgrades: the daemon restarting does not stop tenant containers, so a rolling deploy.sh is safe. Changing resource caps applies to containers created afterwards.

from the same team

Related projects

ORCHD is built by the makers of these open-source tools and products.