Static site generators (Astro, Hugo, Jekyll) produce plain HTML/CSS/JS at build time — extremely fast to serve and simple to host, requiring no application server at runtime. This guide covers deploying any of them to your VPS.
Why Static Site Generators
- Exceptional performance — no server-side rendering per request
- Minimal attack surface — no application code running in production
- Simple hosting requirements — just a web server serving files
Step 1 — Build the Site Locally or in CI
For Astro:
npm run build
For Hugo:
hugo --minify
For Jekyll:
bundle exec jekyll build
Each produces a static output directory (dist, public, or _site depending on the tool).
Step 2 — Transfer the Built Files
rsync -avz --delete ./dist/ deploy@YOUR_SERVER_IP:/var/www/mysite/html/
--delete removes files on the server that no longer exist in the new build, keeping deployments clean.
Step 3 — Configure Nginx
See How to Host a Static Website on a VPS with Nginx for the base server block configuration — static site generator output works identically to any other static HTML.
Automating the Build-and-Deploy Process
Combine your CI/CD pipeline (see How to Build a Simple CI/CD Pipeline with GitHub Actions) with the rsync step above, so pushing to your main branch automatically builds and deploys:
- name: Build site
run: npm run build
- name: Deploy
run: |
rsync -avz --delete -e "ssh -i ~/.ssh/deploy_key" \
./dist/ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:/var/www/mysite/html/
Handling Redirects (Common in Migrated Sites)
location /old-path {
return 301 /new-path;
}
For a large number of redirects, consider a map file instead of many individual location blocks:
map $uri $redirect_uri {
/old-page-1 /new-page-1;
/old-page-2 /new-page-2;
}
server {
if ($redirect_uri) {
return 301 $redirect_uri;
}
}
Handling Trailing Slashes Consistently
rewrite ^/(.*)/$ /$1 permanent;
Ensures URLs are consistent (either always with or without a trailing slash), avoiding duplicate content issues for SEO.
Setting Up a Sitemap and robots.txt
Most static site generators can produce these automatically as part of the build — verify they're included in the deployed output and reference the correct production domain.
Incremental Builds for Large Sites (Hugo/Jekyll)
For sites with thousands of pages, full rebuilds can become slow — check whether your generator supports incremental builds to speed up the CI pipeline, particularly relevant as content volume grows.
Common Errors
404 on routes that should exist — verify the build actually generated the expected HTML files; check the build output structure matches what Nginx's root is pointing to.
Old content still showing after deployment — browser caching; verify cache headers, and confirm the rsync --delete flag actually removed stale files on the server.
Best Practices
- Always use
--deletewith rsync to avoid accumulating stale files - Automate the build-and-deploy process via CI/CD rather than manual uploads
- Set long cache expiration on hashed/versioned assets, shorter for HTML pages themselves
Continue Reading
- How to Host a Static Website on a VPS with Nginx
- How to Set Up Automatic Static Site Deployment from Git
- How to Build a Simple CI/CD Pipeline with GitHub Actions
Browse more articles in Static Site Hosting & Frontend Deployment.
