# Ship Ship turns a VPS into a self-hosted git server with a web frontend — similar to running cgit on your own domain. Visiting your base domain in a browser shows a cgit repo index; clicking through shows trees, commit logs, diffs, and blame. Public repos are cloneable over HTTPS. If you host Go code, `go get` works with your domain out of the box. This is the read-only, public-facing side, and it works exactly the way cgit users expect. The difference is what happens on the write side. When you `git push` over SSH, Ship doesn't just update the bare repo — it builds and deploys your code. A post-receive hook checks out the repo, runs `docker build`, installs a systemd service and Caddy reverse-proxy config, and restarts the app. Your deployment config (the systemd unit, the Caddyfile) lives in `.ship/` in your repo and is versioned alongside your code. Push to main and it's live; push to any other branch and nothing happens. Not every repo needs to be a running service. If there's no Dockerfile, the push is accepted but the deploy step is skipped — the repo just sits there as a browsable, cloneable library. This makes Ship useful for Go modules that only need vanity imports and a public source view, alongside apps that need the full build-and-deploy pipeline. The same base domain serves both. Ship also supports direct deploys (SCP a binary or rsync a static directory) for cases where git push isn't the right fit. Ship is a client-side CLI. All state lives on your laptop at `~/.config/ship/state.json`. The VPS is configured entirely over SSH — no agent or daemon runs on the server. ## Install ``` go install github.com/bdw/ship/cmd/ship@latest ``` Or build from source: ``` go build -o ship ./cmd/ship ``` ## Quick start ### 1. Set up the VPS ``` ship host init --host user@your-vps --base-domain example.com ``` This installs Caddy, Docker, git, fcgiwrap, and cgit. It creates a `git` user for push access, configures sudoers for deploy hooks, and enables automatic HTTPS. The host becomes the default for subsequent commands. ### 2. Deploy **Git push (Docker-based app):** ``` ship init myapp git add .ship/ Dockerfile git commit -m "initial deploy" git push origin main ``` **Git push (static site):** ``` ship init mysite --static git add .ship/ index.html git commit -m "initial deploy" git push origin main ``` **Git push (library / Go module):** ``` ship init mylib --public git add . git commit -m "initial" git push origin main ``` No Dockerfile, so nothing is deployed — the repo is just browsable and cloneable at `https://example.com/mylib`. **Direct (pre-built binary):** ``` GOOS=linux GOARCH=amd64 go build -o myapp ship --binary ./myapp --domain api.example.com ``` You can version control `.ship/` or add it to `.gitignore` — it's your choice. ## Commands ### `ship init ` Create a bare git repo on the VPS and generate local `.ship/` config files. ``` ship init myapp # Docker-based app ship init mysite --static # static site ship init myapp --domain custom.example.com # custom domain ship init mylib --public # publicly cloneable (for go get) ``` ### `ship deploy ` Manually rebuild and deploy a git-deployed app. ### `ship [deploy flags]` Deploy a pre-built binary or static directory directly. ``` ship --binary ./myapp --domain api.example.com ship --binary ./myapp --domain api.example.com --env DB_HOST=localhost ship --static --dir ./dist --domain example.com ship --name myapi --memory 512M --cpu 50% ``` Flags: `--binary`, `--static`, `--dir`, `--domain`, `--name`, `--env`, `--env-file`, `--args`, `--file`, `--memory`, `--cpu` ### `ship list` List all deployments on the default host. ### `ship status/logs/restart/remove ` Manage a deployment's systemd service. ### `ship env` ``` ship env list myapp ship env set myapp KEY=VALUE ship env unset myapp KEY ``` ### `ship host` ``` ship host init --host user@vps --base-domain example.com ship host status ship host update ship host ssh ``` ### `ship ui` Launch a local web UI for viewing deployments. ## VPS file layout ``` /srv/git/.git/ # bare git repos /srv/git/.git/hooks/post-receive # auto-deploy hook /var/lib//src/ # checked-out source (for docker build) /var/lib//data/ # persistent data volume /var/www// # static site files /etc/systemd/system/.service # systemd unit /etc/caddy/sites-enabled/.caddy # per-app Caddy config /etc/caddy/sites-enabled/ship-code.caddy # base domain Caddy config /etc/cgitrc # cgit configuration /etc/ship/env/.env # environment variables /etc/sudoers.d/ship-git # sudo rules for git user /opt/ship/vanity/index.html # vanity import template /home/git/.ssh/authorized_keys # SSH keys for git push ``` ## Supported platforms VPS: Ubuntu 20.04+ or Debian 11+ ## Security See [SECURITY.md](SECURITY.md) for the threat model, mitigations, and known gaps. ## License MIT