Serverless maintenance page w/ Cloudflare
Oleg Khalin
Posted on October 6, 2022
History
A few weeks ago I realized that missed list from the hosting provider about the planned network equipment update and got connection timeout
on production servers. Hopefully, downtime was less than 15 minutes and business wasn't impacted, but our client must know what's going on and we need a maintenance screen, which will not depend on our servers. After this accident, I start thinking about how to resolve it. Few days after i realized that i can pass traffic using Cloudflare Worker's routes even before it pass target servers.
Requirements
- Website proxied using Cloudflare
- Cloudflare Free plan
- Maintenance page HTML
Project setup
Init basic npm
project
mkdir maintenance && cd maintenance && npm init
Init wrangler project
npx wrangler init
Select fetch handler in init script
Let's test it
After adding scripts to packages.json
"workers:dev": "wrangler dev",
"workers:deploy": "wrangler publish",
After these changes run
npm run workers:dev
Okay, now we have our worker handler, next steps are to create our index.html
and its assets.
Create index.html
mkdir public && touch public/index.html
Add site
attribute to wrangler.toml
site = { bucket = "./public" }
let's update our worker code
Install KV package
npm install -D @cloudflare/kv-asset-handler
Import kv-asset-handler
and add assetManifest
import {getAssetFromKV} from "@cloudflare/kv-asset-handler";
// @ts-ignore defined by workers
import manifestJSON from '__STATIC_CONTENT_MANIFEST'
const assetManifest = JSON.parse(manifestJSON)
Update Env
interface
export interface Env {
__STATIC_CONTENT: KVNamespace;
}
Fetch handler code
This code will be executed for any matched route
const { pathname } = new URL(request.url);
try {
const page = await getAssetFromKV(
{
request,
waitUntil(promise) {
return ctx.waitUntil(promise)
},
},
{
mapRequestToAsset: req => new Request(`${new URL(req.url).origin}/index.html`, req),
ASSET_NAMESPACE: env.__STATIC_CONTENT,
ASSET_MANIFEST: assetManifest
},
)
return new Response(page.body, {status: 503})
} catch (e) {
return new Response("Something went wrong", {
status: 500
})
}
Let's test it again
npm run workers:dev
public/index.html
:
Result:
Let's try to deploy it
npm run workers:deploy
Wrangler on the first run will ask you to authorize your requests using the OAuth screen.
How to enable maintenance mode on your website?
Simple as console.log
!
- Log in to your Cloudflare Console and Navigate to the Workers page
- Click on your worker
- Go to Triggers -> Routes -> Add route > You need to create 2 routes for common maintenance behavior.
- domain.dev - your root page
- domain.dev/* - wildcard for all your URIs
- Done! In a few seconds, all traffic will be forwarded to your Cloudflare Worker.
Final
You can check full version of page with integrated TailwindCSS included on my github. (Feel free to check this in template repository)
Thanks for reading, it's my first post. I will appreciate your feedback and advises!
Resources
Example
Github Template Repository
Screenshot
Posted on October 6, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.