Manually building and rsyncing a static site for every change is error-prone and slow. This guide covers fully automating the process: push to Git, and the live site updates automatically.
Architecture
git push → CI/CD pipeline (build) → deploy to VPS via rsync/SSH → live site updated
Prerequisites
- A Git repository containing your static site source
- A VPS already configured to serve the built output (see How to Host a Static Website on a VPS with Nginx)
Step 1 — Create a Deployment SSH Key
ssh-keygen -t ed25519 -f deploy_key -C "static-site-deploy" -N ""
Step 2 — Add the Public Key to the VPS
cat deploy_key.pub | ssh deploy@YOUR_SERVER_IP "cat >> ~/.ssh/authorized_keys"
Step 3 — Add Secrets to Your CI/CD Platform
Add DEPLOY_KEY, SERVER_IP, and SERVER_USER as secrets in your GitHub/GitLab repository settings.
Step 4 — Create the Workflow (GitHub Actions Example)
name: Build and Deploy Static Site
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm run build
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts
- name: Deploy via rsync
run: |
rsync -avz --delete -e "ssh -i ~/.ssh/deploy_key" \
./dist/ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:/var/www/mysite/html/
Step 5 — Push and Verify
Push a commit to main and check the Actions tab to watch the build-and-deploy process run automatically.
Adding a Build Verification Step
- name: Check build output exists
run: test -f dist/index.html || exit 1
A simple sanity check preventing deployment of a broken/incomplete build.
Deploying Different Branches to Different Environments
on:
push:
branches: [main, staging]
jobs:
deploy:
steps:
- name: Set deployment target
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "TARGET_PATH=/var/www/mysite/html" >> $GITHUB_ENV
else
echo "TARGET_PATH=/var/www/staging/html" >> $GITHUB_ENV
fi
Adding a Slack/Email Notification on Deployment
- name: Notify on success
if: success()
run: curl -X POST YOUR_NOTIFICATION_WEBHOOK -d "Site deployed successfully"
Alternative: Using rsync from a Self-Hosted Runner
If your build environment (self-hosted runner) already has direct network access to the VPS, deployment can be even simpler without needing to manage a separate deploy key in CI secrets — see How to Set Up a Self-Hosted GitHub Actions Runner on a VPS.
Common Errors
Deployment succeeds but site doesn't update — verify the rsync target path exactly matches Nginx's configured document root.
"Host key verification failed" — the ssh-keyscan step is missing or didn't run successfully; verify Step 4's SSH setup.
Best Practices
- Use
--deletewith rsync to avoid accumulating stale files from removed pages - Add a basic build verification step before deploying
- Use a dedicated deploy key scoped to only this task, not personal credentials
Continue Reading
- How to Host a Static Website on a VPS with Nginx
- How to Build a Simple CI/CD Pipeline with GitHub Actions
- How to Set Up a Deployment User with Restricted SSH Access
Browse more articles in Static Site Hosting & Frontend Deployment.
