Ye' Olde Site By Joby

My current Nginx config

Since my last posts about how my stuff is configured I've made some pretty significant changes to my web infrastructure. Some of it is kind of interesting too. I'm now only using my VPS as a reverse proxy, which I then point at a home server.

For a static site like this it really seems to give me the best of both worlds. Most of that is because I've configured the proxy to still serve cached content in the event my home server is unreachable (such as from me doing updates, or outages in my sub-par residential internet). I get the cheap high processing power and easy access of a server that's in the same room as me, but the availability and reliability of a VM in a commercial server farm. Also it means I'm not leaking my home IP address by pointing a public DNS record that's associated with me at it.

So the basic infrastructure is:

  • My home server, in this case it's a LAMP stack VM running on Ubuntu Multipass on a little Dell mini-desktop that I keep under my desk.
  • A $5/month Ubuntu/Nginx VM from DigitalOcean, configured to do reverse proxying and use an auto-renewing wildcard SSL certificate from Let's Encrypt
  • A dynamic DNS domain that shall remain unnamed, which is updated by my home router and used to point a domain name at my home web server
  • I've also stopped using even an open-source outside analytics tool. I had been using Matomo, but my analytics needs are minimal so now I'm just using GoAccess to parse analytics out of the Nginx logs.

Let's Encrypt config

My first step was switching my domain nameservers to DigitalOcean instead of the default nameservers of my registrar. This isn't strictly necessary, but made things a lot easier because unlike my registrar DigitalOcean has a certbot plugin that lets you get a wildcard certificate and automatically update it independently of your web server's configuration.

This is extremely handy and I highly recommend it. You can read more about it in the certbot documentation. I literally just followed the certbot instructions.

Nginx config

I've got two Nginx config files, and they're both pretty straightforward.

The first simply handles redirects, to force SSL and redirect to

server {
    listen 80;
    server_name *;
    return 301 https://$host$request_uri;
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;
    return 301$request_uri;

The second is still a bit more of a work in progress, but it has a bit more to it. Slightly more advanced SSL settings for keeping SSL connections alive, gzip configuration, and proxy settings that are pretty high performance for this particular use case, and also handle HTTP range requests so that I can efficiently stream HTML5 video/audio if I want to.

proxy_cache_path /tmp/ levels=1:2 keys_zone=BYJOBY_COM:10>
server {
    # basic server name
    listen 443 ssl;
    # SSL settings
    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout 70;
    # gzip responses
    gzip on;
    gzip_min_length 1000;
    gzip_comp_level 5;
    gzip_proxied any;
    gzip_vary on;
    # proxy for all content
    location / {
        set $proxy_pass_url;
        proxy_pass $proxy_pass_url;
        proxy_set_header Host $host;
        proxy_buffering on;
        proxy_cache_lock on;
        proxy_cache_lock_age 5s;
        proxy_cache_lock_timeout 5s;
        proxy_cache BYJOBY_COM;
        #proxy_cache_valid 200 206 5m;
        proxy_cache_valid 404 5m;
        proxy_cache_valid 500 5m;
        proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 http_429;
        slice 1m;
        proxy_cache_key $uri$is_args$args$slice_range;
        proxy_set_header Range $slice_range;

The biggest problem I hit was that Nginx caches proxy_pass DNS resolution forever unless you manually specify a DNS server with resolver and put the domain to be resolved in a variable. This was a problem since the web server is on residential internet and the IP changes regularly.

Other than that I mostly just configured this all up straight out of the ngx_http_proxy_module documentation. I also had to change my site's actual CMS to send stale-while-revalidate and stale-if-error fields in the Cache-Control header so that Nginx would keep serving stale copies both when the server is down and while it's updating its own copy.

Happy hacking!

Tags: #nginx #webdev #dns #letsencrypt


Categories: blog posts

Page metadata

Date created
March 1, 2021
Date modified
March 1, 2021
HTML copy built
August 3, 2021, 10:12 pm MDT