Documentation
Everything you need to deploy with Ship.
Prerequisites
- macOS or Linux
- SSH key (ed25519 recommended):
ssh-keygen -t ed25519 - Docker (for default deploy flow)
- A Dockerfile or ship.json in your project root
- Cloud provider API token
ship server create
Provision a new Ubuntu 22.04 server with Docker pre-installed. Your SSH key is automatically registered with the provider. State is saved to .ship/server.json and the machine-wide inventory at ~/.ship/servers.json.
# Use defaults
ship server create --provider digitalocean
# Custom options
ship server create --provider hetzner --region fsn1 --size cx22 --image ubuntu-24-04-x64Flags
--provider— digitalocean, hetzner, or vultr (required)--region— override default region--size— override default instance size--image— override default OS image
ship server list
Show all servers tracked in your machine-wide inventory at ~/.ship/servers.json. Displays provider, IP, region, and project path for each server.
ship server listship server destroy
Tears down the server at the cloud provider and removes all local state files (.ship/server.json, releases, runtime config). Also removes the entry from the machine-wide inventory.
ship server destroyship deploy
Build and deploy your application to the provisioned server. If a ship.json deploy config exists, Ship runs your custom local commands, uploads files, and executes remote commands. Otherwise it uses the default Docker flow: build image locally, upload via SSH, and run the container.
ship deployCustom Deploy Flow
Define a ship.json with local build commands, file uploads, and remote commands.
{
"deploy": {
"local_commands": ["npm ci", "npm run build"],
"uploads": [{
"source": "dist.tar.gz",
"destination": "/opt/app/release.tar.gz",
"mode": "0644"
}],
"remote_commands": [
"cd /opt/app && tar -xzf release.tar.gz",
"pm2 restart app"
],
"cleanup_local": ["dist.tar.gz"]
}
}ship status
Report the health of your server and application. Checks SSH reachability, app container status, healthcheck endpoint result, and last release timestamp. Configure the healthcheck path in ship.json.
$ ship status
SSH_REACHABLE=true
APP_STATUS=running
HEALTHCHECK=ok
LAST_RELEASE=2026-03-14T10:30:00ZConfiguration
{
"status": {
"healthcheck_path": "/"
}
}ship logs
Fetch the last 100 lines of logs from the application container on your server. Useful for quick debugging without SSHing in manually.
ship logsship exec
Run an arbitrary command on your remote server over SSH. The command runs as the configured SSH user and returns stdout/stderr.
ship exec "docker ps"
ship exec "df -h"
ship exec "cat /var/log/syslog | tail -50"ship rollback
Restore a previous release. Ship tracks every deploy in .ship/releases.json. Rollback re-uploads the previous release artifact and re-runs the remote commands from that release.
# List available releases
ship release list
# Roll back to the previous release
ship rollbackship secrets
Manage environment secrets locally in .ship/secrets.env (mode 0600) and sync them to your server.
# Add a secret
ship secrets set DATABASE_URL=postgres://...
# List secrets
ship secrets list
# Sync to server
ship secrets syncship domain setup
Configure a Caddy reverse proxy with automatic TLS certificates. Point your DNS to the server IP first, then run the command.
ship domain setup --domain example.com --port 3000Or configure via ship.json:
{
"proxy": {
"domains": ["example.com", "www.example.com"],
"app_port": 3000
}
}ship init
Generate a starter ship.json configuration file. Choose from built-in templates for common project types.
ship init --template docker
ship init --template node
ship init --template go
ship init --template staticship bootstrap
Apply packages, proxy configuration, and setup commands defined in your ship.json to the server. Runs automatically on ship server create if a bootstrap config exists, or can be run manually.
ship bootstrapConfiguration
{
"bootstrap": {
"packages": ["nodejs", "pm2"],
"commands": ["npm install -g pm2"]
}
}Output Format
Ship outputs machine-friendly KEY=VALUE pairs by default, ideal for AI agents. Use --json for structured JSON output.
$ ship server create --provider digitalocean
STATUS=SERVER_CREATED
SERVER_ID=12345
SERVER_IP=1.2.3.4
$ ship server create --provider digitalocean --json
{"status":"SERVER_CREATED","server_id":"12345","server_ip":"1.2.3.4"}