LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

How to Setup a Highly Available WordPress Site From Scratch, Part 2

Tags: , , , , Date/Time: December 18, 2020 @ 12:00 am, by raindog308

How to Setup a Highly Available WordPress Site From Scratch, Part 2In this tutorial series, we are setting up a highly available WordPress web site from scratch.

Part 1 – Introduction, Considerations, and Architecture
Part 2 – Setting Up the VPSes
Part 3 – Setting Up MariaDB Multi-Master Replication
Part 4 – File Replication and Setting Up DRBD
Part 5 – Setting Up OCFS2
Part 6 – Round-Robin DNS, Let’s Encrypt, & Conclusion

Setting Up the VPSes

Here is our setup:

  • web1.lowend.party and web2.lowend.party are the two nodes, both running Debian 10 x64. 
  • www.lowend.party will be the URL that is highly available.
  • We’re using WordPress 5 running on MariaDB.  Since this is a tutorial on HA and not on web design, we’re just going to use the stock WP theme and not spend much time on prettifying the site.
  • In this tutorial, I will use 1.1.1.1 to represent web1.lowend.party’s IP, and 2.2.2.2 to represent web2.lowend.party’s IP.

Here is a checklist of what was done to setup the web sites.  This was done on both nodes.  Note that there are many other things one should do for a production site – setup an active firewall, setup backups, configuring mail, etc.  But this is just a tutorial focused on HA WordPress.

DNS is not listed as we’ll cover that in more detail.

The checklist:

  • provisioned the VPSes (with embedded ssh key for root)
  • dpkg-reconfigure locales (or use locale-gen)
  • dpkg-reconfigure tzdata (to set my preferred timezone, or you can use timedatectl)
  • set hostname in /etc/hostname (a Linode-ism)
  • apt-get update && apt-get -y upgrade
  • apt-get install nginx mariadb-server php-fpm php-mysql
  • ran mysql_secure_installation

Database Setup

I created a database and user for WordPress on both nodes:

# mysql

MariaDB [(none)]> create database wp;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> create user 'wp'@'localhost' identified by 'complexpassword';
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> grant all on wp.* to 'wp'@'localhost';
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.000 sec)

Web Site (nginx) Configuration

I created /web/www.lowend.party as my web root created appropriate log files in /var/log/nginx and set /etc/logrotate.d to handle them:

# mkdir -p /web/www.lowend.party
# mkdir -p /var/log/nginx/www.lowend.party
# chown www-data:adm /var/log/nginx/www.lowend.party/
# cp /etc/logrotate.d/nginx /etc/logrotate.d/nginx_web_dirs
# sed -i 's#nginx/\*.log#nginx/\*/\*.log#' /etc/nginx/nginx_web_dirs

That last sed command changes “/var/log/nginx/*.log” to “/var/log/nginx/*/*.log” so the per-domain logs in /var/log/nginx/www.lowend.party are rotated.

Next I setup the nginx config as follows.  This is using php-fpm for php support.  Here is /etc/nginx/sites-available/www.lowend.party:

server {
  server_name www.lowend.party;
  access_log /var/log/nginx/www.lowend.party/access.log;
  error_log /var/log/nginx/www.lowend.party/error.log;

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/run/php/php7.3-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param  SCRIPT_FILENAME  /web/www.lowend.party$fastcgi_script_name;
  }

  location / {
    root   /web/www.lowend.party;
    index  index.php index.html;
    try_files $uri $uri/ /index.php;
    if (!-e $request_filename) {
      rewrite . /index.php last;
    }
  }
}

Note that we’re not doing https yet.  Fear not – we will get there but not until we’ve got DRBD up and running.

Finally I brought the site up:

# ln -s /etc/nginx/sites-available/www.lowend.party /etc/nginx/sites-enabled/www.lowend.party
# systemctl restart nginx

Setting up WordPress on web1

Setting up WordPress itself is quite simple, but how to get it up and running when we haven’t created the www.lowend.party record yet?  The easiest way was to manipulate my local PC’s hosts file to override DNS

On Windows this would be c:\windows\system32\drivers\etc\hosts while on Mac or Linux it’s /etc/hosts.  I created this temporary entry:

1.1.1.1  www.lowend.party

Then ran the WordPress installer.  It’s just answering questions but if you need a guide, one is available from wordpress.org.  https://wordpress.org/support/article/how-to-install-wordpress/

In the words of Bon Jovi, whoa-oh, we’re halfway there.  WP is up and running on one node.  What about the next one?

Setting up WordPress on web2

There’s no need to setup everything on web2 manually.  They’re both the same distro running the same software.

Copy over the web directory.  On node1:

scp -rp /web web2.lowend.party:/

Copy over the nginx site definition:

scp /etc/nginx/sites-available/www.lowend.party web2.lowend.party:/etc/nginx/sites-available

Setup logging on web2:

# mkdir -p /var/log/nginx/www.lowend.party
# chown www-data:adm /var/log/nginx/www.lowend.party/
# cp /etc/logrotate.d/nginx /etc/logrotate.d/nginx_web_dirs
# sed -i 's#nginx/\*.log#nginx/\*/\*.log#' /etc/nginx/nginx_web_dirs

Make the site live on web2:

# ln -s /etc/nginx/sites-available/www.lowend.party /etc/nginx/sites-enabled/www.lowend.party
# systemctl restart nginx

Copying the MySQL Database

On web1, backup the WordPress database using mysqldump:

mysqldump wp > /tmp/wp.sql

Create the WordPress database and user on web2:

MariaDB [(none)]> create database wp;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> create user 'wp'@'localhost' identified by 'complexpassword';
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> grant all on wp.* to 'wp'@'localhost';
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.000 sec)

Now restore the wp database:

# mysql wp < /tmp/wp.sql

I then changed my local hosts file to point at web2, and the site looks identical to how it will appear on web1.

At this point, we have WordPress up and running on two sites.  If this was a static site, we’d be done.  But because we’re using WordPress, we need to make both the database and web filesystem (where themes, uploads, etc. are stored) synchronized.

Next Part: Part 3 – Setting Up MariaDB Multi-Master Replication

I'm Andrew, techno polymath and long-time LowEndTalk community Moderator. My technical interests include all things Unix, perl, python, shell scripting, and relational database systems. I enjoy writing technical articles here on LowEndBox to help people get more out of their VPSes.

No Comments

    Leave a Reply

    Some notes on commenting on LowEndBox:

    • Do not use LowEndBox for support issues. Go to your hosting provider and issue a ticket there. Coming here saying "my VPS is down, what do I do?!" will only have your comments removed.
    • Akismet is used for spam detection. Some comments may be held temporarily for manual approval.
    • Use <pre>...</pre> to quote the output from your terminal/console, or consider using a pastebin service.

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