Late last night, just as I completed my post about Tesla trying to scam me, I decided to upgrade WordPress to version 5.4. Normally, this shouldn’t be an issue, but for me, since I run a multisite system, there are extra security issues and directory layout complications that must be taken into account.
The first step was, apparently, to backup my database. Since I’ve never backed up the mysql database before, I felt this seemed like a reasonable approach. I certainly didn’t want to pay JetPack to do it; I’m a genuine code jockey, I can do my own backups. After some digging around, I found mysqldump
. Unfortunately, all the instructions on how to use it were incorrect.
After some further poking around, I finally came across the correct syntax. Essentially, the user name and host have to come before the --all-databases
command. Also, the host can’t be localhost
, it must be the IP for the local host. Unfortunately, I was not able to find a way to get it to prompt for my password which meant I had to type my password in the command line, leaving all there in the open for any history
recall to see. Not very secure at all.
mysqldump -h 127.0.0.1 --user=<uid> --password=<pw> --all-databases > mysql.2020.03.31.bak
mysqldump
command; note<uid>
and<pw>
are placeholders for the user name and password; you must replace this with your own values.
Alas, I was not able to find a way to get mysqldump to prompt for a password. I think if I have more time, I may write a python script which builds the command by first prompting for the password. At least that way, the password wouldn’t be stored in the command line history.
The mysqldump
command is quite clever. It just stores the list of sql commands that would be required to recreate the databases you have stored. However, the file is rather big and being text, it compresses nicely with bzip2 -9
, which is what I did.
Once I did this, I was ready for the main Upgrade. I held my breath and pulled the trigger…
The install progressed along nicely until it tried to write a file to the wordpress directory. 🤦🏻♂️ I logged into my server and sure enough, the permissions on the wordpress directory were 755
, which meant the user could add and remove files, but the group and anyone else could not. You see, with my multisite, I try to have all wordpress files with user wp-user
and group as www-data
, to work with apache. And apache runs all web processes as www-data
for both user and group. Thus, when WordPress asked to add a file to its codebase, apache could not write it because the www-data
group didn’t have permission, only wp-user
did.
Change all the wordpress directors to allow
find /usr/share/wordpress -type 'd' -print0 | xargs -0 sudo chmod 775
www-data
to add and remove files from them.
Realizing my mistake, I changed the permissions on all directories to be 775 (both wp-user
and www-data
could add and remove files). Unfortunately, it was too late. Instead, I had no choice but to blow away my current install and replace it with a fresh, new install of WordPress 5.4. At least, that’s what I did on a high level. The details, though, are a bit more complex.
Once I extracted all the wordpress files, I needed to get their ownership to match the settings for my wordpress install. I was able to do this quite easily with the chown
command.
Command to set the right file ownership for wordpress.
sudo chown -R wp-user:www-data wordpress/
Next, I set the directories as above. Finally, the files themselves had to have the right permissions. Namely, they should be readable and writable by wp-user
and the www-data
group, but only readable to others, not writable. Namely, they needed to be set to permission 664.
Change all the wordpress files to allow
find wordpress/ -type 'f' -print0 | xargs -0 sudo chmod 664
www-data
to modify them.
Next, I had to copy over the active wordpress configuration file. This file is actually fairly spartan as all the active site configurations are actually stored in /etc/wordpress
; my wp-config.php
actually just scans this directory for configurations. The configurations, in turn, point to directories in /srv/www/wp-content
with the site-specific files. I thuns needed to bring that file over to the new install.
Copy the configuration to the new wordpress install.
cp /usr/share/wordpress/wp-config.php wordpress
Next, I wanted to preserve the Languages I had installed. I just copied the entire directory over to the local install.
Copy the Languages directory to the wordpress install.
cp -r /usr/share/wordpress/wp-content/languages wordpress/wp-content/
I also have an upgrades
directory that I wanted to preserve.
Copy the Upgrades directory to the wordpress install.
cp -r /usr/share/wordpress/wp-content/upgrades/ wordpress/wp-content/
Finally, I needed to move the links to my shared, dynamic contents that are for all the sites on my server. Specifically, the uploads
, themes
, and plugins
folders all rest in /var/lib/wordpress/wp-content
. (Technically, Uploads rests in blog.restonwriters.org site-specific Uploads directory, but that’s something I’ll fix later to conform with the same layout Themes and Plugins use.) Since these are already symbolic links, they can be moved to the new wordpress install directory to replace the defaults.
One caveat however, is the default install for wordpress comes with one plugin and three themes. In order to preserve those, I renamed the default plugins
directory to plugins-default
, and the default themes
directory to themes-default
. This was necessary before the symbolic links could be moved since those directories were in the way.
Move the symbolic links to the
mv /usr/share/wordpress/wp-content/uploads wordpress/wp-content
mv /usr/share/wordpress/wp-content/plugins wordpress/wp-content
mv /usr/share/wordpress/wp-content/themes wordpress/wp-contentplugins
,themes
, anduploads
directories.
Finally, the apache permissions file needed to be moved as it was also a link, pointing to /etc/wordpress/htaccess
. I store the file there because it makes it easier to maintain in case I accidentally bow the .htaccess
file away.
Move the symbolic link to the
cp /usr/share/wordpress/.htaccess wordpress
.htaccess
file.
Once all this is done, it’s a good idea to run the chown
and chmod
commands from above on the wordpress install directory once more to make sure the copied files and moved links are also properly attributed.
Finally, it was time to perform the brain transplant and move my staged wordpress install to the active /usr/share/
directory. I moved the current install to a temporary directory and then moved my staging install to the /usr/share/
directory to replace it.
Replace the installed wordpress with the new version.
mv /usr/share/wordpress /usr/share/wordpress-old
mv wordpress /usr/share/wordpress
Once all this was done, I was able to get to my web page, and wordpress prompted me to upgrade my database. Once this was done my sites were back online. In total, this site and its sister sites were down for a total of about forty-five minutes. It was a long day yesterday and I was exhausted but I did get it done and you can now see the results.
I hope you enjoyed my story about hacking UNIX. Please note, I am available for hire if you like what you see!