7.1 KiB
backup.sh
backup.sh
is a POSIX compliant, modular and lightweight backup utility to save and encrypt your files.
This tool is intended to be used on small scale UNIX environment such as VPS, small servers and
workstations. backup.sh
uses rsync, tar
and openssl to copy, compress and encrypt the backup.
Installation
backup.sh
consists in a single source file, to install it you can copy the script wherever you want.
Alternatively, you can install the script, the default sources file and the man file using the following command:
$> sudo make install
This will copy backup.sh
into /usr/local/bin/backup.sh
, sources.bk
into /usr/local/etc/sources.bk
and
backup.sh.1
into /usr/local/share/man/man1/backup.sh.1
. To uninstall the program along with the sample sources file and the manual page,
you can issue sudo make uninstall
.
At this point you still need to install the following dependencies:
rsync
tar
openssl
Usage
To show the available options, you can run backup.sh --help
, which will print out the following message:
backup.sh - POSIX compliant, modular and lightweight backup utility.
Syntax: ./backup.sh [-b|-e|-h]
options:
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
-h|--help Show this helper.
As you can see, backup.sh
supports two options: backup creation and backup extraction, the former requires
root permissions, while the latter does not. Let us see them in details.
Backup creation
To specify the directories to backup, backup.sh
uses an associative array
defined in a text file(called sources file) with the following syntax:
<LABEL>=<PATH>
Where <LABEL>
is the name of the backup and <PATH>
is its path. For example,
if you want to back up /etc/nginx
and /etc/ssh
, add the following entries to the sources file:
nginx=/etc/nginx/
ssh=/etc/ssh/
backup.sh
will create two folders inside the backup archive with the following syntax:
backup-<LABEL>-<YYYYMMDD>
In the previous example, this would be:
backup-nginx-<YYYYMMDD>
backup-ssh-<YYYYMMDD>
You can add as many entries as you want, just be sure to use the proper syntax. In particular, the sources file, should not includes:
- Spaces between the label and the equal sign;
- Empty lines;
- Comments.
You can find a sample sources file at sources.bk
(or at /usr/local/etc/sources.bk
).
After having defined the sources file, you can invoke backup.sh
using the following syntax:
$> sudo ./backup.sh --backup <SOURCES_FILE> <DEST> <ENCRYPTION_PASSWORD>
Where <SOURCES_FILE>
is the sources file, <DEST>
is the absolute path of the output of the backup
without trailing slashes and <ENCRYPTION_PASSWORD>
is the password to encrypt the compressed archive.
In the previous example, this would be:
$> sudo ./backup.sh --backup sources.bk /home/john badpw1234
The backup utility will begin to copy the files defined in the sources file:
Copying nginx(1/2)
Copying ssh(2/2)
Compressing and encrypting backup...
Elapsed time: 10 seconds.
After that, you will find the final backup archive in /home/john/backup-<HOSTNAME>-<YYYMMDD>.tar.gz.enc
.
You can also use backup.sh
from a crontab rule:
$> sudo crontab -e
30 03 * * 6 EKEY=$(cat /home/john/.ekey) bash -c '/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY' > /dev/null 2>&1
This will automatically run backup.sh
every Saturday morning at 03:30 AM. In the example above, the encryption
key is stored in a local file(with fixed permissions) to avoid password leaking in crontab logs. You can also
adopt this practice while using the --extract
option to avoid password leaking in shell history.
Backup extraction
backup.sh
can also extract the encrypted backup archive using the following syntax:
$> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD>
Where <ENCRYPTED_ARCHIVE>
is the encrypted backup and <ARCHIVE_PASSWORD>
is the backup password.
For instance:
$> ./backup.sh --extract backup-<hostname>-<YYYMMDD>.tar.gz.enc badpw1234
This will create a new folder called backup.sh.tmp
in your local directory. Be sure to rename any directory
with that name to avoid collisions. From the previous example, you should have the following directories:
backup-nginx-<YYYYMMDD>
backup-ssh-<YYYYMMDD>
How does backup.sh
work?
backup.sh
uses rsync to copy the files, tar to compress the backup and openssl
to encrypt it. By default, rsync is being used with the following parameters:
$> rsync -aPhrq --delete
That is:
-a
: archive mode: rsync copies files recursively while preserving as much metadata as possible;-P
: progress/partial, this allows rsync to resume interrupted transfers and to shows progress information;-h
: human readable output: rsync shows output numbers in a more readable way;-r
: recursive mode: forces rsync to copy directories and their content;-q
: quiet mode: reduces the amount of information rsync produces;--delete
: delete mode: forces rsync to delete any extraneous files at the destination dir.
After that the backup folder is being encrypred using openssl. By default, it is used with the following parameters:
$> openssl enc -aes-256-cbc -md sha512 -pbkdf2 -iter 100000 -salt -k "$PASSWORD" > file.tar.gz.enc
This command encrypts the backup using the AES-256-CBC symmetric encryption algorithm with a 256bit key. Here is what each option means:
enc
: encrypt mode: tell openssl to use encryption functionality;-aes-256-cbc
: encryption algorithm: this option tells openssl which encryption algorithm to use;-md sh512
: hashing algorithm: this option tells openssl which hashing algorithm to use for key derivation, i.e., converting the text-based password($PASSWORD
) into an encryption key;-pbkdf2
: key deriving algorithm: this option tells openssl which key deriving algorithm to use. In this case we use the password-based key derivation function 2 algorithm;-iter 100000
: number of iterations: this options tells openssl the number of iteration to use for the key derivation function;-salt
: enable salting: this option tells openssl to add a random salt to the key derivation process in order to avoid rainbow table based attacks.
Unit tests
backup.sh
provides some unit tests inside the tests.sh
script. This script generates some dummy files inside the following
directories:
- /var/log
- /var/www
- /etc/nginx
- /etc/ssh
For this reason, this script should NOT be used in non-testing environments. To run all tests, issue the following command:
$> sudo ./tests.sh I_HAVE_READ_THE_HELPER