July 25, 2026 · Updated July 27, 2026
DevOps CI/CD GitHub Actions

Building a CI/CD Pipeline for Static Sites

A practical walkthrough of setting up continuous deployment for a Vite-based portfolio using GitHub Actions, SSH, and rsync — from local dev to production in minutes.

Building a CI/CD Pipeline for Static Sites

Why Automate Deployment?

Every time you push a change, manually building and uploading files to your server is tedious and error-prone. A CI/CD pipeline removes that friction entirely — push to main, and your site is live within minutes.

The best deployment is one you don't have to think about. Automate everything that can be automated.

In this post, I'll walk through how I set up continuous deployment for this portfolio using GitHub Actions, SSH, and rsync.

The Stack

Here's what we're working with:

Component Technology
Framework React + Vite
Language TypeScript
Hosting Hostinger VPS
CI/CD GitHub Actions
Transfer rsync over SSH

The Workflow

1. Trigger on Push

The pipeline runs whenever code is pushed to the main branch:

on:
  push:
    branches:
      - main

2. Build the Project

We install dependencies with Yarn and run the production build:

yarn install --frozen-lockfile
yarn build

This produces a dist/ folder with the optimized static assets.

3. Deploy with rsync

The built files are synced to the server using rsync over SSH:

rsync -avz \
  -e "ssh -i ~/.ssh/key -p $PORT" \
  dist/ \
  user@host:/path/to/public_html

rsync only transfers changed files, making deployments fast and bandwidth-efficient.

Key Decisions

Here's what I considered when setting this up:

  • Yarn over npm — Deterministic installs with --frozen-lockfile ensure CI builds match local builds exactly
  • rsync over FTP — Incremental transfers, SSH encryption, and better reliability
  • GitHub Secrets — SSH keys, host, port, and paths are never committed to the repo

Security Considerations

  1. Generate a dedicated SSH key pair for CI/CD
  2. Add the public key to your server's authorized_keys
  3. Store the private key as a GitHub secret
  4. Use a restricted user account with minimal permissions

The Result

With this setup, the entire flow looks like:

  1. Write code locally
  2. Push to main
  3. GitHub Actions builds the project
  4. rsync deploys to Hostinger
  5. Site is live

The whole process takes under 60 seconds from push to production.

CI/CD pipeline flow

Lessons Learned

Start simple. You don't need Kubernetes to deploy a portfolio. A well-configured rsync pipeline is fast, reliable, and easy to debug.

  • Keep your pipeline fast — cache dependencies, minimize build steps
  • Test locally first — run yarn build before pushing to catch errors early
  • Monitor your deploys — check GitHub Actions logs after each push
  • Use branch protection — prevent direct pushes to main in team settings

That's the entire setup. No Docker, no cloud functions, no over-engineering — just a clean pipeline that gets your code from editor to production reliably.