How to Automate cPanel Backups in WHM

I built a playlist on YouTube, talking about how I earn passive income by selling hosting accounts via a Reseller. Right now, a couple thousand dollars per month passively. To my surprise, that playlist has blown up, and many people have found it incredibly useful. However, one of the most frequent questions I get is “How can I automate backups in cPanel?

I, too, had this problem when I first began selling hosting accounts. cPanel offers a way to take backups, but it’s not automated. And I currently have around ~75 clients, which would make it very difficult for me to take manual backups of each website on a weekly basis. Searching Google didn’t come up with much, so instead, I generated my own two-part script.

Both of these scripts are scheduled via cronjob. The first script generates a tar file with a full backup of the site (including all files and database dumps). The second script then takes that backup, and automates the upload from my reseller server to an S3 bucket for safe keeping.

cronjob

Setting up the script is easy. Create a PHP file called “backup.php”, and save it to the main hosting account inside your WHM panel. From there, I have it set to run once per week:

<?php

$theme = "paper_lantern";
$ftp = true;
$ftp_server = "myserver.mycoolserver.com";
$ftp_username = "ftpusername";
$ftp_password = "ftppassw0rd";
$ftp_port = "21";
$ftp_directory = "/backups";

## Get a list of all accounts
$url = "https://<your_whm_url>:2087/json-api/listaccts?api.version=1&want=user,domain";
$headers = array(
'Authorization: whm <your_whm_username>:<your_whm_api_key>'
);

// Send request to Server
$ch = curl_init($url);
// To save response in a variable from server, set headers;
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Get response
$response = curl_exec($ch);
// Decode
$accounts = json_decode($response, true);

#count the total number of accounts
$numAccounts = count ($accounts['data']['acct']);

#loop through accounts, create backup, upload
for($i=0; $i < $numAccounts; $i++) {
$accountName = $accounts['data']['acct'][$i]['user'];
$domain = $accounts['data']['acct'][$i]['domain'];
$auth = base64_encode($accountName.":<cpanel_password_here>");

$url = "https://". $domain . ":2083/frontend/" . $theme . "/backup/dofullbackup.html";
$data = array();
if ($ftp) {
$data["dest"] = "ftp";
$data["server"] = $ftp_server;
$data["user"] = $ftp_username;
$data["pass"] = $ftp_password;
$data["port"] = $ftp_port;
$data["rdir"] = $ftp_directory;
}

$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\nAuthorization: Basic $auth\r\n",
'method' => 'POST',
'content' => http_build_query($data)
),
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);

try {
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
} catch (Throwable $t) {
// you may want to add some logging here...
continue;
}
}
?>

I’ve bolded the text above, in all the locations where you need to replace the values with your own inputs.

For the above script to work, you’re going to need a WHM API Key so that the script can gain access to all your cPanel accounts. You can generate that API key within your WHM panel using the “Manage API Tokens” section:

manage api tokens

As of right now, the only downside with this script is that ALL cPanel user accounts must use the same password in order to be backed up. I believe the script could be fairly easily edited to allow separate passwords for each account, but I just haven’t bothered. Obviously not very secure, but I haven’t ran into any issues thus far.

Once this script runs, it then copies all of the backups to a folder called “/backups”. The second script then runs, and looks in this directory for files to upload to AWS S3:

<?php

require 'vendor/autoload.php';
$dir = '<file/path/where/backups/are/stored/from/previous/script>';
$files = preg_grep('/^([^.])/', scandir($dir));

foreach($files as $file) {
$s3 = new Aws\S3\S3Client([
'region' => 'us-east-1',
'version' => 'latest',
'credentials' => [
'key' => "<your_aws_access_key>",
'secret' => "<your_aws_secret_key>",
]
]);

echo "Beginning upload of: ".$file."\n";
$result = $s3->putObject([
'Bucket' => 'hosting-backups',
'Key' => $file,
'Body' => fopen($dir.$file, 'r')
]);
unlink($dir.$file);
echo "Finished upload of: ".$file."\n";
echo "------------------------------\n";
}
?>

It’s definitely not perfect, but it does the job, and it prevents me from having to manually run the backups for each one of the sites I manage. I also really enjoy the fact that it automatically uploads the backups to S3, and then deletes them from my reseller server. This helps me save on disk space. Not to mention, S3 storage is very cheap. For 30-days worth of backups for all of my 75 websites, I spend about $1.50/month paying for S3, so the cost is very minimal.

Cheers! Hopefully you find this helpful.

5 thoughts on “How to Automate cPanel Backups in WHM

  1. Just so I understand…So other options besides manually backing each up or running this script is pay from hosting company to run backups. Obvisouly that comes at a premium cost to you as a fixed cost. Then have to figure out joe to balance and pass that along to customer.

    1. Hi Nicola. The script above will allow you to backup all cPanel accounts within WHM with a single script. Keep in mind, though, that the only downside to this is that all cPanel accounts must have the same password. For this reason, I recommend that you use a very long, secure password. Hope that helps!

Leave a Reply

Your email address will not be published.