shipyard

Config reference

Every field in shipyard.yaml. Required fields are flagged; everything else has a sensible default.

Strict mode. Unknown fields are rejected at load time. Misspell health_check as health-check and the deploy refuses to start with the exact YAML line that caused it.

app (required)

app: webhook-relay

Short slug used in log lines and as the default lock-path component. Lowercase alphanumerics with - or _ only. Up to 63 chars.

host (required)

host:
  ssh: ubuntu@1.2.3.4
  identity_file: ~/.ssh/id_ed25519
  release_root: /var/www/webhook-relay
FieldRequiredNotes
sshyesuser@host[:port]. Port defaults to 22. IPv6 supported via user@[::1]:port.
identity_fileyesPath to private key. ~/ is expanded. Encrypted keys are not supported in v0.1 — decrypt with ssh-keygen -p first.
release_rootyesAbsolute path on remote. Must be writable by the SSH user.

artifact (required)

artifact:
  source: ./build/release.tar.gz
  format: tar.gz
FieldRequiredNotes
sourceyesLocal path to the build artifact. Relative paths resolve against the directory of the config file, not the shell’s cwd.
formatautozip or tar.gz. Inferred from the source extension if omitted.

releases

releases:
  keep: 5

Auto-prune retains the most recent keep releases plus the current symlink target (if different). Default 5. Cannot be less than 1.

shared

shared:
  files:
    - .env
  dirs:
    - storage
    - bootstrap/cache

At deploy time, every entry under shared.files and shared.dirs is symlinked from the release dir back to shared/. Use this for anything that must persist between releases (.env, Laravel storage/, uploaded media).

Paths are relative to the release directory. Absolute paths are rejected. If a shared.files target doesn’t exist on the remote when the deploy runs, the deploy fails fast with an actionable message (no silently-created empty .env).

health_check

health_check:
  url: https://my-app.example.com/healthz
  expect: "healthy"
  status: 200
  retries: 10
  delay: 3s
  timeout: 5s
FieldDefaultNotes
urlrequired if block presentMust start with http:// or https://.
expectemptySubstring that must appear in the body. Empty = status check only.
status200HTTP status that counts as healthy.
retries10Number of attempts. Total wall time ≈ retries × (delay + timeout).
delay3sWait between attempts. 3s, 500ms, 1m all parse.
timeout5sPer-request timeout.

If the whole health_check block is omitted, the deploy flips and exits without probing. --skip-health on the deploy command does the same per-invocation — use it sparingly.

Redirects are not followed. Point the URL at the final destination directly. The deploy log surfaces every attempt’s status code so a flapping probe is immediately diagnosable.

hooks

hooks:
  pre_upload:
    - composer install --no-dev --optimize-autoloader
    - npm run build
  post_extract:
    - php artisan migrate --force
    - php artisan config:cache
  post_flip:
    - sudo systemctl reload apache2
  on_rollback:
    - sudo systemctl reload apache2
PhaseWhereCwdWhat it’s for
pre_uploadlocalyour shell’s cwdBuild the artifact.
post_extractremotethe new release dirMigrations, cache warming. Runs before the flip — if it fails, the release dir is deleted and the current symlink never moves.
post_flipremotecurrent/Reload the web server / restart workers. Runs after the flip — if it fails, Shipyard rolls back automatically.
on_rollbackremotecurrent/Cleanup or notification after a rollback (health-fail or post-flip-fail).

Each entry is passed to sh -c on the relevant side. Quotes are linted for balance at load time — an unterminated string is rejected before the deploy starts.

lock

lock:
  enabled: true
  path: /var/www/webhook-relay/shared/.shipyard.lock
  ttl: 10m
FieldDefaultNotes
enabledtrueSet false only if you’re certain about concurrency.
path<release_root>/shared/.shipyard.lockAbsolute path. Must be writable by the SSH user.
ttl10mStale-lock threshold. Minimum 30s. A lock older than ttl is stolen automatically (logged loudly) so a crashed deploy can’t block forever.

Implementation: SFTP O_CREATE|O_EXCL on a small JSON file containing local user, hostname, PID, and acquired-at timestamp. shipyard status displays the holder.


← Quickstart · → CLI reference