So you’ve followed our in-depth guide and built yourself a shiny new web server that’s secure and tuned for optimal WordPress performance, but what’s next?

In this chapter I’m going to outline a few tasks that should be carried out on a regular basis to ensure that your server continues to run securely and perform well. We’ll look at performing software updates, upgrading PHP, and a few “gotchas” to watch out for that we may have experienced ourselves.

But first, let’s start with server monitoring.

Server Monitoring

As I’m using DigitalOcean, performance monitoring for my server is a relatively simple process thanks to the built-in server monitoring tools. For those not hosting with DigitalOcean, Netdata and SolarWinds Observability are other options.

If you enabled monitoring during the Droplet creation, then you’re good to go! Otherwise, you’ll need to install DigitalOcean’s metrics agent manually.

Once installed, you should see the Droplet’s current resource utilization graphs when visiting the Droplet dashboard.

Monitoring dashboard

Alert Policies

Alert policies are extremely useful, and you should configure them for all production Droplets. Alerts reduce the need to manually check your server’s health by sending a notification when one of your chosen metrics reaches a certain threshold.

Head to the Monitoring tab and click Create alert policy.

Create alert policies

Here you can create as many alert policies as required. I like to set up alerts for CPU, memory and disk utilization with a threshold of 80%, which is a good starting point for most people.

Alert policies list

Investigating Alerts

A high resource usage alert can be the first sign that something is wrong with your server or the applications that it’s running. To investigate, SSH into your server:

ssh abe@pluto.turnipjuice.media

Run htop to have a look at the system resource usage in real-time:

htop

Screenshot of a terminal window showing htop.

The above screenshot is sorted by memory usage, so if the alert you’re investigating was about high memory usage, you should have a visualization of the processes that are eating a lot of your memory at the top of the list. If you’re investigating an alert about CPU, you’ll need to change the sort column by hitting the F6 key.

If it’s Nginx or PHP appearing at the top of the list, you should have a look at your access and error logs. If it’s MySQL, you’ll need to enable the slow query log to investigate or use an application monitoring software tool like New Relic. In fact, we have a comprehensive guide on debugging a slow WordPress site with New Relic. Other monitoring tools include Grafana and Nagios.

Recently, we were receiving high CPU alerts from our VPS provider. After performing some application monitoring using New Relic, we discovered that a database query was running slow, which was causing MySQL to spike CPU usage. It turns out we were missing an index on one of our database tables. Adding the index resulted in a big drop in CPU usage:

CPU spike

If the alert is for high disk utilization, you’ll need to check your disk space usage to find out which files are taking up a lot of space on your server.

Site Monitoring

Equally important to server monitoring is site monitoring, making sure your site is running in addition to your server. For example, your server could be running just fine, but the PHP-FPM process failed and so your WordPress site is showing an error on all pages that are page cached. With server monitoring properly set up, you’ll receive an alert as soon as PHP-FPM fails.

We have basic site monitoring built-into our platform so if you sign up for the right SpinupWP plan, you get site monitoring. If you’re not using SpinupWP, you could try Oh Dear! or Pingdom.

Keep Plugins and Themes Updated

Let’s start with an easy one that isn’t just applicable to self-hosted WordPress installs. WordPress itself, WordPress themes, and all plugins should be regularly updated. No software is immune to vulnerabilities and updating often will ensure those inevitable vulnerabilities are patched.

While you’re at it, make sure you delete obsolete themes and plugins. There’s no reason to keep them around, other than to provide a potential entry point for malicious users. The majority of premium plugins and themes won’t receive updates via the WordPress dashboard if they’re deactivated. For that reason, it’s better to delete them than leave them lying around.

Check Backups are Running

It’s inevitable that things go wrong, sometimes horribly. Regular site backups are an integral part of any disaster recovery process. In chapter 6, I demonstrated how to set them up. However, you need to ensure that they are running as expected months down the line.

Earlier this year, we noticed that our site backups hadn’t made it to S3 for almost two months. The cause? Our backup script had stopped working due to a Python dependency issue. The moral of the story? Schedule a recurring time to verify that backups are being carried out. You should also periodically test the backups by importing the SQL into a test database to ensure they’re usable if things were to go wrong.

Watch Those Log Files

Just like server monitoring, log files can help to identify issues early on before they become catastrophic. Every once in a while it’s worth checking the logs to see at a glance if anything unusual is happening. I would concentrate on the following:

We use Papertrail to make it easier to monitor those log files (especially debug.log, which we have permanently enabled). What makes Papertrail ideal is that you can easily send certain logs to Slack. We have an alert configured for any fatal errors that occur.

Set Up Persistent Debug.log

Enabling debug.log for live sites is often discouraged. This is because, by default, the log is stored in a publicly accessible location. This can expose potentially sensitive information about your server to would-be hackers. However, this log can be critical for helping track down obscure errors in production environments.

We can get the benefits of a persistent log while avoiding the risks by moving it to a new location and denying public access to all log files. To move the log files alongside other logs, update your wp-config.php with the following lines:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', ‘/sites/globex.turnipjuice.media/logs’ );

Next, configure Nginx to disallow access to .log files. Add the following Nginx location block to your site’s Nginx config file, in my case /etc/nginx/sites-available/globex.turnipjuice.media. You should place this block inside the main server block, just before the location / block:

# Prevent access to certain file extensions
location ~\.(ini|log|conf)$ {
    deny all;
} 

Enable Logrotate

Log files themselves can become problematic if left unchecked. One downside to most VPS providers is that they provide a limited amount of disk space, which means the logs can quickly fill the server’s storage. In the past, I’ve had a server completely fall over because a log file grew to over 25 GBs in size.

One way to help prevent this is to enable log rotation, available by default on servers running Ubuntu 16.04 or higher through the logrotate command. This will rotate (rename), compress, and remove old log files to prevent them from eventually consuming all of your disk space. The default configuration located in /etc/logrotate.conf rotates logs weekly and removes log files older than 4 weeks. This configuration handles logs in the /var/logs directory.

To create a site-specific logrotate configuration, add a new file to the /etc/logrotate.d/ directory, named after your specific site.

sudo nano /etc/logrotate.d/globex.turnipjuice.media

For example, this is what the contents of /etc/logrotate.d/globex.turnipjuice.media looks like:

/sites/globex.turnipjuice.media/logs/*.log {
    daily
    rotate 14
    size 1M
    compress
    missingok
    notifempty
    dateext
    create 0664 abe abe
    sharedscripts
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

Below are the details of each of the options used above:

  • daily: perform the rotation every day
  • rotate 14: remove the log files after 14 days
  • size 1M: only rotate logs that are a minimum of 1MB
  • compress: all rotated logs will also be compressed
  • missingok: prevent errors from being thrown if the log file is missing
  • notifempty: prevent empty logs from being rotated
  • dateext: use the date as a suffix of the rotated files
  • create: create a new log file with a specific name and permissions after rotating the old one

Finally, once the logs are rotated, any commands configured from the command line in the postrotate script will be run once at the end.

Update Server Packages

If you followed along with this guide, you would have configured automatic security updates using unattended-upgrades, which will apply security updates on a daily basis. However, it won’t install general software updates that contain new features and bug fixes. If you SSH into your server you’ll often be presented with the following:

Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-36-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Thu Jun 27 14:05:30 EDT 2024

  System load:  0.0               Processes:             108
  Usage of /:   6.1% of 47.39GB   Users logged in:       0
  Memory usage: 33%               IPv4 address for eth0: 104.236.70.190
  Swap usage:   0%                IPv4 address for eth0: 10.17.0.5

Expanded Security Maintenance for Applications is not enabled.

6 updates can be applied immediately.
To see these additional updates run: apt list --upgradable

6 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm


*** System restart required ***

Those packages won’t automatically get updated because they don’t contain security fixes. To update them, run:

sudo apt update
sudo apt dist-upgrade

It is recommended to use apt dist-upgrade vs. apt upgrade because it will intelligently handle dependencies.

Before performing any upgrades, you should create a full system backup (a.k.a. snapshot) via your VPS provider.

Upgrade PHP

The previous step will update PHP through the point releases (e.g. 8.0.0 to 8.0.25), but it won’t upgrade PHP to a new major version (e.g. 8.3).

If you’re using the ppa:ondrej/php repository as we have throughout this guide, you can safely install multiple major versions of PHP side-by-side, avoiding any disruption to the uptime of the sites running on the server. You only need to follow these steps if your server isn’t already running PHP 8.3.

sudo apt update
sudo apt install php8.3-fpm php8.3-common php8.3-mysql \
php8.3-xml php8.3-intl php8.3-curl php8.3-gd \
php8.3-imagick php8.3-cli php8.3-dev php8.3-imap \
php8.3-mbstring php8.3-opcache php8.3-redis \
php8.3-soap php8.3-zip -y

Next, you should configure the new version of PHP as demonstrated in chapter 2. Remember to also copy any modifications from your existing php.ini file, found at /etc/php/{PHP VERSION}/fpm/php.ini.

At this point, you’ll have multiple PHP versions installed, but Nginx will still pass requests to the older version. Next, update your site’s Nginx config so that the fastcgi_pass directive passes requests to PHP 8.3.

sudo nano /etc/nginx/sites-available/globex.turnipjuice.media
location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
}

Test that your config changes are correct, then restart Nginx.

sudo nginx -t
sudo service nginx reload

Visit Site Health under Tools in your WordPress dashboard to ensure the site is now running on PHP 8.3. Once confirmed, repeat the changes for each site on the server. Ideally, you’ll perform these changes on a staging site and test the critical paths before updating any production sites.

Once you’ve moved all your sites on to the latest version of PHP, you can remove the old version of PHP.

What About Updating Ubuntu?

Ubuntu releases a new LTS version every two years, the most recent of which is 24.04, released on April 25, 2024.

So should you update to a new LTS version as they’re released?

It’s a question often debated, and you’ll get different recommendations depending on who you ask. Personally, I don’t ever upgrade a server’s operating system (OS).

An OS upgrade can be a slow process to complete (think about the last time you updated your computer to a new major release of macOS, Windows, or Linux systems). During this time your sites will be completely inaccessible.

There’s also a good chance that some existing server packages won’t be compatible with the new version of the OS. This can further increase downtime as you scamper to rectify such issues.

Spinning up a fresh server and migrating sites is a much safer approach. Doing so allows you to test that everything is fully working as expected. A clean slate is also an excellent opportunity to reassess if your current setup still meets your needs or if a different server stack might be more suitable. You can safely try these changes without impacting your live sites.

Once you’re happy with the new setup, you can switch your DNS over with minimal downtime.

Action Plan

I’ve covered the various tasks that should be carried out on your server, but how often should these tasks be performed? I recommend that you perform the following tasks once a month:

  • Perform WordPress updates, including themes and plugins
  • Ensure backups are running and that they’re usable
  • Check your server metrics to see if there were any unusual spikes
  • Quickly scan your server’s error logs for problems
  • Update server packages

As for upgrading to a new version of Ubuntu, you should definitely be aware of the end-of-life date of your version of Ubuntu. At that point there will be no further updates released of any kind including security updates. You should definitely move all your sites to a fresh server and decommission the old server before that date. We typically provision a fresh server roughly every two years, generally after a new LTS release.

That’s all for this chapter. In the next chapter you will be able to snag a complete set of Nginx configuration files optimized for WordPress that we’ve been building throughout this guide.