Long-time readers of this blog will remember the hugo-lambda project that’s been powering this site. It uses S3 notifications to trigger Lambda functions that would rebuild the site’s contents from source on every change, and served the content with CloudFront behind an ACM Certificate.
After talking with the team at Aerobatic (interview coming soon) I took their product for a test drive. Aerobatic is a Bitbucket add-on that lets you push static assets to a branch and have them deployed and hosted automatically.
Image from the Aerobatic blog
Like my project, they use Lambda to build Hugo or Jekyll sites from Bitbucket hooks, which supplants my existing setup while adding new features. Hugo support was announced a few days ago, so it’s still brand new.
Aerobatic runs on AWS, so features like their CDN (actually CloudFront) and free SSL certificates (issued by ACM) are backed by familiar tools. The hugo-lambda templates cover some of the same ground, but Aerobatic also comes with a wealth of knowledge and best practices in its configuration. They set cache lifetimes, do URL rewriting, and build Jekyll or Hugo sites automatically.
To improve caching, they do HTML preprocessing on assets that automatically versions content so cache lifetimes can be absurdly long by default. On this page, Aerobatic is rewriting CSS, JS, and image URLs like this:
<!-- before --> <script src="/js/all.min.js"></script> <!-- after processing --> <script src="//d2q4nobwyhnvov.cloudfront.net/f2c9d102-b172-4302-9676-c51165d633ad/kzh6ySRLqsKYlA/js/all.min.js"></script>
What this means for you is skipping any manual cache-busting hacks like
sure clients get the new version because the version (as defined by a git
commit) is builtin to the URL. In the example above the version is
kzh6ySRL..., and the UUID
f2c9d102-... is my site’s ID on the Aerobatic
asset CDN. For details on how the rewriting works, see their docs on the
Caveat: because the site version is based on the commit, that means all your asset URLs change every commit, because of this I use external CDNs for boostrap and other long-lived content.
In addition to doing smart things automatically, they give you the option of proxying requests to your own S3 buckets for large assets, or anything you need direct control over. With the proxy, you can serve videos, images, and user-uploaded content on the same domain without worrying about CORS or integrating with your existing app. As long as it sends content to the right bucket, you’ll be set.
The Conversion Tango
Moving to Aerobatic was slightly complicated because I was already using CloudFront for my domain - two CloudFront distributions can’t exist that share an alias. I had to migrate off CloudFront to make the switch.
- Spin up temporary hosting
- Switch DNS to temporary server
- Delete CloudFront distribution with
- Add domain to Aerobatic and wait for the configuration to propagate
- Switch DNS to Aerobatic CDN
For temporary hosting, I used an EC2 instance with Caddy because it auto-issues TLS certificates (via LetsEncrypt) and the configuration was a mere 4 lines. Because I’d been using permanent redirects to send visitors to the SSL version of the site, I had to support SSL on the temporary host if I didn’t want to turn away visitors, and Caddy’s builtin LetsEncrypt made this a breeze.
# Caddyfile serverlesscode.com log ./access.log root ./public gzip
Once the site was running on EC2, I could move the Route53 record to point to it. After 5 minutes (the record lifetime) I turned disabled the old CloudFront distribution and deleted it. Aerobatic has a great interface for adding domains and it took all of 5 clicks to enable serverlesscode.com on the platform.
After another 20 minute wait for CloudFront to finish propagating, it was time to switch my DNS over to Aerobatic and kill the EC2 instance I had been using.
After a week of burn-in testing, I’d recommend Aerobatic for static hosting. If you’ve got a personal blog, or you’re an agency that builds sites with Jekyll, Hugo, or another generator Aerobatic is a great alternative to managing your own hosting/CI pipeline. They also offer features targeted at single-page apps, but this blog doesn’t use any of them.