Hosting WordPress Yourself Part 5 – Cron, Email and Automatic Backups
In the previous installment of this series, I walked you through the process of setting up server monitoring and caching. In this post I will demonstrate how to configure cron, outgoing email and automatic backups.
WordPress has built-in support for scheduled tasks, which allows certain processes to be performed as a background process at designated times. Out of the box WordPress performs the following scheduled tasks:
- Automatic updates which are pushed out by the WordPress core team to fix security vulnerabilities.
- Check WordPress is running the latest stable release.
- Check for plugin updates.
- Check for theme updates.
- Publish any posts scheduled for future release.
However, the cron system used by WordPress isn’t the most performant or accurate of
implementations. Scheduled tasks within WordPress are triggered during the lifecycle of a page request, therefore if your site doesn’t receive any visits for a set period of time, no cron events will be triggered during this time. This is also true of sites that use full page caching, such as Nginx FastCGI, which was introduced in the previous post. The reason for this is that WordPress is no longer processing each page request if the page cache is hit. Generally, this means that cron will not fire until the page cache expires. If you have have configured the cache to expire after 60 minutes this may not be an issue, however, if you are caching for longer periods of time this may become problematic. Other issues can arise on high traffic sites, where full page caching isn’t an option. This is due to needlessly checking the cron queue on every single page request, which is very inefficient.
To overcome these issues it’s advised that cron is configured using the system daemon (background process), which is available within Unix based systems. Because cron runs as a daemon it will run based on the server’s system time and no longer requires a user to visit the site. Before configuring cron it’s recommended that you disable WordPress from automatically handling cron. To do so add the following line to your wp_config.php file.
Cron events are added to a text file called crontab and each line within the file equates to a single cron event. If your server hosts multiple sites you will need one entry per site.
Begin by connecting to your server.
Open the crontab using the following command. If this is the first time you have opened the crontab, you may be asked to select an editor. Option 2 (nano) is usually the easiest.
I’m not going to go into detail on the crontab syntax, but adding the following to the end of the file will trigger cron every 5 minutes. Just remember to update the file path to point to your WordPress install and that each site has a separate entry.
*/5 * * * * cd /home/ashley/ashleyrich.com/public; php -q wp-cron.php >/dev/null 2>&1
Some articles suggest using
curl for triggering cron, but calling PHP on the command line is often more flexible. The reason for this is both Wget and cURL are bound to the same timeout limits as normal user requests. However, in some situations you may want your cron jobs to run for longer periods of time, for example if you’re performing background processing. By default CLI scripts have no timeout limits and will execute until complete.
You may be wondering why I
cd into the directory and then run wp-cron.php. This is due to how older versions of WordPress used relative paths for including files, as seen here. The following should be safe to use on WordPress versions 3.7 or later:
*/5 * * * * php -q /home/ashley/ashleyrich.com/public/wp-cron.php >/dev/null 2>&1
>/dev/null 2>&1 part ensures that no emails are sent to the user account initiating the cron job.
Save the file by hitting CTRL X followed by Y.
Cron is now configured using the Unix native cron tool, but I’ll demonstrate how to check it’s running correctly later on.
Email servers are notoriously difficult to setup. Not only do you need to ensure that emails successfully hit your recipients inboxes, but you also have to consider how you’ll handle spam and viruses (sent as email attachments). Installing the required software to run your own mailserver can also eat up valuable system resources and potentially open up your server to more security vulnerabilities. This article over at DigitalOcean discusses in more detail why you may not want to host your own mailserver.
For that reason I do not recommend that you configure your server to handle email and instead use a ‘best of breed’ service provider, such as G Suite. However, WordPress still requires a method for sending outgoing emails. Depending on the type of site you’re hosting they’re used in various situations:
- Admin notifications
- New user signups and password resets
- Order updates (WooCommerce etc)
Before moving on, you must have a valid email address to be used as the reply to address.
Although you can configure WordPress to use an outgoing SMTP server provided by your email service provider, I prefer to use Mailgun, which is a product by Rackspace. In addition to simplifying the setup process Mailgun provides statistics on how many emails are delivered, bounced or rejected. It’s also free for your first 10,000 emails each month.
Visit the API Keys page and copy your Active API Key.
Login to your WordPress site and head over to the Add Plugins page. Search for “Mailgun for WordPress” and install the plugin. Navigate to the Mailgun screen from within the Settings menu and enter your domain name, API key and sender email address.
Job done. Emails will now get routed through Mailgun’s mail servers.
Testing Cron and Outgoing Email
In order to test that both cron and outgoing emails are working correctly, I have written a small plugin that will send an email to the admin user every 5 minutes. Obviously this isn’t something that you’ll want to keep enabled indefinitely, so once you have established that everything is working correctly, remember to disable the plugin!
Create a new file called cron-test.php within your plugins directory, with the following contents:
Upon activating the plugin, you should receive an email shortly after. If not, check that the crontab configuration and Mailgun credentials are correct.
Performing backups on a regular basis is essential. It’s inevitable that at some point in the future you will need to restore data – whether that be due to user error, corruption or a security breach. You never know what could go wrong, so having a recent backup to hand can really make your life easier as a system administrator. There are generally two types of backups I like to perform. The first is a full system backup and the second is a backup of each individual site hosted on the server.
Full system backups are best performed by your VPS provider, and both Digital Ocean and Linode offer this service for a nominal fee. This sort of backup is generally only used when a catastrophic failure occurs, as it’s not usually desirable to restore the entire system if only a single site needs restoring, hence the reason for single site backups.
Single site backups only backup the items required to restore a single site and in terms of WordPress this usually consists of the database and the uploads directory. If you’re using a plugin such as WP Offload S3, you can skip the need to backup the uploads directory as the files are automatically sent to Amazon S3 when added to the media library.
For sites that aren’t updated often a weekly backup should suffice, but you may want to perform them more frequently. For example, the backups on this site are performed every 2 hours because changes occur more often due to new orders and product activations.
To setup single site backups, first create a new directory within the site’s root directory.
This will sit along side the existing cache, logs and public directories, which is standard I like to follow with all self hosted sites.
Now create a new file called backup.sh.
Paste the following contents into the file, ensuring you update the path to your site.
Hit CTR X followed by Y to save the file.
Ensure the newly created file has execute permissions.
chmod u+x backup.sh
The last step is to schedule the backup script to run at a designated time. Begin by opening the crontab.
Add the following line to the end of the file.
0 5 * * 0 sh /home/ashley/ashleyrich.com/backup.sh
This will run backups every Monday morning at 05:00, server time. Just remember that you’ll need to add this script and crontab entry for each individual site you wish to backup. In a future post, Brad will demonstrate how to send the backup files to Amazon S3 and remove those that become redundant.
That concludes part 5. In the next post I’ll show you how to setup HTTPS which will encrypt data sent between your server and the web browser.
If you handle email or backups differently, let me know in the comments.