Self-hosting a tiny static site with nginx
This site used to be a single index.html. It is now a few dozen HTML files produced by a Python script, and that's about as complicated as I want it to get. Here is the whole setup, mostly so that I remember it next time.
The build
There is no framework. A ~300-line build.py reads Markdown files with a tiny front matter block, renders them into one HTML template and writes everything into dist/. It also packs project tarballs and makes thumbnails for the gallery. The only dependency is Pillow.
I tried Hugo and liked it, but every time I came back after six months the theme had changed its config format. A script I wrote myself doesn't do that.
Deploying
Deploy is rsync to a VPS with a backup of the previous version:
ssh host "rsync -a /var/www/site/ /root/site-backups/site-$(date +%F-%H%M)/"
rsync -rlt --delete --chmod=D755,F644 dist/ host:/var/www/site/
Rollback is the same command in the other direction. I keep the last ten backups; the whole site is a few dozen megabytes, mostly images.
nginx
The server block is short. The interesting part is cache policy:
location / {
try_files $uri $uri/ =404;
}
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~* \.(jpg|png|webp|tar\.gz)$ {
expires 30d;
}
The stylesheet URL contains a hash of its content (style.css?v=1a2b3c4d), so it can be cached forever: when the file changes, the URL changes. HTML is not cached at all, which is fine, it is tiny.
Things I'd tell myself a year ago
try_files $uri $uri/ =404plus directories withindex.htmlgive you clean URLs for free. No rewrite rules.- Turn on
http2and TLS 1.3 and forget about it. There is nothing to tune for a site this size. - Add a proper
404.htmlanderror_page 404 /404.html;. The default nginx error page is ugly and tells everyone your exact nginx version. server_tokens off;while you're at it.- A single-vCPU box with 2 GB of RAM serves static files faster than you'll ever need. The bottleneck is the uplink, not nginx.
That's it. Boring, which is the point.