Static blog served globally in < 1s with one server.

Posted on April 20, 2018 in rants

Website performance matters to me deeply. The "broadband" connection in my village got upgraded from 2 Mbps to somewhere between 3 to 6 Mbps in 2017. There's only so much information a pair of copper wires can carry. Ping round-trips to anywhere interesting are in multiples of hundreds of milliseconds. I have had access to 100Mbps down and upstream connections when living in Bangalore, but that was at work. Pretty much everything I know, I have learned over a slow dialup/ADSL connection.

I glance over hundreds of pages in a typical learning session, and read through + save snippets of dozens of pages for later reference. As a result, sites that leisurely download several megabytes in tens or hundreds of files before they can render a text article make me cringe in pain over the utter waste. I can't change other sites, but I can change ones I run, including this blog.

keycdn sample of sites and their load times

You may notice that a single request loads the entire page in a fraction of second. The "entire page" is the home page with excerpts from 10 blog posts, the HTML markup, the CSS and that display picture in the corner - all delivered compressed into 14kb, which expands to 27kb on download.

The blog is compiled using pelican - a static-site generator. I have slightly modified the Flex theme to reduce the requests made by the page. However, pages containing images such as this post aren't yet optimized, it is on the todo list.

Since wait for DNS is highly variable and I am yet to optimize that part of the delivery, following tests are run with the DNS primed. Each result is simply the result of a second test run after the initial warm-up request. Even with slow DNS lookups, the longest page-load from Melbourne took 1.9 seconds.

Here's what the tests say:

GTmetrix seems happy with the PageSpeed and YSlow scores.

gtmetrix report from Vancouver, 700 ms

Pingdom is reporting two requests, counting one for favicon embedded in data-uri. The scores are decent though.

pingdom report from Melbourne, 883 ms

pingdom report from San Jose, 538 ms

pingdom report from New York City, 324 ms

pingdom report from Stockholm, 112 ms

KeyCDN has one testing location in the same country as this server and from here, it is screaming fast.

keycdn report from Frankfurt, 89 ms

While at it, checked out Qualys SSL Labs:

Qualys SSL Labs report, A+ rating

Not too shabby, eh?

These tests can alert about known pitfalls, but I take them with a grain of salt since they cannot cover all the little things that matter. With that in mind:

gtmetrix PageSpeed report

gtmetrix YSlow report

Why bother sharing this?

Fast, secure (https everywhere!) website served from one server is very much a feasible model to deploy your own blog. It is humanly possible without overly complicated frameworks.

Having good ol' sysadmin skills in the coming age of serverless, even if cultivated as a hobby is something I take as an advice for myself. And if you are considering the same, here's some encouragement 😬

For example, this blog uses the following software:

  • Live site:
  • Build+deploy toolchain:
    • Pelican - static-blog generator.
    • Fossil - source code management.
    • acme.sh - letsencrypt certificate via DNS auth.
    • A shell script to deploy (rsync + run commands inside jail over ssh).
  • Workflow/Edit:

Pelican was the first new component for me in this setup, but it is well thought-out and documented. Learning how to operate it was not too difficult.

The deploy script was written once, now publishing a new post is a matter of creating a markdown file, fossil add ..., then a fossil commit -m "..." followed by ./deploy.sh.

Here is the deploy script in its entirety, homeserver is available to my laptop and phone over a private VPN and is set up in ~/.ssh/config. The blog is compiled and uploaded to the public server by gmake ssh_upload at the end.

#!/usr/bin/env bash

rsync ~/source/blog.fossil homeserver:source/blog.fossil
ssh homeserver -- 'cd source/blog && fossil checkout --latest && gmake ssh_upload'

After experiences with many blog engines over the years, several storing the images straight on CDNs and the sites nor images now anywhere to be found, today I would rather host lower-quality images directly on the blog, heck, even keep in the same repository. With rsync, it is a one-time upload, and in return I retain access to the entire content and code required to build and deploy the blog.

Does this site suffer from risks? Of course, taking it down in a denial-of-service attack should not be too difficult. It is a single server after all. However, as of today this blog should not need to worry. And in case of such a threat proving itself imminent, moving the blog to a CDN is trivial.

Until then, this one server is sufficient to deliver the blog to whoever cares to read it.

It is a personally satisfying feeling to have some control over one's own identity as it is presented over the web. To not track and violate the privacy of those who show interest in your words. To use the opportunity to build another endpoint in the world-wide-web that does the expected thing and nothing more.

You can do this too!