DevOps

Zero-Downtime Deploys on a Single VPS

A boring, reliable deploy pipeline for a Laravel site on one VPS: atomic releases, health checks, cached config and a rollback that takes ten seconds.

Prima Puspita Prima Puspita CPO & Co-Founder · Business Analyst Lead 2 min read 1,275 views
Zero-Downtime Deploys on a Single VPS

You do not need Kubernetes to deploy a personal site without downtime. A release directory, a symlink swap and a health check are enough, and the whole thing fits in a script you can read in one sitting.

Atomic releases

Each deploy clones into `releases/<timestamp>`, installs dependencies, builds assets and only then switches the `current` symlink. PHP-FPM keeps serving the previous release until the swap, which is a single atomic operation.

Key points

  • Never build on the server you serve from; build in CI and ship artifacts.
  • Migrations must be backwards compatible with the release still running.
  • Cache config, routes and views after every deploy.
  • Keep the queue worker under supervisor and restart it on release.

Health checks before the swap

The script runs migrations with `--force`, warms the config, route and view caches and hits a local health endpoint. If anything fails the new release is deleted and the old one is never touched.

Zero-Downtime Deploys on a Single VPS
Illustration for “Zero-Downtime Deploys on a Single VPS”

Example in code

#!/usr/bin/env bash
set -euo pipefail

release="/var/www/site/releases/$(date +%Y%m%d%H%M%S)"
git clone --depth 1 git@github.com:example/site.git "$release"

cd "$release"
composer install --no-dev --optimize-autoloader --no-interaction
npm ci && npm run build
php artisan migrate --force
php artisan optimize

ln -sfn "$release" /var/www/site/current
sudo systemctl reload php8.4-fpm

Rolling back

Because releases are directories, a rollback is just pointing the symlink at the previous one and reloading PHP-FPM. Keeping the last five releases costs a few hundred megabytes and has saved an evening more than once.

The deploy script is boring on purpose; excitement belongs in the product, not the pipeline.

Takeaways

Downtime is usually a symbol of a deploy that mutates the running release. Build somewhere else, swap atomically and keep the last few releases around.

Share
Prima Puspita

Written by

Prima Puspita

CPO & Co-Founder at kuliahkemana.com and Business Analyst Lead with a decade in banking, insurance and SaaS. I turn messy requirements into products people enjoy using.