Self-host Ship

3 min read

Self-host Ship

Install on a clean VM

./install.sh --host 203.0.113.10 --user root mybox

Clean 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 --start

join 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.