Well, that was an ordeal.
A few weeks ago I got an email that my shared web hosting account (that I use for both this site and RoaldDahlFans) was up for renewal, and it reminded me that I didn’t like the host I was using. I was stuck on PHP5 and they were going to charge me more to move to a server with PHP7, and that pissed me off. So I asked Twitter what to do.
Folks – where's the best WordPress hosting these days?
— Kris Howard 💃 (@web_goddess) June 16, 2020
I got a lot of different answers, most of which were a LOT more expensive than I was spending. I was okay with going up a little bit, but these are both hobby sites rather than professional so anything over, say, $20/month was too much. A few folks threw out the suggestion to use Amazon Lightsail, which was intriguing. After all, it’s always a good idea to eat your own dog food. (I should also mention that these sites are and have always been hosted and paid for by me personally, so they’re not running on my employee AWS account or anything like that.)
I thought I’d document the process that I followed for the sites, which was based on this blog post and this AWS tutorial. Truthfully, setting up a new WordPress site on Lightsail is super easy and takes less than hour. All the complexity was because I was migrating two very old and very crufty sites from PHP5 to PHP7 and trying to preserve twenty years’ worth of old URLs. So even though I encountered a few hurdles not described in the tutorials, I wouldn’t let that stop you. Read on for the details…
- Create new Lightsail instance. Now, a lot of people told me to use the small instance, the one that’s $3.50/month and has a free month trial. Sadly, I worked out pretty quickly that 512MB of memory wasn’t the best with WordPress, and I ended up moving to the next size up. Thankfully changing to a larger instance was super easy – I just made a snapshot of my existing one, and then used it to create a new, larger instance afterwards.
- Connect and get application password. For connecting, I just used the pop-up console you can access from within the Lightsail dashboard. Super handy!
- Set up a Static IP address and point it at your instance. This allowed me to point my domain name to a single IP address, even if the instance behind it changed. (See my point about upgrading to a bigger instance in Step 1.)
- Login to WordPress and apply any necessary updates.
- Go to the old site and install All in one Migration plugin. Then I kicked off a full export of my old site, which took some time.
- Go back to your new site and use the All in one Migration plugin to import your old content. (It’s already included in the default bitnami WordPress install.) Because I was going to be doing a couple sites which were both large, I paid for the Unlimited Extension, which worked well. A bunch of blog posts recommended that the first think you should do after importing is resave your permalink settings, so I did that.
- Update plugins and check for website weirdness. Because I was going from PHP5 to PHP7, some stuff broke. For example, I was using a MyFonts Webkit plugin to display a custom font on my site. That broke all kinds of stuff. However, I was able to remove it and then upload a fresh version, which fixed the errors. I had a couple other plugins that hadn’t been updated in a long time, so I trashed them and replaced with updated ones that had been tested against the latest version of WordPress. I also had a couple instances of short open PHP tags in my child themes, which I had to replace. Oh, and as part of this, I had to occasionally change permissions on files in order to edit them. I found that doing “sudo chown” on them in the console worked perfectly.
- Copy over any files you had outside WordPress. Because my sites have been around a long time – since before I used WordPress, in fact – I had some files on the server that I wanted to keep. I was able to use SFTP to move those over to the new Lightsail instance.
- Change custom domain name to point to new website. This involved setting up a Lightsail DNS zone and changing the nameservers at my registrar.
- Turn off the Bitnami banner on the site. I just followed these steps.
- Use the Better Search & Replace plugin to fix site references in the database. When my old content was imported, it ended up with a lot references to the site’s Static IP address rather than the domain name. This plugin allowed me to search for those and replace with my domain.
- Set up a free Let’s Encrypt SSL Certificate. I followed the steps in this tutorial. Pro tip: each time the steps have you add a TXT record to your DNS zone, check that it appears with this tool before you progress to the next step. I also installed the Really Simple SSL plugin and used it to activate SSL.
- Turned off Cloudflare. My old sites were using Cloudflare as a CDN, so I removed that.
- Set up Amazon CloudFront using the AWS for WordPress plugin. I used this tutorial with one small change: I created a separate subdomain to use as the CloudFront origin rather than going with just the root (non-www) domain. This allowed me to then use htaccess (see below) to redirect all my non-www traffic to my www subdomain, which was pointed at CloudFront. (I learned this trick the hard way. Originally I followed the tutorial exactly, leaving roalddahlfans.com as the origin. Then I used htaccess to forward my non-www traffic to www…. and you see where this is going. Infinite redirects. Not good. So use a separate subdomain for the origin and avoid that problem.)
- Fix up your htaccess. Ugh, this was such a nightmare. Bitnami has a special way they want you to handle htaccess on Lightsail, but I ended up having to depart from that for both sites. For RoaldDahlFans, because of the history of the site I actually have quite a few htaccess files in directories to handle the 1500+ redirects I recreated when I moved to WordPress. So for that one, I ended up changing the AllowOverride option in Apache so that I could use use them. With this site, I left AllowOverride set to None but added the necessary rules to my htaccess.conf file. Then I had a weird situation where none of the pages beyond the home page would work, and to fix it I had to move a couple of the rules in httpd-app.conf into htaccess.conf. Important gotcha: in this post it says to run mv httpd-app.conf httpd-app.conf.old to create a backup of your file, but that command actually does a rename. So yeah, don’t do that or you’ll lose everything in the original one.
- Fix up any analytics/ads. I have Google Analytics and Google Ads on RoaldDahlFans, so I ended up using the Site Kit by Google plugin to add. I also use the WP Simple Adsense Insertion plugin to actually display ads on the site.
- Fix up any paid subscriptions. I had a paid Jetpack/Vaultpress subscription for RoaldDahlFans and it did not like me moving to a new server. I ended up having to lodge a support request to get them to help me sort it out and get backups working again from the new site. I also upgraded this site to paid Jetpack, but because it’s a new subscription, it appears to be using Jetpack Backup rather than Vaultpress. But that’s confusing, because Vaultpress still shows it in that dashboard. 🤷♀️
- Enable two-factor login via Wordfence. Might as well. Extra security!
- Enable support for sending email. For the Roald Dahl website, I have a contact form where people can email me. In order for that to work, I had to enable emails from WordPress. I also had to install the WP Mail SMTP plugin as part of that.
- Create Lightsail snapshots. You can also decide if you want them to be automatically created every day.
- Enable support for forwarding email. I don’t get a lot of email on the domains associated with these sites, but I do occasionally get some. I ended up setting up a serverless workflow to forward them to me using Amazon Simple Email Service. (I also took this guy’s advice and check the spam flags before forwarding.) I have a lifecycle policy set up on the S3 buckets to delete any messages after a week.
- Tag your resources in AWS. I set up a tag for each site that I used on the various services so I could keep track of the costs associated with hosting each one.
Still to do:
Kill the old shared hosting account! I’m just waiting another week to make sure everything’s working before I get rid of the old sites entirely. Cap the number of post/page revisions WordPress is storing and clean up the old ones from the database. Add in Open Graph tags for better sharing posts to social media. I thought I had that working before, but apparently not… 🤔
- Automate renewal of the Let’s Encrypt SSL certificates. These are only good for 90 days, and I’ve seen a few posts mention where folks have cron jobs set up to renew them.
Automate security patching. This blog post has some good suggestions I’ll implement.
- Offload media to S3. I’ve seen a few blog posts about moving your static media over to S3.