Deploying GitHub CMS to a VPS involves three steps: server setup (Ubuntu + nginx + SSL), configuring GitHub Secrets for secure SSH access, and setting up a GitHub Actions workflow for automatic deployment on push to main. Total setup time: 15-20 minutes.
Deployment Architecture
The deployment pipeline follows a simple flow: git push → GitHub Actions → build → rsync → nginx. Each push triggers a build that generates static HTML with JSON-LD, Open Graph, sitemap, and RSS, then rsyncs the result to the VPS. Zero-downtime deployment is achieved through symlink swapping.
Step 1: Server Setup (Ubuntu + nginx + SSL)
- Provision a VPS — any provider: DigitalOcean ($6/mo), Hetzner ($4/mo), Vultr ($6/mo)
- Install nginx:
sudo apt update && sudo apt install nginx -y - Configure nginx — create a server block for your domain with gzip, caching, and security headers
- Install SSL:
sudo apt install certbot python3-certbot-nginx -y && sudo certbot --nginx -d yourdomain.com - Create deploy directory:
sudo mkdir -p /var/www/githubcms && sudo chown $USER:$USER /var/www/githubcms
Step 2: GitHub Secrets
Add these secrets to your repository (Settings → Secrets and variables → Actions):
SSH_HOST— your VPS IP addressSSH_USERNAME— SSH user (usuallyrootor a deploy user)SSH_PRIVATE_KEY— the private SSH key for authentication
Step 3: GitHub Actions Workflow
The workflow runs on push to main: checkout → setup Node.js → npm ci → build → rsync to VPS → health check. The full workflow takes 2-3 minutes including build time.
Best Practices
- Use symlink swap for zero-downtime: deploy to
/var/www/githubcms/releases/{timestamp}, then update symlink - Enable gzip in nginx for text assets (HTML, CSS, JS, JSON, XML)
- Set cache headers: 30 days for static assets, 1 hour for HTML
- Monitor with health checks: the workflow validates the site responds with HTTP 200 after deployment
Summary
GitHub CMS deployment is fully automated through GitHub Actions. Once configured, any push to main triggers a complete rebuild and deploy with zero manual steps. The static output through nginx achieves TTFB ≤200ms, faster than any dynamic CMS.