We start here by assuming that you have already installed WordPress on your Amazon EC2 server. If you have not done so, this article describes how I set up a LAMP stack and WordPress on my EC2 instance. I am using Ubuntu so all my commands are based on that operating system. Most of the commands that I will be running requires super-user status so I change to root mode by doing:
$ sudo su
If you do not want to run as root, simply add a sudo before each of the commands below, for example, sudo apt-get update.
Before starting with migration, go to your WordPress dashboard and click on your Site Health Screen link. Make sure that all the required PHP packages are installed. You may want to check your PHP version here so that you install the right packages based on your version.
$ php -v PHP 8.1.2 (cli) (built: Jan 24 2022 10:42:33) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.2, Copyright (c) Zend Technologies with Zend OPcache v8.1.2, Copyright (c), by Zend Technologies
In my case, the required gd module was not installed so I do:
$ apt-get update $ apt-get upgrade $ apt-get install php8.1-gd
After all the updates, remember to restart your web server. I am using Apache so I do this:
$ systemctl reload apache2
You can see all your installed PHP packages by doing the following:
$ dpkg --get-selections | grep php
You can also create a PHP info page by doing the following:
$ vi info.php
Insert the following into the file:
<?php phpinfo(); ?>
Save and exit the file. Then access the file from your web browser.
http://your_domain/info.php
1. Install Themes and Plugins
The first thing that I do is change my WordPress file ownership to Apache.
sudo chown -R www-data:www-data your_wordpress_dir;
This will make it easy to install themes and plugins without having to muck around with SFTP. Once we have done the initial setup and want to harden our WordPress site, we can change the ownership of our WordPress files according to this article.
If there are problems with installing particular themes or plugins, you may want to edit your wp-config.php file and turn on debugging. Find the following line:
define( 'WP_DEBUG', false );
Replace it with the following three lines:
define( 'WP_DEBUG', true ); define( 'WP_DEBUG_DISPLAY', false ); define( 'WP_DEBUG_LOG', true );
Then I go to my WordPress wp-content directory and change the permissions of my debug.log file so that it is not readable by the public.
$ chmod 660 debug.log
After installing all my themes and plugins, I got an error message saying that I was missing the xml_parser_create PHP function, which most likely means that I am missing the php-xml module. To install it, I do:
$ apt-get install php8.1-xml $ systemctl restart apache2 $ systemctl status apache2
Make sure to restart your web server after installing new modules so that it becomes available to WordPress.
Another issue I faced due to installing the latest version of PHP is that some plugins that I use have not yet updated their code to fix deprecation warnings. In this case, there may be many deprecation warnings that appear in your debug.log file making it difficult to properly debug your website. To stop this, add the following to your theme functions.php file. Go to Appearance > Theme File Editor to edit functions.php, and add the following:
error_reporting(E_ALL ^ E_DEPRECATED);
2. Move Media Files
Go to your original server to zip up all your media files. I usually zip by year but if the zip file is too large, you may also break it up by month. I go to my WordPress /wp-content/uploads directory of my origin server. If I do not have zip installed I do:
$ apt-get install zip
To zip up files by year I do:
$ zip -r 2012.zip 2012
The -r flag gets zip to recursively include all files in the directory. You can also include multiple directories or files in your zip archive. For example, to zip multiple months, I go to wp-content/uploads/2012 and do:
$ zip -r 2012A.zip 01 02 03
This article provides many more options on how to use zip.
After I zip up all my media files, I download them onto my desktop using an SFTP client for Windows. I am currently using WinSCP. It can transfer configuration files from PuTTY so setup is very easy. Then, I use it to upload all the zips onto my new Amazon EC2 server. In order to do this, your uploads directory must have its ownership set to your sftp user, which is currently set up to be ubuntu in PuTTY. Alternatively, for added security, we may create a separate SFTP user account. More on how to setup SFTP for a new user as well as for WordPress.
After uploading all my media files to the new server, I can unzip them by doing the following: First I install zip and unzip.
$ apt-get install zip
Next, I go to my wp-content/uploads directory where I uploaded all my zips and unzip my media files there.
$ unzip -n 2013.zip
The -n flag is to indicate that there is no overwrite. I.e. if the media file already exists, do not overwrite it. We can also use the -d flag to indicate the directory we want the unzipped files to go into. For example, if we zipped by month, we can do:
$ unzip -n 2013A.zip -d 2013
If we unzipped our files in the wrong directory, that is not a problem. We can simply move our files to the right place. The following moves a directory and all sub directories.
$ mv -f origin_dir destination_dir
The -f flag overwrites existing files without prompting you. You can also use the -i flag to get prompts when a file of the same name exists.
If you created duplicate directories by mistake, you may delete them using the following:
$ rm -r dirname (recursive remove) $ rm -rf dirname (recursive force remove, i.e. no prompting)
Another useful command is the rename command. For example we may want to rename all files ending with .JPG to .jpg. To do this:
$ apt-get install rename $ rename 's/.JPG/.jpg/' *.JPG
The first part (‘s/.JPG/.jpg/’) says to substitute JPG with jpg, and the second part says which files to operate on.
If you are using the WordPress Importer plugin to import your media files, make sure to put in all your additional file sizes first, before reading in the attachment records and creating the image files. In general, the zip/unzip method is a quicker and better way of ensuring an accurate migration.
Finally, remember to remove the zip files you created or uploaded to your servers once you are done with them.
3. Export Our WordPress Database
Now it is time to export our WordPress database from our origin server. Before I do any exporting, I empty both my comments’ trash and spam folders in my origin server. Not doing so may result in a large sql dump file. Then I do the following:
$ mysqldump --add-drop-table --no-tablespaces -u wp_user -p wp_database > my_database.sql $ gzip my_database.sql
wp_user = Your WordPress database user name.
wp_database = Your WordPress database name.
my_database.sql = The name of the file to store your original WordPress database.
Now I download the database file from my origin server and then upload it onto my new Amazon EC2 instance using my handy SFTP client. To install my original database into a new server I do the following:
$ apt-get install pv $ pv mydump.sql.gz | gunzip | mysql -u root -p your_new_database
This is going to overwrite the WordPress home and siteurl with values from our origin server. Since we still need to do more testing as well as install our SSL certificates, we are not yet ready to make the full move yet, so we will want to reset the WordPress home and siteurl for our new server. I do:
$ mysql mysql> use my_new_database; mysql> UPDATE wp_options SET option_value = 'http://my_staging_domain' where option_name = "home"; mysql> UPDATE wp_options SET option_value = 'http://my_staging_domain' where option_name = "siteurl";
After doing this, test your new server by going to http://my_staging_domain/wp-admin. You may get a WordPress update your database message, which is normal. When updating is done, fully log-out and log-in again. If you have problems logging in, make sure to clear all your WordPress cookies. If you are still having problems logging in, try starting a new incognito window in Google Chrome and logging in from there.
Next, go to Settings > Permalinks and make sure that everything is set up properly. Save Changes and then test the permalinks on your new site. If you are having problems with making permalinks work, this article may help.
For WordPress permalinks to work, you will need to enable the rewrite module on your apache server and allow overrides on our virtual server directory. As a quick refresher, to enable the rewrite module in apache do:
$ a2enmod rewrite
To enable overrides, go to your virtual server configuration file in /etc/apache2/sites-available.
$ cd /etc/apache2/sites-available $ vi your_domain.conf
Make sure you have the following in your config file:
<Directory /var/www/chataboutyou> AllowOverride All </Directory>
Then restart your apache server.
$ apachectl configtest $ systemctl restart apache2
4. Transfer Plugin Config Files
Many popular plugins allow us to download our config files. Now is a good time to download plugin config files from our original server and import them into our new server. This may require new packages to get installed.
In my case, I needed to install the curl package, so I do:
$ apt-get install php8.1-curl $ systemctl restart apache2 $ systemctl status apache2
Remember to always restart your web server after installing new packages so that they will be available to WordPress.
After uploading all my plugin config files, I also upload whatever theme customization files that I have. For this to work, I will need to change ownership of my WordPress files to whatever I set my sftp user to be. At the same time, I still want to allow WordPress to be able to make necessary changes to my site. For this, I set my ownership and permission according to this Rackspace article.
I don’t create a new user, instead I set ownership to my sftp_user. I describe how I set up SFTP here.
$ chown -R sftp_user:www-data /var/www/your_domain
Then, I run the other find commands according to the Set Permissions section.
$ find /var/www/your_domain -type d -exec sudo chmod 755 {} \; $ find /var/www/your_domain -type f -exec sudo chmod 644 {} \;
I execute the other find commands accordingly for my wp-content directory. I use the w3tc plugin for caching, and it needs to have full access to its’ own cache directories. Therefore, I also do:
$ chown -R www-data:www-data wp-content/cache $ chown -R www-data:www-data wp-content/w3tc-config
5. Other Useful Migration Considerations
At this point we are done with our migration process and should have a running mirror site. After we have finished testing our staging site, we can point our DNS to our new Amazon EC2 server and update our WordPress site links by going into Settings > General and changing WordPress Address and Site Address.
Before doing so, here are a couple of useful migration considerations:
Check Disk Usage
We can check our disk usage by doing the following:
$ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 7.6G 3.3G 4.4G 44%
If we were running an old database, we may consider updating our comments’ font set. Doing so will allow our users to submit a larger set of emoticons, including those on their mobile phones.
$ mysql mysql> use my_database; mysql> ALTER TABLE wp_comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;
When I tried to do this however, I got an error on zero dates. To fix this error and update my font set, I had to take out the NO_ZERO_DATE mode from my SQL configuration as described here.
On my Amazon EC2 instance I do the following:
$ cd /etc/mysql/mysql.conf.d $ vi override.cnf
I enter the following into my override.cnf file:
[mysqld] sql-mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
NOTE that the name of my SQL config file needs to start with a letter after ‘m’ because the configuration files are read alphabetically. This article has more details. Finally, I restart my SQL server for the changes to take effect.
$ service mysql restart $ systemctl status mysql.service
If there are errors, check our MySQL log file at:
$ more /var/log/mysql/error.log
This should fix the zero date restriction.