Ship on hook. One webhook, one command. Receive a POST → git pull → run your deploy script. Configure the deployment via YAML or env vars. No SaaS, no containers. Just Node and your repo.
Built for indie devs, micro-SaaS, and open-source projects that want simple, self-hosted deploys.
npm install -g shiphookcd /path/to/your/repo
shiphookBy default Shiphook listens on port 3141. Send a POST to trigger a deploy:
curl -X POST http://localhost:3141/It runs git pull in the repo, then your script (default: npm run deploy). Response is JSON with pull and run output.
From your repo root, run:
shiphook deployFor every webhook-triggered deploy (and shiphook deploy), Shiphook writes a log file into:
.shiphook/logs/<id>.json(machine-readable).shiphook/logs/<id>.log(human-readable)
The server response includes log: { id, json, log } so you can correlate a request to a file.
GitHub requires an HTTPS payload URL. Shiphook listens on HTTP locally; use nginx + Let’s Encrypt (Certbot) in front.
On Linux (Debian/Ubuntu or RHEL-family: AlmaLinux, Rocky, RHEL, CentOS, Fedora, …), after DNS points your domain at the server:
- The first time you run plain
shiphookin an interactive terminal, it asks if you want HTTPS setup; sayyto run it (installs nginx/TLS,shiphook.serviceon systemd, prints your webhook secret, then exits — the server keeps running under systemd). Or runshiphook setup-httpsanytime. - You will be prompted for domain, email (Let’s Encrypt), local Shiphook port, and webhook path. The installer configures nginx, obtains a certificate, and enables Certbot auto-renew (
certbot.timerwhen available).
Non-interactive services: set SHIPHOOK_SKIP_HTTPS_PROMPT=1 so the server starts without prompting (HTTPS setup is skipped).
Details: HTTPS (nginx + Certbot) (docs).
- No vendor lock-in — Your server, your script, your Git. No third-party deploy service.
- YAML or env — Put
shiphook.yamlin your repo (or set env vars). Env overrides file. Run and point your Git webhook at it. - Fits your stack — Use
npm run deploy,pnpm build,./deploy.sh, or anything else. - Secret-based auth (required) — The server always requires a secret. Set
SHIPHOOK_SECRET(orsecret:inshiphook.yaml), or omit it and the CLI will auto-generate one and persist it to.shiphook.secret. Send it asX-Shiphook-SecretorAuthorization: Bearer <secret>.
Add a shiphook.yaml in your repo (see shiphook.example.yaml) or set env vars. Env overrides the file.
| Option | Default | Description |
|---|---|---|
port / SHIPHOOK_PORT |
3141 |
Server port. |
repoPath / SHIPHOOK_REPO_PATH |
current dir | Repo path for git pull and script. |
runScript / SHIPHOOK_RUN_SCRIPT |
npm run deploy |
Command run after pull. |
secret / SHIPHOOK_SECRET |
— | Required for auth. If omitted, the CLI auto-generates and persists one in .shiphook.secret. |
path / SHIPHOOK_PATH |
/ |
Webhook path (e.g. /deploy). |
- Repo → Settings → Webhooks → Add webhook.
- Payload URL:
https://your-domain.example/(or your path). Use nginx + Certbot in front of Shiphook (shiphook setup-httpson Linux); do not use plainhttp://for GitHub. - Secret: Same as
SHIPHOOK_SECRET/.shiphook.secret. - Events: Push events.
- Save. Every push triggers a deploy.
Full docs (install, config, webhooks, programmatic API): Documentation
import { createShiphookServer, ensureWebhookSecret, loadConfig } from "shiphook";
const config = loadConfig();
await ensureWebhookSecret(config);
const server = createShiphookServer(config);
await server.start();MIT.