Moving WordPress (4) – SSL, themes, etc.

This is the final part of my writeup of everything I did to move my site from one EC2 instance to another, and make a bunch of other changes. It’s mostly documentation for myself, so it is rough and may at times not make complete sense, though I hope anybody else who tries something similar finds it useful:
Moving WordPress (1) – what I wanted to do
Moving WordPress (2) – AWS setup
Moving WordPress (3) – database and content
Moving WordPress (4) – SSL, themes, etc.

With the site(s) kind of up and running, I permanently pointed DNS to the new locations, then set about installing the Let’s Encrypt Certbot for SSL support. I have used it in the past, and have found to be simple to set up. Then I set up themes and did a bit more cleanup. I did this a few minutes at a time over a few days.


In the past, I installed epel (Extra Packages for Enterprise Linux) and then used those packages to support the Certbot installation. There are still instructions available for doing this bouncing around on the internet, but they are no longer applicable on Amazon Linux 2023 and I won’t link to them because they will just confuse. The world overall is moving away from epel, and for good reason. It was time to learn a new way to do this.

Certbot lists Snap, Docker, and Pip as the supported ways of running their software today. Of these, pip was the most familiar to me. In any event, the instructions provided on the Certbot site are straightforward and address everything you need to do but somewhat incomplete/incorrect for newer versions of Linux like AL2023 (see below). [Added November 23]

Apache Settings

I installed the certs, and the installation program also updated my httpd.conf file to rewrite all requests to the three sites as “https,” effectively forcing all users into SSL. It also rewrites the URL for this website as “” if you happen to type “”

There are three sites on this server at this time, each in it’s own directory. The entries for this site look like this:

#WWW rewrite as canonical name with https
DocumentRoot /var/www/html/websitedirectoryname 
RewriteEngine on 
RewriteCond %{SERVER_NAME} 
RewriteRule ^{REQUEST_URI} [END,NE,R=permanent]

#Canonical name rewrite as https
DocumentRoot /var/www/html/websitedirectoryname 
RewriteEngine on 
RewriteCond %{SERVER_NAME} 
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

I won’t address the finer details of the httpd.conf file, which is critical to Apache and requires modification if you’re running more than a single site on the same server. It’s easy enough to find documentation for that, and the official docs will surely be far more up-to-date over time than anything I’ll write here.


I chose a theme from the currently available ones that I liked, and installed it to both of my websites. It will likely change over time, so I won’t discuss those details here. The current details are always up to date on my technical details page.

I’m not crazy about this one. It doesn’t offer forward/back links that I like for multi-part posts like this one. It also assigns the post to a random category for display when I’ve included it in more than one. But that’s mostly because my category tree is way too complex and needs pruning. There are a few other quirks, I’ll likely have to pay for a “non free” theme to get all the options I want, but that’s not much for a simple site like this.


I installed the WP-Optimize plugin, that I had used to clean the databases before moving them, on all three sites. I’ll use it for occasional maintenance. On my Travel Blog, I also installed the Envira-Gallery plugin as that site is photo heavy. Most pages on that site feature a photo gallery and Envira has been the solution I’ve liked best for those. There are a handful of other things I’d like to do, but my focus right now is on beginning to write again.

Final tweaks and cleanup

WordPress is pretty good about including warnings and suggestions on their status pages, and a few things were clearly not working right. These were easy enough to address.

For starters, I didn’t have Image Magick installed. This is really helpful for processing uploaded photos.

sudo dnf -y install php-soap php-pear
sudo dnf -y install ImageMagick ImageMagick-devel ImageMagick-perl 
sudo pecl install imagick 
sudo chmod 755 /usr/lib64/php8.2/modules/ (or wherever it ends up, check the output of the installation)

Then add to php.ini:

php-intl is missing:

sudo dnf install php-intl

The zip library for php is missing, so there are problems with downloading and installing updates that are zipped. Fixed with:

sudo dnf install libzip libzip-devel
sudo pecl install zip

You should add to php.ini:

Finally, due to the way AWS servers are set up, you encounter some security issues when installing updates. I have yet to find a good explanation of what’s going on. But this is resolved by adding the following to wp-config.php:

define( 'FS_METHOD', 'direct' );

I should, someday, figure out what the exact issue is, as this setting is not required when you run WordPress on a host that is set up for it, but has been an issue for both of my ec2-based installations. But I’m not a Linux administrator, so it’s not a high priority to me.

I did some final tuning with WP-Optimize. There was a lot of old crud in the database even after cleaning it up. There were even more old records in the wp-options table from plugins I no longer use that were extending the response times, especially on my travel site. It wasn’t terrible, only 87ms on the travel site vs 64ms for this site, and well below the desired threshold of 600ms.

I went through and removed a lot of junk database entries, reducing my response times to 62ms for the travel site (that includes a header image on every page) and 52ms for this site (which as of this writing, has no header image). Seems more than reasonable. The site status for both still warns me that I’m not using page caching. I’d love to get to the point where that matters.

Final cleanup and architecture review

I backed up the sole EBS volume that was attached to my old host, and deactivated the host. Once I was sure everything was up and running nicely, I purchased reserved instances for both my EC2 and my RDS instances. I’d love to have a big enough AWS bill to justify a savings plan, but I can’t, so for now RIs are my best option.

Finally, I reviewed and tightened all the security settings, deleted VPC peering with the old VPC, and eventually deleted the old VPC and everything remaining in it. I’ve tagged all the resources associated with this application and can view them all in Systems Manager.

There are 34 individual tagged resources associated with running this relatively simple WordPress environment:

  • EC2
    • 1 EC2 instance
      • +1 for the instance reservation
      • +1 for the keypair to access it
    • 2 EBS volumes
      • +4 for the snapshots (3 snaps for the html volume, 1 for the root volume)
  • Database
    • 1 RDS instance
      • +1 for the instance reservation
      • +3 for snapshots
    • 1 DB subnet group
  • Other storage
    • 2 S3 buckets for image files (work on implementing these is still in progress)
  • Network
    • 1 VPC
    • 1 Elastic IP address
    • 1 Internet Gateway
    • 3 Subnets
    • 3 Route Tables (1 default)
    • 4 NACLs (1 default, and 1 for each subnet)
  • Security
    • 3 Security Groups (1 default, 1 for the EC2 instance, 1 for RDS)
  • The Resource Group itself, which is tagged as a resource

AWS provides a lot more granular control than some other cloud services. But this can get pretty burdensome pretty quickly. Ideally, you’d never do something manually in the way I chose to do this one.

Epilogue, Certbot redux

[Added November 23]

I received a notice from Certbot that all my certificates were set to expire shortly. This seemed odd, because Certbot is scheduled to check them daily and update when they are within 30 days of expiration. I concluded that for some reason, the daily cron job was not working correctly. etc/crontab listed the job correctly. I had added it there when I set up Certbot. In fact, I recall having to add the /etc/crontab file, which was missing. Hmmmmmm…

It didn’t take long to identify the problem. AWS has decided not to include Cronie by default in AL2023, as it is superseded by systemd’s timer capability. Again, I’m not a Linux adminstrator and while I should probably learn the full capabilities of systemd at some point, figuring out how to use timer to run the Certbot command is more than I want to bother with right now. So I installed Cronie:

sudo dnf install -y cronie
sudo systemctl enable crond.service
sudo systemctl start crond.service

Just to be certain, I ran Certbot manually:

sudo certbot renew -q 

And I checked the update with:

sudo certbot certificates

That should keep everything running.