Site Updates

  • ~6 min read

I’ve slapped a new coat of paint on the place and made some minor under the hood changes. More detail below.

Move to AWS

In late 2016 I moved the site from being served from a little VPS+ngnix to S3+CloudFront. The site was basically all that was running on the VPS and why pay $5/month to serve up static files when it could cost pennies. The site now averages about $0.70/month to serve (on a CDN), $0.5/month of which is just hosting the DNS for on Route53. Cheaper and better performance. Win-win.

I went into AWS initially planning on just setting things up by hand, but at the time there was a neat “Host a static website” quickstart thing that sets up the basics for a static site really easily and even provides a nice status page. I started with that.

It wasn’t perfect, had to make some tweaks and add some stuff (like www → root redirecting), but it was cool. I can’t find the slick status page anymore, or a link to the quickstart, so maybe they dropped it.

But managing things through a GUI long term is not something I wanna do, so eventually encoded the setup in some terraform (see /infra/). Importing the existing resources into terraform was pretty easy, props to them for supporting that. At least most of them. The TLS cert for the domain, managed by ACM, was harder to deal with. In general these can be a bit of a pain for config tools because of the verification step, but I could not get terraform to import my existing verified certificate. Not a big deal though, currently using a data source to pick out the right cert, so at least I don’t have to specify the ARN by hand.

Pretty happy with things. I wish I could use a CloudFront Origin Access Identity to restrict access to the S3 bucket so that all requests are forced to flow through CloudFront, but it breaks the S3 website hosting stuff. So if someone manages to guess the S3 website URL, they could side step the CloudFront stuff, which is a) more expensive to me and b) misses out on some security settings.

May setup a shared secret in a header between CloudFront and S3 such that S3 would reject requests without the right value to at least block serving up actual content to good guessers. Might eventually write my own little server to perform the S3 website duties and misc. other things. But I can live with things for now.

Most folks are probably better/more easily served using something like Netlify, but I like doing things myself and my needs are simple.

Better security

While overkill for a static site like this, the move to S3+CloudFront did mean I lost an easy way to specify recommended security headers, most important to me is HSTS. In December 2016/early 2017 AWS launched Lambda@Edge, which allows one to hook into the CloudFront flow and make changes, most importantly for me, it gives us the ability to add these headers back. Feels like a kludge to setup a lambda to set some static headers (honestly Amazon, just provide a way to set static headers in CloudFront), but it’s easy enough and I finally got around to setting it up for the site redo. The lambda is very simple.

Also added a Content Security Policy (CSP), but instead of as a header, it’s HTML <meta> element since it kinda belongs with the content. I could probably be convinced to go either way with it, but it’s in the HTML for now.

See the Mozilla Observatory tests.

Repo organization

Rearranged some things in the repo. Broke apart the structure, with site executable bits in a top-level executable/ dir and the content (posts, pages, etc.) in content/. The nix build setup has also changed to accommodate the new layout as well as being reworked in general. The nix stuff is also locked down to a specific version (should have done that from the beginning).

I’d love to use nix even more to build and publish the site and there is a derivation to build the content, but because I rely on the files timestamps to show when a post or page has last been modified and those are lost/reset during the build that way, I pretty much have to build the site from the repo. Maybe I’ll move the last modified date into a meta field in the files themselves, but for now it’s not that big of a deal.

Dropped Bootstrap and therefore the submodule for it.

Moved from using Google Fonts to just subsetting the text fontsMerriweather and Fira Mono at time of writing

myself and serving them with all the other site content, which required some build scripts. This was interesting and probably not quite as good as using Google Fonts, but I like having everything self contained.

Also moved from a full FontAwesome to just a subset with fontello, which has a nice setup for automation. See the fontello-* targets in the makefile.

New look

I tend to waffle on about things, so I wanted the site optimized for long-form reading. That has really always been the focus, but I think the new design is better than what I had before, with a bit wider main column for text and sidenotes support. It’s based on tufte-css, though with a good amount of additions and tweaks to make it work better for a whole site instead of just an article.

I’m not using the upstream CSS directly, but rather I ported it to Clay to be easier for me to work with. “Easier to work with” in some ways, being embedded in Haskell is nice, but the Clay files are compiled with the site executable, not by it, so CSS changes take a site rebuild to take effect. It’s easier to set up this way, but I should probably move it to be compiled separately at some point.

Tried to reduce and simplify everything. I kinda want to have the site navigation vertical on the side instead of horizontal across the top. May move the table of contents into the sidenotes area, but I’d need to avoid any sidenotes that are on early content, which is a complication.

I’m not very happy with how code blocks look. The Tufte and Pandoc markups kinda collide. Also not sure I agree with the Tufte approach of not setting off the blocks with a different background. Will need to keep tweaking things.

New markup

The underlying HTML markup is more compatible with h-entry.

Finally set a favicon.

I had two constraints I tried to respect in this whole process 1) only care about modern browsers and 2) no JavaScript. For certain design elements in the future, especially supporting them across all devices, I may relax the second constraint, but if I could get something I liked without JS, then I wanted that. And the first one both helps with that and makes my life easier.

Wrap up

I’d like to go even more IndieWeb in the future with “notes” (think of a tweet, short unnamed content) and more social support (distributed commenting/liking/etc., with things like Webmention and ActivityPub), but those don’t fit well with a static sitethough and help

and I like the simplicity of what I’ve got for now.

The goal was to update the site and get it to a place I was happier with. That goal was achieved. Now to finish the slew of half-written posts I’ve accrued.