Posted 2020-06-28
This edition is not a philosophical rant, but rather a brief summary documenting how this blog/site is run, with some rationale and commentary.
Because I like to be in Vogue, the front-end for this blog is statically generated markup, rendered with templated markdown, and with just a sprinkling of webshit.
Fun fact: the design/css was something I made ~2008, when this site was originally backed by php 😱.
I don't have anything more to add about the front-end, which is how it ought to be.
The back-end is more interesting (read: over-engineered). There are a few layers worth mentioning:
Commentary: I wanted something robust, enterprise-grade, web-scale. Just kidding - I like rust, and I wanted to be able to serve REST endpoints, and so I avoided solutions for purely static sites. I have nothing against static site generators, and I highly recommend them!
Asking a software engineer to maintain a webshit is a bit rough, isn't it. If my blog crashes due to request volume, then I'm an unprepared doofus - but if my site is genuinely web scale, then I've probably just been burning time and money for what is ultimately not critical software.
There are really only a few deployment options:
Upon inspection, none of these were really satisfying for my needs (read: wants). I had already thrown away the thought of static site generators as using one here takes the fun engineering work away, and I did still have in mind that I might eventually expose some REST endpoints. Managing a VPS is too high-effort - and I am operationally irresponsible. Kubernetes with auto-scaling is quite elegant, but I didn't much want to work through the faff of Google Cloud or AWS if it could be avoided. FaaS is the dream, but all of the big providers have somehow settled on node.js being the right common denominator.
So I began a journey by asking: how can I FaaS my rust application, with minimal faff, reasonable prices, and reasonable scaling expectations? I was prepared to throw away actix (service layer), but rust was a hard requirement.
I did already know about things like crowbar, for writing rust code that transforms into an AWS Lambda python shim, but that didn't defeat the problem of avoiding touching AWS. What I really wanted was a better FaaS platform.
I found vercel, which was then called zeit.co/now.js, and found it quite compelling. Some code was re-written to use their rust shim, and within a day I managed to get my site running on their platform - truly FaaS - and with some nice automated continuous delivery to boot!
Unfortunately, after zeit re-branded as vercel, they also threw away their old FaaS model. The new company image wanted to be more focused on a webshit CDN platform, and along with that, hard FaaS request limits, and pricing 150,000x higher than Lambda.
In my ensuing rage, I found myself reading about FaaS platforms more carefully, at which point I discovered fly.io. Fly appears on comparison sites as a FaaS platform - and this is mostly true, just with longer lived instances and a reuse model (as I recall, firebase functions also have this feature).
The deployment model is fantastic - you just push a docker image, and Fly serves it on its edge network in 16 regions with an efficient hypervisor.
Instance size and concurrency limits are also configurable.
Here's my deploy.sh
:
#!/usr/bin/env bash
set -euxo pipefail
docker run --rm -it -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder cargo build --release
flyctl deploy
The docker command above is using rust-musl-builder to produce low-effort static MUSL binaries. With this, my whole webserver docker image is just 17MB.
Markdown rendered by askama, served by an actix microservice, hosted on fly.io.