About Moving My Hosted WordPress Site to Static HTML on AWS

Until recently, this was a WordPress site running on a traditional web hosting service with no SSL certificate. It’s now a collection of static files sitting in S3 buckets in AWS fronted by Amazon’s CloudFront CDN behind an HTTPS URL, with email handled by Amazon WorkMail. My web life has gotten much simpler, I have a lot more money left over, and my security posture has dramatically improved, to say nothing of the radically improved load times making both Google’s algorithms and human visitors happy.

It all started when I got the bill for another 2-year renewal from my (now former) web host. Add to that Google’s constant complaints that I really should encrypt my site with an SSL certificate. I know you can get "free" certs, but there are issues with that approach, and I just couldn’t see how this little site (and another I host for someone else) was worth hundreds of dollars for hosting & SSL. (Most of my visitors run ad blockers, so Google Ads revenue doesn’t come close to covering that cost, making this a labor of love.) I’ve been working with AWS at my day job for many years now, so that was a natural place to turn, as I was already familiar with it, though Azure & GCP offer similar options if you prefer. (I don’t know about GCP, but Azure isn’t a registrar, so if you go with them, you’ll still have to pay someone else to keep your domain name. AWS allows you to handle all of that with Route 53.)

My first question was "is this even possible?" Can you take a dynamic site backed by a database with no actual HTML files making it up, and convert it into static pages without losing all the cool effects my heavily-modified WordPress theme gave me, plus all of those plugins...? Well of course, the answer turned out to be yes! As usual with WordPress, the answer came in the form of a plug-in called Simply Static. You just install that, run it, then go get a drink. When you come back a few minutes later you’ll have a ZIP file containing lots of static HTML (and XML and CSS and…) files. Sure enough, when I unzipped the files and tried it on my local computer it looked OK. A little rough around the edges, but I could work with it.

I’ll spare you the blow-by-blow of my thought processes getting it into AWS and mistakes made, etc., and get right to the good stuff – how to do it. First, you need to set up an S3 bucket for the web site. AWS covers most of the basics on their site. The one thing I’ll add to AWS’s instructions is that it’s a good idea to name your bucket the same as your web URL, so in my case it’s www.rainingforks.com. This makes things easier later on, and ensures maximum compatibility with services needing to interact with it. (Also, since I planned to front my site with Amazon CloudFront, I could diverge from the instructions linked above slightly, and continued blocking public access to my S3 bucket, since really only CloudFront needs access. While this is more secure, the disadvantage is that it makes it impossible for links ending in a slash ("/") to work. This meant I had to do a bulk find & replace to the HTML code in all of my files to ensure all the HTML ended in "/index.html" or whatever. Many people might find this too much of a pain to justify just disallow public S3 bucket access, but I bit the bullet and did it, since it’s a one-time thing and then it’s done forever, leaving you that much more secure.)

The next thing to do was to set up SSL & CDN for this web site. That’s easy enough to figure out if you poke around AWS. Basically, you want to use AWS Certificate Manager to handle your self-generated SSL cert, and configure CloudFront to point at your S3 bucket. Each setting has a nice little help button next to it that you can click on for an explanation of what it means and lots more info about it, so I won’t waste time rehashing all of that here.

There are a few things to be aware of regarding the CDN though...

First, you need to configure an origin access identity (OAI) for your site in the CloudFront distribution, or you’ll get 403 errors trying to load your site. 403 errors happen if you’ve disabled public S3 access, so this is a way to give CloudFront permission to get what it needs from S3.

The other thing to remember is you’ll now update files by uploading them to S3 via console or CLI (yay - no more SFTP!), but CloudFront caches your files for the period of time you specify – usually at least a day. So if you want to immediately see the changes you’ve made to your files, you’ll need to first invalidate files in the CloudFront distribution to prompt it to go fetch the latest/current version of the file right now.

The only other potentially confusing part of this whole migration was moving my domain ownership and DNS records over from my host to Amazon Route 53. Entire classes can be held on DNS and how domains work, so I won’t waste a lot of space bringing you up to speed on the basics here. Instead, let me just mention a few things that I thought were particularly good to be aware of in that process:

How to transfer a domain registration to Route 53.

Making Route 53 the DNS service for an inactive domain. (Note, these instructions worked for me, because I didn’t care if my site had some downtime during the switch-over. As it turned out, there was no downtime, since I had a copy of my site waiting at the new address, and everything worked smoothly, but if you actually care about potential downtime, AWS has other pages giving you other ways to make the transfer which are a bit more complicated.)

You also need Amazon Route 53 alias records to route traffic to AWS resources, such as CloudFront distributions. Once you set that up, you’ll want to configure custom URL CNAMEs for the ugly default CloudFront domains.

Lastly, you’ll need somewhere to point people for your Contact page (or equivalent). For this I used Amazon WorkMail (which can be configured to forward to other email accounts if desired). This is by far the most expensive component to this entire set up, but if you only need an address or two, the $4/user/month they currently charge isn’t bad.

So, with all of that set up, what else needed to be done? Well, the HTML that Simply Static output wasn’t very pretty to a human, so I went through a formatted a sample blog as a template to use going forward. Now I just copy that file, rename it, and populate the template with the new content. It’s not that different from what I used to do in WordPress, though there’s a bit more copy & pasting. A small price to pay for someone like me who only posts an occasional blog.

In addition, I had to delete/comment out the old Disqus code in my pages that WordPress used and set it up to be on static pages using their "universal code" instructions. Again, not a big deal when you use NotePad++ or other editor, which allows you to load in all your HTML at once and do bulk changes at a time.

Also, since I didn’t have WordPress automatically updating the display on each page showing the number of comments, so I just removed that, since if anybody really cares they can scroll to the bottom of the page and look for themselves. ;)

I think that was about it… Maybe a few tweaks to the Contact page (I removed a form, to make room for a heavily obscured email address using some JavaScript trickery), and got rid of the XML feed stuff, since I’m too lazy to manually update it.

How much did I save? Well, it cost $12 up front to move the domain to Amazon. Since then though, I’ve paid nothing, since my S3 and CloudFront use is all within the free tier, and the first 30 days of WorkMail is free. Once all the free promotional pricing goes away though, I expect it to be MUCH cheaper than the old host. CloudFront has a modest cost, but S3 is basically pennies for a few MB of web files, and Route 53 & ACM are pretty cheap also. I did the math a while ago and it came out to a massive savings, but as time goes by I’ll update this page if prices are higher than I expected. (AWS publishes all its services’ costs if you want to do Internet searches and some math yourself.)

So, I just wanted to write this post to let others who are staring down the barrel of a massive two or three-year web site renewal bill know that it doesn’t have to be that way. In AWS you can cancel at any time without penalty, and get better performance and security for less cost. (Oh, and if I suddenly get the Reddit Hug of Death, AWS’s CloudFront will be much better able to handle it than the crappy web host I paid the bare minimum to would’ve been!) If you’re at all a computer nerd then you too should have fun going through the process just as a learning experience, if nothing else! Happy coding!

Steve