Software: powerbackup
Simple and flexible incremental backup
Design
This script was designed for using from cron for daily server backup. So, there was several design decisions:
- Reliability and Simplicity
- We don't need bugs in backup system, so it must be really simple and well-tested.
- Consistency
- It have a little sense to backup MySQL database files as is without flushing/locking, for example. So, it should be possible to flush/lock database while backup, and locks shouldn't be kept longer than really needed. Other installed projects may require another custom pre/post backup actions — if you wanna be sure they'll work after restoring from backup, of course.
- Speed
- Backups should be fast and not affect overall system performance. Thus we need incremental backup at least, and also manual tuning of what and how to backup for different things should be possible.
- Format
- tar and gzip are good enough. For encryption gnupg can be used. Or other standard tools. So there is no needs in inventing own format for backup files.
- Interface
- It should provide enough information for further tuning of backup speed/size from one view and useful in cron scripts (i.e. don't bother admin with useless emails with script output when everything is ok) from another.
- Flexibility
- It should be ease to process backups in any way (encrypt, upload using scp, etc.) and parse script output for some monitoring system.
Implementation
For creating incremental backups GNU Tar is used. Only full and level one backups will be created, so to restore from backup at most two files will be required. It's recommended to read 5.2 Using tar to Perform Incremental Dumps and 5.3 Levels of Backups sections from tar manual to find out how to handle created backup files and how to restore from backup (there no powerrestore tool, usual GNU tar can be used to restore from backups).
Overall server backup is split into several independent backup tasks. Each task has own include and exclude file lists for backup and own hooks. This make it possible, for example, make MySQL database backup separate task and setup hooks to flush/lock database only for that task (so database will not be locked while doing backup of other system parts).
For the sake of implementation simplicity include and exclude file lists parsed by (include) bash and (exclude) tar. While tar have support for "include" file lists (option -T) it doesn't support pathname expansion so it's fairly useless. That result in different parsing rules for these files, which increase administration complexity and generally should be considered an architectural flaw. Luckily, bash pathname expansion behaviour are nearly same as tar behaviour with options --wildcards --no-wildcards-match-slash (used in powerbackup), so in practice it's enough to keep in mind only rule: never add last slash to directory names in exclude file.
There two possible hooks: tar and archive.
- tar hook
- Default: /bin/tar. Used to create .tar-file. It executed with many parameters which should be given to GNU tar. Custom hooks allow you to do something before/after /bin/tar execution — flush/lock MySQL, etc.
- archive hook
- Default: /bin/gzip. Used to post-process .tar-file. It executed with single parameter — .tar-file name. Custom hooks allow you to replace gzip'ing with something else — encrypting/uploading backup, or doing bzip2 -9, etc.
Backups are created in current directory. Also in current directory powerbackup will create taskname.snap files for each task, which will be used to create incremental (level one) backups on next powerbackup execution in this directory. If current directory does not contain taskname.snap file (because powerbackup is executing first time in this directory or because they was manually removed) the full backup will be created.
Tasks are configured in /etc/powerbackup/. Also this directory contain log.filter file (used for filtering tar/gzip stderr), optional global tar and archive hooks, and other helper scrips (hooks) with their configuration files (few of them included in powerbackup distribution as examples).
Configuration
To set up backup task you should create a subdirectory in
/etc/powerbackup/ and put there include file.
Also this directory may contain optional exclude and optional
executable scripts tar and/or archive. Directory
name become backup task's name.
cd /etc/powerbackup
mkdir config
echo '/etc/' >> config/include
echo '/proc/config.gz' >> config/include
echo '/usr/src/*/.config' >> config/include
mkdir users
echo '/home/' >> users/include
echo '/home/*/.maildir' >> users/exclude
ln -s archive.encrypt_gpg users/archive
mkdir mysql
echo '/var/lib/mysql/' >> mysql/include
ln -s tar.lock_mysql mysql/tar
The /etc/powerbackup/archive.encrypt_gpg and
/etc/powerbackup/tar.lock_mysql are example hooks distributed
with powerbackup. Before using, they should be
configured too:
cd /etc/powerbackup
echo 'my password' > gpg.pass
mysql -u root -p mysql
mysql> GRANT RELOAD ON *.* TO _backup@localhost IDENTIFIED BY "my password";
echo '_backup' > mysql.user
echo 'my password' > mysql.pass
You can setup global hook for all tasks (except tasks
which define own hook).
cd /etc/powerbackup
# encrypt all backups
ln -s archive.encrypt_gpg archive
# or just disable default behaviour (gzip'ing)
ln -s /bin/true archive
Usage example
If you've tasks configured as shown in previous section (expect global
archive hook) you can create full backups.
# mkdir /var/powerbackup
# cd /var/powerbackup
# powerbackup
Backuping config ... 999999 bytes, 0.999 sec
Backuping users ... 9999999 bytes, 9.999 sec
Backuping mysql ... 999999999 bytes, 99.999 sec
# ls -1
config.full.20080601_211050.tar.gz
config.snap
mysql.full.20080601_211050.tar.gz
mysql.snap
users.full.20080601_211050.tar.gpg
users.snap
Next execution in same directory will create incremental backups.
# cd /var/powerbackup
# powerbackup
Backuping config ... 100000 bytes, 0.100 sec
Backuping users ... 1000000 bytes, 1.000 sec
Backuping mysql ... 100000000 bytes, 10.000 sec
# ls -1
config.full.20080601_211050.tar.gz
config.incr.20080601_211200.tar.gz
config.snap
mysql.full.20080601_211050.tar.gz
mysql.incr.20080601_211200.tar.gz
mysql.snap
users.full.20080601_211050.tar.gpg
users.incr.20080601_211200.tar.gpg
users.snap
You can select which tasks to backup. Also you don't have to keep
previous backups to create incremental backup — only
taskname.snap file is required.
# cd /var/powerbackup
# rm *.{full,incr}.*
# powerbackup config mysql
Backuping config ... 100000 bytes, 0.100 sec
Backuping mysql ... 100000000 bytes, 10.000 sec
# ls -1
config.incr.20080601_211406.tar.gz
config.snap
mysql.incr.20080601_211406.tar.gz
mysql.snap
users.snap
Remove taskname.snap to force full backup.
# cd /var/powerbackup
# rm users.snap
# powerbackup
Backuping config ... 100000 bytes, 0.100 sec
Backuping users ... 9999999 bytes, 9.999 sec
Backuping mysql ... 100000000 bytes, 10.000 sec
# ls -1
config.incr.20080601_211406.tar.gz
config.incr.20080601_212015.tar.gz
config.snap
mysql.incr.20080601_211406.tar.gz
mysql.incr.20080601_212015.tar.gz
mysql.snap
users.full.20080601_212015.tar.gpg
users.snap
Known limitations
It creates single archive file, without volume splitting — so it's impossible to have more than 4GB in single file on FAT32.