How To Back Up Shared Hosting Onto A Linux Host (Or NAS)
If you’re running website(s) that live on a typical shared hosting environment then you’ve probably given a thought or two as to how your precious online real estate should best be backed up.
Unfortunately, when it comes to backup, your typical shared hosting environment is not an ideal environment.
That’s because Shared hosting consists of one piece of hardware (a server/VM) being “shared” out between several customers.
Because the hosting company needs to ensure that Customer A cannot access the files of Customer B, in a shared hosting environment each user is limited to operating within their part of the server only.
On a typical Linux server, relative to the server root this is:
Typical Approaches To Shared Host Backup
So what happens if you want to back up your websites?
The standard options are typically that users can:
a) Initiate a full account backup via their cPanel. This option is certainly a very viable way of generating a full account backup of each website you host. However, the usual deficiencies about taking full backups apply: it’s heavy and inefficient because you’re copying the entire filesystem every time you run it irrespective of how much data has changed on the server between runs.
Additionally — perhaps a more serious defect — most regular cPanel users are not able to automatically initiate these backups (although the functionality exists). Hosts aren’t so keen on having users regularly dump large archives of their entire filesystem, it turns out. This is really critical. Sure, you can set yourself Google Calendar reminders to run full account backups of your hosting. But there’s a very to extremely high chance that in three months’ time the thought of …… not running backups ….. is going to sound more appealing to you than running them.
Backups need to be scripted and automated to run on time and should not depend on fickle things like the level of motivation of a human system administrator who’s job it isn’t to run these backups (and if you had a dedicated backup administrator you probably wouldn’t be running on shared hosting … but I digress).
Nevertheless, if you do pull out full cPanel backups from your website you’ll end up with nice standardized archives that look like this on the inside and can be used to move to a new web host if you so please (you’ll probably just have to ask your new host to execute the restore process).
b) Commonly, your second backup option in a shared hosting environment is to subscribe to some add-on package that your host provides. The backup and disaster recovery (DR) system is vast and it’s wide. These days, it’s common for shared hosting providers to build a couple of backup/DR tools into their offerings. For instance, some sort of incremental backup engine is very common so that amateur webmasters can easily roll back changes that rendered their website(s) unusable— like a Wordpress upgrade that went askew. However, these restore copies are usually stored offsite (to the web hosting) and are incremental in nature. Users don’t typically have a programmatic way of downloading the full backup set — and, as time goes on, full incremental backup sets can comprise several dozen increments. This is problematic because the 3–2–1 rule (below) calls for two backup copies to be held so that one can be stored onsite. And, as mentioned, downloading these backups onsite is often not practicable.
A DIY Approach To Shared Hosting Backup
Despite the deficiencies of the shared hosting environment for backup all hope is not lost.
Using nothing more sophisticated than the humble but powerful rsync command line interface (CLI) and a couple of cron jobs it’s possible to create a basic local backup set onto your Linux computer or NAS.
For the purpose of these example commands, let’s assume that we’re talking about backing up a typical Wordpress installation.
Assuming that Wordpress is installed at the root level of yourdomain.com, and that your cPanel username is yourdomain, then we’ll want to back up the following directory from our host:
This can be achieved easily with rsync as follows:
rsync -arvz firstname.lastname@example.org:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/
(Rsync syntax: -a = archive mode; -r = recursive; -v = verbose; -z = file compression during transfer).
Sometimes shared (and reselling) hosting providers insist on having their users connect via a non-standard SSH port. Let’s say we had to SSH into the shared server over port 12345. We would just modify the command to:
rsync -arvz -e ‘ssh -p 12345' email@example.com:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/
If we only had one website and wanted to just pull in the job every two weeks or so, then it wouldn’t be overly onerous to run this command manually in order to observe it running and ensure successful execution. To make that easier we could add the progress parameter.
rsync -arvz -e ‘ssh -p 12345' --progress firstname.lastname@example.org:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/
To get even more verbosity, you can string three ‘v’s together like this. When the rsync is checking the files on the source you will be able to see exactly what is going on.
rsync -arvvvz -e ‘ssh -p 12345' --progress email@example.com:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/
We’d probably also want to sync deletions at source to the target. So we’d add the delete switch:
rsync -arvz -e ‘ssh -p 12345' --progress --delete firstname.lastname@example.org:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/
(To populate the contents of public_html at the root of the target, and not capture the encasing folder, make sure to include a trailing slash)
Don’t Forget The Database
In order to back up a Wordpress installation — or many web applications — we’d nee to back up the MySQL database as well as the filesystem.
To do this, consider setting up the following.
Firstly, build a backup folder in your hosting that is not located within or above /public_html.
For instance would be fine.
Next, set up a cron job to run on the hosting to back up the MySQL database that is attached to your Wordpress installation.
If you can’t remember your Wordpress database, MySQL user and MySQL password then you can find all of these by inspecting wp-config.php which is located at the root of the Wordpress installation.
You could, for instance, set this up in cron:
mysqldump -u mydom_wp912 -p’12345xs' mydom_wp912 > /home/yourdomain/backup/dailymysql_backup.sql
Then, we’d need to pull that backup into the local filesystem:
rsync -arvz -e ‘ssh -p 12345’ --delete email@example.com:/home/yourdomain/backup/ /home/backups/myhosting/yourdomain/mysql/
Build a few restore points
If you want to take this further then you could build out two more folders on the local computer which you use to host these backups.
For instance, create folders called:
To create these backups simply run rsync jobs between /daily /weekly and /monthly — including the source deletion switch — and set these to run in cron at the appropriate intervals.
E.g for the weekly job.
rsync -arvz /home/backups/myhosting/yourdomain/ home/backups/yourdomain/weekly
To make our backup 3–2–1 compliant, we would want to sync this backup of our hosting to another cloud. Thankfully, we can leverage the power of rsync (again) so that even our offsite backups are relatively light. (This is important: pushing full backups to a remote from a typical home internet connection can be a tedious process).
Rclone is a command line interface (CLI) that can be used to sync a Linux filesystem with a remote source (or to keep two remotes in sync). Although rsync can also handle the former type of sync operation (one local and one remote) it does not support as many cloud protocols as rclone does.
After configuring a B2 bucket for instance we could use a simple copy command to move our backups up to an offsite:
rclone copy -v /home/backups/myhosting/yourdomain/ B2:/hostingbackups/
Script It For Automation
Finally, we would likely want to encase our rsync commands within a Bash script so that we could execute them automatically from our local (say, from an NAS).
As this would be run from cron there’s no need to include the progress switch:
#!/bin/bashrsync -arvz -e ‘ssh -p 12345’ --delete firstname.lastname@example.org:/home/yourdomain/public_html/ /home/backups/myhosting/yourdomain/files/rsync -arvz -e ‘ssh -p 12345’ email@example.com:/home/yourdomain/backup /home/backups/myhosting/yourdomain/mysql/exit
That’s all that’s required.
It’s still worth taking offsites just to make sure that you have a backup that is virtually guaranteed to be restorable between different hosts.
But the above steps can provide a basic file and MySQL incremental backup set for a shared hosting environment onto a Linux host or NAS.
QA update 10/07/20:
✅ Successful test restore of MySQL as generated by this method
✅ Successful test restore of files as generated by this method