Docker Compose
Run one Tenant with nylorun start and Docker Compose.
One Tenant, started with nylorun start. Compose runs the Runtime and its
stores. There are no replicas.
npx nylorun start --tenant app --no-openProvision
Install Node 24 and Docker Compose v2. A running Tenant uses about 1.2 GB, most of it Restate.
npx nylorun start --tenant app --no-open
npx nylorun status--no-open skips the browser. Print a Studio login later with
npx nylorun studio --no-open.
Reverse proxy
nylorun start publishes the Runtime on 127.0.0.1 only. Put a TLS reverse
proxy on the same machine:
| Rule | Why |
|---|---|
Listen with TLS; forward to 127.0.0.1:<port> | The application key travels on every request. |
Rewrite Host to localhost:<port> | The Runtime answers 421 to any other Host. |
Forward only /health, /ready, and /v1/* | Nothing else is the Tenant API. |
| Never proxy the Admin API, Studio, or Restate | Admin is on its own port (8788). Answer /v1/admin/* with 403 anyway. |
| Do not buffer responses | Event streams stay open with a keepalive every 15 seconds. |
Pass Authorization and Nylorun-* through | Your app sets those headers. |
runtime.example.com {
@admin path /v1/admin /v1/admin/*
handle @admin {
respond "Blocked by the reverse proxy" 403
}
@api path /health /ready /v1/*
handle @api {
reverse_proxy 127.0.0.1:8787 {
header_up Host localhost:8787
flush_interval -1
}
}
handle {
respond 404
}
}| Placement | Certificate |
|---|---|
| Same LAN | Tailscale, or a local CA (tls internal) whose root the app server trusts. Never plain HTTP. |
| Internet | A public certificate. Prefer a private path (VPN or the same network) over a public endpoint. |
Firewall so only the proxy port and your SSH port are reachable.
App server
On the app machine:
eval "$(npx @nylorun/cli env)"| Variable | Value |
|---|---|
NYLORUN_RUNTIME_URL | The proxy URL, https://runtime.example.com. |
NYLORUN_SERVER_KEY | The application key nylo env prints. Never the admin key. |
NYLORUN_ACTIONS_URL | A URL the Runtime's machine can reach. |
Register the Action endpoint at that URL. See Action endpoints and Serve your users.
Operate
| Service | Role |
|---|---|
runtime | Tenant API and scheduling. |
gateway | Model and tool calls. Holds provider keys. |
harness | Turns, stdio MCP, and workspaces. |
studio | Operator dashboard on loopback. |
postgres | Session record. |
restate | Session advancement. |
s2-lite | Event history. |
rustfs | File bytes. |
npx nylorun status
npx nylorun logs runtime -f
curl -sS http://127.0.0.1:8787/health
curl -sS http://127.0.0.1:8787/readyGET /health reports version, protocol range, and features. GET /ready
checks the listener, Tenant, Postgres, Restate, and s2; it answers 503
until they are ready.
The Admin API listens on 127.0.0.1:8788 (GET /v1/admin/status,
GET /v1/admin/openapi.json). Leave it on the machine.
Backups
Back up the Postgres and RustFS volumes together with keys/vault-kek. Stored
credentials cannot be read without the vault key.
nylorun stop keeps volumes. nylorun reset deletes this Tenant's data.
Upgrades
Upgrade nylorun and run start. It refuses to run an older Runtime than the
Tenant last ran (--allow-downgrade overrides).
Your own Postgres
Needs wal_level=logical, at least two replication slots, and a role with
REPLICATION plus read access to nylorun_streams. A local Tenant starts
Postgres with those settings already.