I’m hosting three different WordPress blogs for different people (this one included) and recently decided to switch away from my home server to a VPS. My home server has a RAID-Z array and important data is backed up remotely on a regular basis giving me the peace of mind that my data is safe, but I can’t be so sure about the VPS. Also, I might switch to a different VPS provider in the future and wanted to make deploying the blogs as easy as possible. I came up with the following solution.
Goals
- Daily backups usable for small websites with little traffic
- Backups should be complete: all files, MySQL dump, logs
- Flexibility
Why Git?
Using git has many inherent advantages over simply copying files to a remote server.
- Daily backups will only store diffs, taking up little space
- Using a VCS allows you to see history, merge fixes, branch, etc. if you need to (eg. for developing plugins/themes on one computer and easily merging them into your website)
- Push backups to a remote server using http, https, ssh, or git protocols
- Easily exclude files from backups using
.gitignore - Setting up a new server is just a
git cloneaway - Know your backup succeeded just by browsing your git repository
- More!
So, why should we store the database backup and log files in git as well?
- Complete history of your website – restore the files AND database to any state you want
- The diffs in each commit give you the traffic for the day and which rows were added to your database
- No need for separate backup methods!
Of course, git isn’t the perfect solution for all websites. High-traffic websites may find their git repositories quickly grow in size when storing database backups and log files.
Structure
To make things easier, I structured each of the sites in the following fashion:
1 2 3 4 5 6 7 8 | |
Also, the MySQL username and database name for each site is the same as the URL, so “example.com” for this case.
Prepare the Remote Repository on the Backup Server
Create an empty repository on the backup server.
1 2 3 4 | |
Add data to the repository
We can clone the empty repository we just made and add the initial data to it. Do this on the server your site is currently hosted on.
1 2 3 4 5 6 7 | |
I also made a simple Makefile to automate backing up. Edit it to suit your needs (especially the MYSQL_ variables) and place it in the root of your repository.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Now we can commit changes and push to our backup server. Remember that you can add a .gitignore to keep files or directories from being backed up.
1 2 3 | |
Deploying
Now when you want to deploy your site, set up the MySQL user and database then checkout the site from git.
1 2 3 4 | |
As long as your web server points to /usr/local/www/example.com, you should now be able to access your site!
If you want to test backups, just generate some log activity or do something which would update the database and run make backup from /usr/local/www/example.com.
Automating Backups
You can automate backups by using cron.
Access your crontab
1
| |
…and add the following line:
1
| |
If all goes well, you should see daily commits popping up on your backup server! If you ever lose data, you can go back to the deploying section and go back to your last backup.