Self-host Ship
3 min read
Self-host Ship
Install on a clean VM
./install.sh --host 203.0.113.10 --user root myboxClean VM to a working Ship: provisions the server, generates the secrets that should never be shared between installs, asks for the two only you can supply, builds Ship and deploys. It builds sandbox images only when a sandbox daemon is installed.
The full bring-up — dashboard plus worker plus Nucleus via one
teploy deploy, webhook wiring, the default-deny sandbox, embeddings and
the security model — is in docs/DEPLOY.md in the repository. Read
docs/UPGRADING.md before deploying a new version with runs in flight:
a durable run enqueued under old code and replayed under new is the one
hazard specific to Ship. Measured capacity per box is in
docs/capacity.md.
Join an existing install
A second box joins the Ship you already have rather than becoming another one:
./install.sh --export-secrets ship.env --host <controller> --user <u> oldbox
teploy-ship join http://<controller>:7460 --secrets ship.env \
--nucleus-url postgres://nucleus:<pw>@<controller>:5432/nucleus --startjoin verifies the controller, its token, the store, every sandbox daemon
in the pool, the forge, the model route and the forge co-location gate —
and writes nothing and starts nothing unless all of them answered. It
never fetches credentials over the network; you carry them in the bundle.
Worker environment
| Variable | Effect |
|---|---|
SHIP_MAX_STEPS |
Step budget per run |
SHIP_MAX_CONCURRENT_RUNS |
Concurrency cap on the worker |
SHIP_SANDBOX_TTL_SEC |
Sandbox lifetime |
SHIP_TESTS=1 |
Run the repo's suite after the agent stops, before the push |
SHIP_TELEMETRY=1 |
Post a before/after RED-metrics comparison from Observe on the PR |
SHIP_TESTS picks the suite command from the repo's own entry (Projects
page), else what Ship detected at enqueue (package.json scripts.test, a
Makefile test: target, go.mod, Cargo.toml, pytest), else the worker-wide
SHIP_TEST_COMMAND.
Preview deploys
With SHIP_PREVIEW_DIR set on the worker and SHIP_PREVIEW=1, a run that
opens a PR also builds that branch's image and puts it on a temporary URL,
then comments the link on the PR:
teploy build --json # an image of THIS branch
teploy preview deploy <branch> --ttl 24h --image <tag>Both commands run on the worker host, never in the agent's sandbox:
the CLI holds the credentials that reach your servers, and the sandbox
executes model-authored commands. teploy deploy is never invoked — a
preview must not be able to reach production. A preview that fails is
reported on the pull request and never fails the run.
Telemetry on the pull request
SHIP_TELEMETRY=1 plus OBSERVE_URL, OBSERVE_READ_TOKEN and
OBSERVE_SERVICE posts requests, errors, error rate, p95, p99 and Apdex
over two adjacent windows. The credential is an Observe share token:
GET-only, pinned server-side to its own site, revocable. Below
OBSERVE_MIN_REQUESTS in either window the comment says "not enough data
to compare" — a confident percentage computed from nine requests would
look like proof while being noise.