Skip to main content
The ssh deployer ships the CI build artifact to your own server with a zero-downtime, symlink-based release layout (the same idea as Envoyer and Capistrano). The server needs a little one-time preparation.

What ends up on the server

A deploy uploads the tested artifact to a new releases/<timestamp> directory, links .env and storage, optionally runs storage:link, migrate --force, optimize and your post_deploy commands, then points current at the new release with an atomic rename. Releases beyond keep_releases (default 5) are pruned, and the previous release is never pruned, so a rollback always has a target.

One-time setup

1

A deploy user

The user must be able to write to the application path. It does not need sudo.
2

A deploy key

Generate a key pair used only for deployment, authorise the public half for the deploy user, and store the private half as the CI secret SSH_PRIVATE_KEY.
3

Known hosts

Slipway uses StrictHostKeyChecking=yes: it will refuse to talk to a server whose key it does not already know. Store the server’s host key as the CI secret SSH_KNOWN_HOSTS:
ssh-keyscan trusts whatever answers at that moment. For production, compare the fingerprint with the one on the server (ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub) before saving it.
4

Production .env

Create it once and never commit it:
The deploy aborts with a clear message if shared/.env is missing.
5

Point the web server at current/public

6

Requirements

PHP on the server, and an mv that supports -T (GNU coreutils; it is used for the atomic switch). Some minimal userlands lack it, so test on the real server.

CI secrets

Different names can be set per environment with the key_secret and known_hosts_secret options. Declare every secret name in the secrets list of config/slipway.php.

Things to know

Rollback does not undo migrations. It only re-points current. Write migrations that the previous release can still run against (add columns before using them, remove them a release later).
  • OPcache / PHP-FPM. Some setups keep serving the old code until PHP-FPM is reloaded. Add a reload to post_deploy, for example 'sudo -n systemctl reload php8.3-fpm', and allow exactly that command for the deploy user in sudoers.
  • Queue workers hold the old code in memory. Add 'php artisan queue:restart' to post_deploy.
  • Disk space. keep_releases multiplies the size of a release (including vendor/).
  • First deploy. There is no previous release, so a failed first deploy cannot roll back and the job fails with a message saying so.
  • Approvals. Set 'approval' => true on production so a human confirms before the artifact is shipped.

Check it before you rely on it

1

Deploy to staging first

Use a throwaway or staging server before production.
2

Break something on purpose

For example make the health-check path return 500 and confirm the previous release comes back and the job fails.
3

Verify from your machine