A Simple CI/CD Setup with GitHub Actions for a Static Site

For this site, I use GitHub Actions for CI/CD, and I deliberately kept the setup as simple as possible. This isn’t a site that needs a multi-stage pipeline or approval gates — just enough for a static site with no complex build process.
The flow is just three steps
Build. On every push to main, the workflow runs npm ci && npm run build. Since this site is static (Astro), the build output is just a set of HTML/CSS/JS files — no server-side rendering that needs deploying separately.
Sync to the server. The build output gets synced straight to the VPS over SSH using rsync, via the easingthemes/ssh-deploy GitHub Action. No Docker image to build and push to a registry — just copy the static files to the directory Nginx serves.
Done. No service restart, no database migration step, because there’s neither in this setup.
Compared to the old setup
My old setup for the Laravel version of this site was a lot more involved: build a Docker image, push it to a registry, SSH into the server for docker compose up, wait for the container to come up healthy. Now, push to live takes tens of seconds, not several minutes — and it’s not just about speed, it’s about fewer things that can fail along the way. A Docker image that fails to pull, a registry that’s down, a container stuck restarting — none of those are failure scenarios I have to think about anymore.
What I learned setting this up
Pin third-party Action versions explicitly — @v5.1.2, not just @v5, which sometimes doesn’t even exist as a tag, or can change behavior without me noticing if the maintainer pushes a new version to the same major tag. And always test that the rsync target path is correct before fully relying on the automation — I once got bitten by a one-character typo in the destination path that made the sync “succeed” while the files landed in the wrong directory, and the site never actually updated even though GitHub Actions showed a green check.
For a personal static site, CI/CD doesn’t have to be complicated. Fewer moving parts means fewer things that can break — and it’s also easier to remember how to fix it if something does fail one day, since there are only three steps to debug, not ten.