posted in DevOps on 2016-04-27 16:28:37 UTC by Dave Martorana
Attempting to put my money where my mouth is, I just finished moving all three of our websites to a new, static-only, HTTPS-secured infrastructure.
Most recent setup
I moved the flyclops.com site to a statically-rendered site some time ago, serving it over Amazon S3. That went fairly well, but it’s a very minimal website, and doesn’t require anything dynamic.
The tech blog, which you’re reading now, was hosted on Wordpress, as are most blogs in this world. But over time, “features” became unnecessary (or even fairly useless) - think comments. Other features, like caching plug-ins, were nothing more than a means to an end - near-statically loading sites. But it was kludgy.
Enter FREE SSL
LetsEncrypt was released out of beta. This was a turning point. I spend a lot of time making noise about three-letter agencies and snooping and the necessity of encryption across as much of life as possible. Considering Flyclops is a profitable enterprise, there wasn’t much excuse for not having HTTPS across all our sites to begin with. With LetsEncrypt being production-ready, there was no more excuse at all.
Shortly thereafter, Amazon AWS released AWS Certificate Manager. AWS Certificate Manager offers free, auto-renewing SSL certificates for anything hosted on AWS services. That was now two free SSL services to choose from. Being hosted almost entirely on AWS, ACM was a natural choice - it’s also easier to manage from a renewal standpoint, in that there is no renewal overhead as with LetsEncrypt. There are plenty of tools that make LetsEncrypt renewing almost entirely hands-off, but that would still be something to manage.
What to do with PHP?
Now we had to choose - spin up servers to run PHP-based websites in AWS? That sounded plenty unnecessary. Instead, I took a closer look at Hugo, the Go-based static site generator I had glanced at when I moved the main website to a static site. I quickly ported the static site to Hugo, and was very happy with the process. (It helps that we recently finished moving our entire backend infrastructure to Go-written services - Hugo felt like a natural fit after that.)
I became determined to get our blog there as well, and installed the Wordpress to Hugo Exporter plug-in (thank you all you wonderful open-source devs out there). I exported my content, and spent about a day or so setting up templates, partials, taxonomies, and archetypes in Hugo. The process wasn’t entirely painless, but “minimally” painful. All-in-all, easier than I expected.
All that was left was the press kit. Lo-and-behold, I was not the first person to want to push the wonderful presskit() to a static environment, and I happened upon dopresskit-static on Github. A fork and a few tweaks later, and I had all our websites generating static output.
Static sites need static hosting, and S3 was a natural fit… except it really isn’t a totally natural environment. To boot, you can’t use AWS Certificate Manager-based SSL certificates with S3. Besides, Amazon has this sweet CDN service called Cloudfront that would deliver static content so much faster than S3.
First, I generated the following SSL certificates in AWS Certificate Manager:
- One for
- One wildcard certificate for
I set up three S3 buckets (one per site) to act as origins for content. I then set up three Cloudfront distributions, one for each bucket, with the appropriate CNAMEs. Cloudfront distributions let you specify:
- CDN origin - an S3 bucket, or BYO
- A secure certificate from AWS Certificate Manager
- CNAMEs for the distribution
- A default file to serve (index.html)
- What to do/serve for different HTTP error codes (404 page). Hint: Depending on how you set up S3 origins, they will return 403 errors for missing documents, not 404.
- Whether to serve both HTTP/HTTPS, HTTPS only, or redirect HTTP to HTTPS (we use redirect)
Distributions take a few minutes to set up, and once they were published, I went into
DNS (conveniently, Route53 on AWS) and
point to the appropriate CDN distributions.
All that was left to do was to set up publishing. At first, I just assumed I’d push public content to S3 manually as I updated it. But then I took a look at the “Deployments” capabilities of our git service, Beanstalk by Wildbit. It turns out, Beanstalk’s deployments are incredibly powerful and feature-rich. Publishing, selectively, even, a git branch to an S3 bucket, with pattern-matched inclusions and exclusions, automatically or manually, was extremely easy to set up.
(Don’t use Beanstalk for git hosting? Check out DeployBot!!)
And bonus - it will automatically invalidate any updated files on Cloudfront! That is spectacular!
Now I write content, use Hugo to generate the static version of the site, commit the changes to git, push them to my Beanstalk remotes, and a few seconds later, they’re published!
So now, at least, my money is now firmly where my mouth is - all of our sites are HTTPS only. To boot, they’re completely static, and CDN-served from an edge node close to you.
Now we can concentrate on more important things, and not worry about constant security updates to Wordpress and PHP, hosting issues, SSL costs or renewals, site or page speeds, ease of crawl-ability for web crawlers, and a host of other things.
Not too shabby for a couple days work.