Probably the Cat
, 2 min read
My blog lives on a NAS in a cabinet at home. Now, when the house goes dark, the site doesn't.
This blog runs on a NAS in a cabinet at home. That's the point of it, and also its weak spot. If the power goes, the internet drops or I restart the wrong container, the site just vanishes, and visitors get a Cloudflare error page explaining that a tunnel they've never heard of is broken.
So I spent an evening teaching it to fall over gracefully.
A small container on the NAS makes a static copy of the site and uploads it to Cloudflare Pages. A Cloudflare Worker sits in front of christingeorge.com and passes every visitor straight through to home, as before. If home doesn't answer, it serves the copy instead. Readers keep reading. The only things that stop are the ones that need the server, which means comments, newsletter signups and me logging in. All of it runs on Cloudflare's free tier.
Getting there took a few wrong turns.
The first upload failed because Cloudflare's upload tool wanted to write temporary files into a folder I'd mounted read-only. My mistake, one-line fix.
The copy was supposed to refresh whenever I published, using a Ghost webhook. Ghost refused to send it, first because site-mirror didn't look like a real web address, and then, once I gave it a name that did, because the address pointed somewhere private inside my network. That second refusal is Ghost being sensible, since webhooks aimed at internal addresses are a classic way to poke around someone else's network. So the mirror now asks instead of waiting to be told. Ghost's sitemap records when each post last changed, and every five minutes the mirror reads it. If anything has changed, it refreshes the copy, and nothing on the network has to be opened up for it.
Then came the first real test. I stopped Ghost, loaded the site, and got the error page anyway. The Worker wasn't running at all. I had set its route to *.christingeorge.com/*, which covers every subdomain I own and not the site itself. One asterisk and a dot.
Testing had its own trap. At home, Pi-hole sends my domain straight to the NAS without going near Cloudflare, so from my own Wi-Fi I'd never see the backup, however broken home was. The real tests had to come from my phone on mobile data, or from curl told to ask Cloudflare's DNS instead of mine.
When it finally worked, the answer came back as a plain 200 with one extra header, x-served-from: backup-copy.
During an outage, the site now says so. A note at the top reads "Home server's down, probably the cat." and the ticker in the footer turns red. That line isn't entirely a joke. The NAS lives in a closed cabinet because of the cat, and cat hair still gets in through the cable hole. My uptime now depends on Cloudflare's global network and one cat's shedding schedule.