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.

define('DISABLE_WP_CRON', true);

Introducing crontab

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.

crontab -e


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/; php -q wp-cron.php >/dev/null 2>&1

Some articles suggest using wget or 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/ >/dev/null 2>&1

The >/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.

Outgoing Email

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.

Start by signing up for a free account. Then verify your domain, as detailed in the Quickstart Guide.

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.

Automatic Backups

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.

mkdir backups

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


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

The last step is to schedule the backup script to run at a designated time. Begin by opening the crontab.

crontab -e

Add the following line to the end of the file.

0 5 * * 0 sh /home/ashley/

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.

About the Author

Ashley Rich

Ashley is a PHP and JavaScript developer with a fondness for solving complex problems with simple, elegant solutions. He also has a love affair with WordPress and learning new technologies.

  • Hey Ashley, Creating automated backups via Cron jobs looks great. Thanks for the tutorial. Maybe you can add ability to deploy backups at a staging server?

  • Paul Vincent

    Looking forward for the next part, especially SSL, when will you post it? 😉

  • Yoyo

    brilliant and helpful post… Thank you for this great series. May I ask if this: “12,000 emails each month” is actually correct? I see this: “You’re currently on our free trial plan that includes 2,000 total sends and 30 days of technical support.” maybe Mandrill has changed it’s offerings??

    • Yoyo

      Mailgun looks promising:

      • Sam

        I’m a huge fan of Mailgun

    • Good spot. It seems Mandrill have updated their pricing structure. It looks like existing accounts still receive the 12,000 free emails, but new customers only get 2,000.

      Mailgun might well be a better solution.

  • Sam

    One of the best tutorials I’ve read. Learnt a ridiculous amount and now have a series of websites that perform better than I could of imagined. Thank you!

  • Helms

    Hey Ashley. Any news on when Part 6 SSL & SPDY setup will be posted? Need that tut and your tuts are tiptop. Thanks for taking the time!

  • Land

    Thanks for the article. If WP user’s hosting doesn’t support Cron, or its Cron service is crap, we can use or WP plugin

  • Rajiv

    Great tutorials, I am a non tech guy but with the help of this tutorials I am able to install my 1st WPMU … thanx…
    But one problem I don’t know the issue I am not able to update or download any pugins from the wp, when I am going to do this wp required a

    Connection Information

    To perform the requested action, WordPress needs to access your web server. Please enter your FTP credentials to proceed. If you do not remember your credentials, you should contact your web host.
    where I need to give hostname, FTP username & Password.

    Can anybody help me on this…..

    • It sounds like you need to change ownership of the site’s root directory to the user running PHP, e.g.:

      sudo chown user:user

  • Hello;

    Waiting for the improved version

  • alexhaworth

    Hey Ashley. I’m getting a 504 error when trying to install mandrillwp… all the other settings went swimmingly but after activating mandrill I try to pop the auth key in and it hangs… then I get 504’s until I remove the plugin… it’s strange as I can’t see any wp error being spat out in the log and I use mandrillwp religiously on all my other sites…

    I thought it maybe a permissions issue but it doesn’t look like it… I was wondering if you could think of any reason this could happen?

    I noticed sendmail had an error message when adding wp cli but I guess this is ok to ignore since I won’t be using that service at all and isn’t related?

    Thanks again for a great article.. I’m trying to make this into a CHEF config at the moment 🙂

    • That’s strange indeed, I use wpMandrill on this setup all the time. A 504 error is usually indicative of timeouts with FastCGI. Does anything in this topic help:

      • alexhaworth

        Hey Ashley – sadly I tried those steps already from my googling.. it didn’t seem to make any difference – do you think theres another file that those settings are being defined afterwards with this specific version of php-fpm or nginx?

        Super strange as I followed all the steps faultlessly to a t and I’m using a 4gb vultr setup which I’d assume will have more than enough umpf!

  • George Teichmann

    Great series of posts! Very Helpful! I apologize if you mention it, but can I set up the Cron system you discuss in this post on an Ubuntu based server?

    • Thanks George! Yeah, the server in this series is running Ubuntu so the steps will be the same.

  • Oliver White

    hi there,

    what’s the purpose of using mandrill? if we could simply install “sendmail” ? it should handle all system emails. This will also reduce WP plugins installed 😉

  • Hello Ashley, thank you for this tutorial! It’s amazing!
    I made everything as you said, but i don’t get backups automatically for my DB, i’m getting backups from the site though. Any thoughts on why ?

  • Hello!

    I want make just a week backups. And, how I make backups every 2 days?

  • Thank you very much Ashley for the posts. @anyone – For mandrill, we create one api for each website?

  • megab

    Excellent Guide! My WordPress is flying now 🙂
    Just one questions. Is it possible to adapt your backup script to use Google Drive?


  • Vasilis

    Hello, nice tutorial. Do you suggest to use mailgun for the outgoing messages and G Suite for the incoming messages, in order to avoid setting up a mail server? I integrated my wordpress installation with mailgun but I am not sure what I should do with the incoming messages (since it is an e-shop I am expecting emails)?
    Thank you in advance.

  • Keerthan Koundinya

    Hello Ashely, Thank you for such a wonderful tutorial. I just have one issue with the backup script. The wp-content backup is getting generated but my DB backup is not. Kindly help me with this.

    • Kevin Sears

      Ah yes, I had this issue too.

      Crontab doesn’t seem to know about the WP command so reference WP-CLI directly.

      wp db export ../backups/`date +%Y%m%d`_database.sql –add-drop-table
      /usr/local/bin/wp db export ../backups/`date +%Y%m%d`_database.sql –add-drop-table

      Worked for me