Maintenance Page
I will be relocating my servers again in the next few months. These servers host this blog, a couple websites, my Fediverse server, and various internal services. My internal services will simply be down during this process, but for the external-facing services, I wanted something a little more elegant. Namely, a proper maintenance page.
One of the challenges to self-hosting is managing hardware. Unlike using a cloud service (VPS) or a dedicated hosting provider, when I unplug my hardware, I disappear from the internet.
This is exactly what I did the last time I needed to relocate my server. I disappeared for a while, then I reappeared later.
Granted, I’m not hosting anything critical. I doubt anyone even noticed the last time I took everything offline. But I noticed, and since this the purpose of this all is learn and challenge myself, I wanted to do better.
Offsite Server?
My first thought was to host something on my offsite server. I’m lucky enough to have a family member who allows me to keep a small backup server on their network, so spinning up an ngnix instance with a simple “Down for Maintenance” page on that server is probably the most “self-hosted” way to accomplish what I want.
This has a couple drawbacks, though. First, I don’t like the idea of hosting publicly accessable services on a machine that is intended to only back-up my personal data. While it would probably be fine, it violates my personal standards for my data. Second, it’s not my network. I can’t set up new firewall rules and upnp is (rightfully) blocked. This would leave me needing to circumvent the firewall in some way.
The easy answer is Cloudflare proxying (which I’ve previously talked about here). This would circumvent the firewall and NAT limitations; but, while it would work, there’s a big problem: I’d be allowing strangers into someone else’s network. That would be an abuse of their trust and just a generally not-cool thing to do.
Unfortunately, without any usable hardware, I think I’ve exhausted my self-hosted options. If I want a page that can exist independently of my servers, a cloud option is likely the only solution. A full blown VPS would be overkill and I don’t want to create a whole account with a dedicated hosting provider just to host a temporary page, though… So what other options are there?
Cloudflare Workers
Cloudflare offers what they call “workers,” as a free service. While I don’t want CF to have access to all my data (see post linked above), I think letting them host a maintenance page is a pretty acceptable compromise. The way this will work is that CF will intercept requests for my websites and return a simple page explaining that my site is down for maintenance.
The first step is to build the maintenance page itself. I want any one visiting the page to know that my downtime is intentional, so a generic CF 502 error page isn’t going to cut it. I also want to make sure that the page returns the correct http code: 503. The 503 code tells browsers and search engines that the site is temporarily unavailable and can provide guidance on when to check the site again.
Here’s how my new page looks:
It’s color-matched to my site and provides a clear message that we’ll be back soon.
The worker is written in JavaScript. The JS is run by the worker itself, though, not the client browser. Here’s where we define the status code and the re-try period:
return new Response(maintenanceHTML, {
status: 503,
headers: {
'content-type': 'text/html;charset=UTF-8',
'Retry-After': '86400'
},
}
We can also drop into the browser’s debug console to see that we’re providing the correct status code.
Next, I set a “route” for the worker. This tells CF that when it sees that route, to send the request to the worker instead of forwarding it to my server. In this case, since I want this page to be returned for all of my pages, the route is just two wildcards: *.k3can.us/* and k3can.us/*.
Together these should match any requests which come in for the domain.
Now, since I don’t typically allow CF to intercept my private data, this worker won’t actually, well, work. At least not yet.
The final step is to enable their proxy service. Under the DNS settings, I can toggle my domain from “DNS Only” to “Proxied.” This allows CF to decrypt all the data coming from my server, but since I’m only planning to enable this when my server is down and the worker is going to intercept all the requests, there won’t actually be any private data coming from my server in the first place.
Essentially, this toggle now functions as an easy “maintenance mode” switch. When I need to take my server offline, I can flip the switch to Proxied and all requests will receive my maintenance page. As soon as my server is back online, I flip the switch back to “DNS Only” and everything is back normal and properly end-to-end encrypted.
Lastly, I actually created one extra DNS record: maintenance.k3can.us. I’m going to leave the proxy enabled on just this one entry, so that you (and I) can see the maintenance page without actually taking my site offline. You can also compare the TLS certs to see the difference between my real cert and the MITM cert provided by CF.