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
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
- 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 insudoers. - Queue workers hold the old code in memory. Add
'php artisan queue:restart'topost_deploy. - Disk space.
keep_releasesmultiplies the size of a release (includingvendor/). - 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' => trueon 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