Install WordPress on Ubuntu 18.04 with Remote DB

This post goes into documenting the installation of WordPress on a blank Ubuntu 18.04 image and utilising a remote MySQL server (db.shank.land) rather than having a full LAMP stack on the one machine.


Azure Instance

The installation of the VM that I will run WordPress on is very simple and I have initially chosen a low spec “Standard B1s” machine which provides 1 x vCPU and 1Gb of vRAM:

Azure Instance

This spec can be changed at a later date if I find WordPress is struggling for resource but based on what I have been using on AWS LightSail, I believe it will be fine.

Creation takes a few minutes and the only options I changed from the standard Ubuntu 18.04 image were to allow HTTP, HTTPS and SSH inbound ports to be open. WordPress itself will be SSL enabled but will have a redirect from anything attempting connection on TCP80 (HTTP) to be redirected to TCP443 (HTTPS). If I just blocked HTTP, this redirect wouldn’t work and anyone attempting to access just http://51.104.4.149 would get an error.

Before starting any config on the server I changed the dynamic public IP into a static one to ensure I could change the DNS entry for shank.land to point to this new IP on Azure in the knowledge it wouldn’t change on me.

Changing to a static public IP from dynamic

Once the server is provisioned and the IP statically assigned, there are just the normal bits to complete before moving onto the WordPress installation. These, for me, consist of the following:

  • Update the OS (sudo apt-get update, sudo apt-get upgrade, sudo apt-get dist-upgrade)
  • Run ‘sudo dpkg-reconfigure tzdata’ to change the timezone
  • Add into my Checkmk installation to allow monitoring

MySQL

As the title of this post suggests, rather than using a normal LAMP stack where MySQL is installed on the same server as WordPress, I decided that I wanted a separate MySQL instance so I could connect other applications into it at a later date. I also wanted to check that I could! For WordPress this doesn’t really make much of a difference except in one config file where you point to the remote server instead of ‘localhost’. I am not going to go into how I created this MySQL server now (I’ll save it for a later post) but the following commands were run on this DB server in the same way you would do if it were local to the WordPress installation.

mysql -u root -p

mysql> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

mysql> GRANT ALL ON wordpress.* TO 'wordpressuser'@'localhost' IDENTIFIED BY 'password';

mysql> FLUSH PRIVILEGES;

mysql> EXIT;

Once the above is done, all further work can be completed from the server that will be hosting WordPress.


Apache Config #1

Firstly, we need to ensure that Apache is install to actually host the WordPress installation:

sudo apt install apache2

Next, PHP has to be installed with its various components:

sudo apt install php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip

We then want to ensure that PHP files are seen as priority over anything else when someone browses to the site. To do this ensure that the file /etc/apache2/mods-enabled/dir.conf mirrors the following with index.php at the start of the list:

<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>

Restart Apache with the following command:

sudo systemctl restart apache2

We now need to create the vhost config file for Apache:

sudo vim /etc/apache2/sites-available/wordpress.conf

#paste the following into the new file:
<VirtualHost *:80>
        ServerAdmin webmaster@server.com
        DocumentRoot /var/www/wordpress
        <Directory /var/www/wordpress>
                AllowOverride All
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

We then need to enable this new configuration and disable the default:

sudo a2ensite wordpress.conf
sudo a2dissite 000-default.conf

Enable the rewrite module which is used by WordPress and various plugins and then restart Apache:

sudo a2enmod rewrite
sudo systemctl restart apache2

WordPress

Now we can install WordPress and get it configured. Firstly, download the latest version of WordPress into a temporary location and uncompress:

cd /tmp
curl -O https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz

Create the .htaccess file for WordPress to use at a later point:

touch /tmp/wordpress/.htaccess

Next, copy over the sample config file to one which WordPress can read and create the upload directory for use later before copying the entire directory into the correct location:

cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php
mkdir /tmp/wordpress/wp-content/upgrade
sudo cp -a /tmp/wordpress/. /var/www/wordpress

The following commands will set the correct permissions on the files and folders we have just copied across:

sudo chown -R www-data:www-data /var/www/wordpress
sudo find /var/www/wordpress/ -type d -exec chmod 750 {} \;
sudo find /var/www/wordpress/ -type f -exec chmod 640 {} \;

Now we need to setup the WordPress config file for our installation. The following will generate unique values which you need to place into your config file:

curl -s https://api.wordpress.org/secret-key/1.1/salt/

It is important to note that these values are specific to you and the time you ran the generator. Once you have these values you need to edit the main WordPress config file and input them:

sudo vim /var/www/wordpress/wp-config.php

You should be replacing the dummy lines that already exist within this file with the ones the generator provided.

With this file still open we can then change all of connection settings which are at the beginning of the file:

define( 'DB_NAME', 'database_name_here' );

define( 'DB_USER', 'username_here' );

define( 'DB_PASSWORD', 'password_here' );

define( 'DB_HOST', 'localhost' );

All of the above were created at the beginning of this post on the MySQL server. With utilising a remote MySQL server, the main difference from standard is to ensure DB_HOST is set to this remote box rather than ‘localhost’.

Within my Azure environment, the MySQL and WordPress servers are running on the same vnet which means that instead of using the public IP within this config file, I am using the private IP. This makes my life easier as don’t have to worry about opening ports etc as the local vnet is fairly open already and not accessible from outside. So, my config looks like:

define( 'DB_NAME', 'wordpress' );

define( 'DB_USER', 'wordpressuser' );

define( 'DB_PASSWORD', 'superSecretPassword' );

define( 'DB_HOST', '10.0.0.7' );

Now when I open up a browser and go to http://IP_Address, I should be presented with the following if everything has worked:

WordPress Installation

Apache Config #2

Before continuing with the WordPress install, it is a good time to complete SSL enabling the site using LetsEncrypt. I have used LetsEncrypt lots in the past and is a great and easy way to achieve traffic encryption without having to spend any money!!

sudo mkdir /opt/letsencrypt
cd /opt/letsencrypt
sudo wget https://dl.eff.org/certbot-auto
sudo chmod a+x ./certbot-auto
sudo ./certbot-auto

Once the required packages have been installed you will then enter the wizard which will ask you the following questions:

  • Enter an email address for renewals and security updates: <your email>
  • Do you agree with the T&C’s?: (A)gree/(C)ancel
  • Share information?: (Y)es/(N)o
  • Enter your domain name: <your domain name>
  • Auto redirect?: 1/2

Once SSL is enabled for the site we have to ensure the certificate renews as LetsEncrypt certificates are only valid for 90 days. This is simply done by adding a crontab entry:

sudo crontab -e

#paste in the following to update the certificate once a day at 1am:
0 1 * * * sudo /opt/letsencrypt/certbot-auto renew && sudo service apache2 restart >/dev/null 2>&1

Once this is complete you can now go to https://<yourdomainname> to complete the installation of WordPress.

Leave a Reply

Your email address will not be published. Required fields are marked *