migrating a Lightsail WP site to a new instance

I needed to update PHP to 7.4.x on my Lightsail/Bitnami hosted WordPress site, which meant I needed to spin up my site on a new instance and re-do all the initial setup. (There may be other ways, but since Bitnami is packaged as a bundle, this seemed like the most straightforward approach, where I’m least likely to shoot myself in the foot because of details I’m unaware of.) This post is primarily a reminder for myself of what all that entailed.

export current site

I use All-in-One WordPress Migration with the Unlimited extension, since my site exports to a file larger than the free limit. This also enables me to use the backup/restore feature if the regular import is not working.

Go to All-in-One WP Migration > Export, export to file, and download the file.

create new instance

In the Lightsail console, create a new instance with the same size as the current one (unless you need to upgrade) and the Bitnami WordPress bundle. Give it a decent name now, as you can’t rename it when you’ve determined that it’s set up correctly.

Use the terminal icon once it’s running to ssh into the instance, and run

cat bitnami_application_password

to get the password for the default user (user) so you can log in to WP admin.

While you’re in the terminal, disable the Bitnami banner:

sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1

import site

First, clean up the plugins and themes from the default WP site; delete the ones you don’t use (leave one default theme or WP will complain in its Site Health checks), update the ones you do, activate All-in-One WP Migration, and manually install and activate the Unlimited extension, which you should have stored locally (or in Google Drive or wherever) when you bought it.

Then, go to All-in-One WP Migration > Import and import the file you just exported from the current site. Some guides say that if your file is >40MB, you’ll need to update settings in your wp-config.php file, but with the Unlimited extension, I have not needed to make any manual changes.

If the import hangs, it may be worth uploading the file via SFTP and using the Backups > Restore function instead of Import.

When the import completes, click around the site to check for anything broken on the new system. (I did have some issues with EXIF data on my photos not displaying at this point, but it seems to have been related to SSL or how the image URLs were determined, as it did load if I forced the page to use http; and the issue was resolved after I transferred the static IP and got SSL and the redirect set up.)

install lego

I used to use certbot-auto for managing my SSL certificate, following a guide at Metablogue, but I noticed a warning in my cron log when doing this upgrade that that tool has been deprecated, so I am now following Harry Bailey’s guide and using a Golang Let’s Encrypt tool, lego. I don’t like how freely that guide uses sudo, but I don’t know where it’s truly necessary or not, so I followed the guide as written.

To confirm that Bitnami is using its own openssl package, ssh into the instance and run:

test ! -f "/opt/bitnami/common/bin/openssl" && echo "Using system packages." || echo "Self-contained installation."

Assuming it is, run the following to install lego:

cd /tmp
curl -Ls | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -i -
tar xf lego_[TAB to complete path]
sudo mkdir -p /opt/bitnami/letsencrypt
sudo mv lego /opt/bitnami/letsencrypt/lego

(Note: I saw a redirect in the process; I believe the lego repo has moved from xenolf to go-acme.)

transfer static IP

Obviously, this assumes you already have a static IP and it is attached to your live site. This is the part of the process that I most dislike – I want to be able to smoothly transition from old to new host, with zero downtime, but there is downtime while the IP is detached, and while DNS is updating (and there will be a security warning if the DNS is updated before the SSL certificate is retrieved). I’m not sure how to avoid that with a WordPress site, unless they have a capability I’m unaware of to be set up as a distributed system.

Anyway, in the Lightsail console, go to Networking, detach the static IP from the current/previous host, and attach it to the new host.

get SSL certificate

Stop Bitnami and call lego to get the certificate; note that this registers both the base domain and www. Registering www is not strictly necessary but you probably want to.

sudo /opt/bitnami/ stop
sudo /opt/bitnami/letsencrypt/lego --tls --email="" --domains="" --domains="" --path="/opt/bitnami/letsencrypt" run

Back up original cert files and symlink to the new ones; replace [DOMAIN] with your domain.

sudo mv /opt/bitnami/apache2/conf/server.crt /opt/bitnami/apache2/conf/server.crt.old
sudo mv /opt/bitnami/apache2/conf/server.key /opt/bitnami/apache2/conf/server.key.old
sudo mv /opt/bitnami/apache2/conf/server.csr /opt/bitnami/apache2/conf/server.csr.old
sudo ln -sf /opt/bitnami/letsencrypt/certificates/[DOMAIN].key /opt/bitnami/apache2/conf/server.key
sudo ln -sf /opt/bitnami/letsencrypt/certificates/[DOMAIN].crt /opt/bitnami/apache2/conf/server.crt
sudo chown root:root /opt/bitnami/apache2/conf/server*
sudo chmod 600 /opt/bitnami/apache2/conf/server*

And restart Bitnami:

sudo /opt/bitnami/ restart

update config

Locate your wp-config.php file (try ~/apps/wordpress/htdocs) and update the lines defining WP_SITEURL and WP_HOME to point to https instead of http.

define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST'] . '/');
define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST'] . '/');

While you’re in this file, make any other modifications you had on the original site; I don’t like the default post revision behavior (unlimited proliferation), so I limit revisions to 3 per post/page by adding this line before the definition of ABSPATH:

define( 'WP_POST_REVISIONS', 3 );

Finally, edit the /opt/bitnami/apps/wordpress/conf/httpd-prefix.conf file to force redirection from http -> https. Add these lines at the top of the file:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [R,L]

schedule SSL cert auto-renewal

Create a file called in /opt/bitnami/letsencrypt/scripts/ with the following contents (values updated for your site):


sudo /opt/bitnami/ stop apache
sudo /opt/bitnami/letsencrypt/lego --tls --email="" --domains="" --domains="" --path="/opt/bitnami/letsencrypt" renew --days 90
sudo /opt/bitnami/ start apache

Make it executable:

sudo chmod +x /opt/bitnami/letsencrypt/scripts/

Open the crontab editor:

sudo crontab -e

And add an entry to run the script once a month, logging any output to a log file for later reference.

0 0 1 * * /opt/bitnami/letsencrypt/scripts/ > /var/log/renew-certificate.log 2>&1


Update any fully specified links (to resources on your site) you have on the site; I try to always use relative links, but found one page that had full URLs for image sources, which were still pointing to the non-static IP address but worked fine once I corrected them to be relative.

And there were other instances in plugins, posts, and comments that I wouldn’t have found manually; I ended up having to use the Better Search Replace plugin to get to all the references of the IP address; first replacing http://[IP] -> https://[domain] to also replace any unwanted http links with https, then [IP] -> [domain] to catch any instances that were already https or didn’t have the scheme. You can find the plugin under Tools in the left-hand nav after you’ve installed and activated it.

One annoying note about this: I use MailPoet for my post notification emails, and it seems they use a Last Modified timestamp as a stand-in for other fields that are not strictly identical with Last Modified, so after this change, for example, every record of past sent emails shows the time of the change as the time it was sent. That nothing else will ever modify their tables is a bad assumption, but evidently one they made. Something to watch out for.

I kept reading you might need to flush permalinks, although I’m not sure if there was any practical effect for my site.

When you’ve confirmed the new instance is working as expected, stop the old one. Keep it around for a bit if you want to be able to revert, or go ahead and delete it. Same for the export from the old instance; once I know the new instance is working, I’d be more inclined to delete the old export and make a new one if I want it as a backup.

Leave a Reply