New version!
- Fixed bug related to Bash version that affected Darwin systems; - Fixed bug with file existence check; - Fixed minor issues; - Fixed various typos; - Added verbose mode; - Added packages for Debian and RHEL.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
deb/
|
||||
24
README.md
24
README.md
@@ -6,17 +6,22 @@ workstations. `backup.sh` uses [rsync](https://linux.die.net/man/1/rsync), [tar]
|
||||
to copy, compress, encrypt the backup and verify 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:
|
||||
`backup.sh` is a single source file, to install it you can copy the script wherever you want. Alternatively, if you
|
||||
are running a DEB/RPM distribution, you can install it with the following command:
|
||||
```sh
|
||||
$> sudo apt install ./bin/backup.sh-1.0.0.x86_64.deb # Debian
|
||||
$> sudo dnf install ./bin/backup.sh-1.0.0-2.x86_64.rpm # RHEL
|
||||
```
|
||||
|
||||
For any other UNIX system, you can use the following command:
|
||||
```sh
|
||||
$> 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/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`.
|
||||
`backup.sh.1` into `/usr/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:
|
||||
- `Bash`
|
||||
- `Bash(v>=4)`
|
||||
- `rsync`
|
||||
- `tar`
|
||||
- `gpg`
|
||||
@@ -24,13 +29,14 @@ At this point you still need to install the following dependencies:
|
||||
## Usage
|
||||
To show the available options, you can run `backup.sh --help`, which will print out the following message:
|
||||
```text
|
||||
backup.sh - POSIX compliant, modular and lightweight backup utility.
|
||||
backup.sh v1.0.0 - POSIX compliant, modular and lightweight backup utility.
|
||||
|
||||
Syntax: ./backup.sh [-b|-c|-e|-h]
|
||||
Syntax: ./backup.sh [-b|-e|-c|-V|-h]
|
||||
options:
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-V|--verbose Enable verbose mode.
|
||||
-h|--help Show this helper.
|
||||
|
||||
General help with the software: https://github.com/ceticamarco/backup.sh
|
||||
@@ -121,6 +127,8 @@ This will automatically run `backup.sh` every Saturday morning at 03:30 AM. In t
|
||||
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.
|
||||
|
||||
By default `backup.sh` is very quiet, to add some verbosity to the output, be sure to use the `-V`(`--verbose`) option.
|
||||
|
||||
### Backup extraction
|
||||
`backup.sh` can also be used to extract and to verify the encrypted backup.
|
||||
To do so, use the following commands:
|
||||
|
||||
75
backup.sh
75
backup.sh
@@ -37,6 +37,11 @@
|
||||
set -e
|
||||
|
||||
checkdeps() {
|
||||
if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
|
||||
echo "This version of Bash is not supported."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if dependencies are installed
|
||||
missing_dep=0
|
||||
deps="rsync tar gpg"
|
||||
@@ -66,13 +71,20 @@ gethash() {
|
||||
# $2: output path
|
||||
# $3: password
|
||||
# $4: compute sha256(0,1)
|
||||
# $5: verbosity flag(0,1)
|
||||
make_backup() {
|
||||
BACKUP_SH_SOURCES_PATH="$1"
|
||||
BACKUP_SH_OUTPATH="$2"
|
||||
BACKUP_SH_PASS="$3"
|
||||
BACKUP_SH_SHA256="$4"
|
||||
BACKUP_SH_VERBOSE="$5"
|
||||
|
||||
if [ "$BACKUP_SH_VERBOSE" -eq 1 ]; then
|
||||
BACKUP_SH_COMMAND="rsync -aPhr --delete"
|
||||
else
|
||||
BACKUP_SH_COMMAND="rsync -aPhrq --delete"
|
||||
fi
|
||||
|
||||
BACKUP_SH_COMMAND="rsync -aPhrq --delete"
|
||||
BACKUP_SH_DATE="$(date +'%Y%m%d')"
|
||||
BACKUP_SH_FOLDER="backup.sh.tmp"
|
||||
BACKUP_SH_OUTPUT="$BACKUP_SH_OUTPATH/$BACKUP_SH_FOLDER"
|
||||
@@ -119,8 +131,13 @@ make_backup() {
|
||||
|
||||
# Compress backup directory
|
||||
echo "Compressing backup..."
|
||||
tar -czf "$BACKUP_SH_OUTPATH/backup.sh.tar.gz" \
|
||||
-C "$BACKUP_SH_OUTPATH" "$BACKUP_SH_FOLDER" > /dev/null 2>&1
|
||||
if [ "$BACKUP_SH_VERBOSE" -eq 1 ]; then
|
||||
tar -cvzf "$BACKUP_SH_OUTPATH/backup.sh.tar.gz" \
|
||||
-C "$BACKUP_SH_OUTPATH" "$BACKUP_SH_FOLDER"
|
||||
else
|
||||
tar -czf "$BACKUP_SH_OUTPATH/backup.sh.tar.gz" \
|
||||
-C "$BACKUP_SH_OUTPATH" "$BACKUP_SH_FOLDER" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Encrypt backup directory
|
||||
echo "Encrypting backup..."
|
||||
@@ -151,10 +168,12 @@ make_backup() {
|
||||
# $1: archive file
|
||||
# $2: archive password
|
||||
# $3: sha256 file(optional)
|
||||
# $4: verbosity flag(0,1)
|
||||
extract_backup() {
|
||||
BACKUP_SH_ARCHIVE_PATH="$1"
|
||||
BACKUP_SH_ARCHIVE_PW="$2"
|
||||
BACKUP_SH_SHA256_FILE="$3"
|
||||
BACKUP_SH_VERBOSE="$4"
|
||||
|
||||
# Decrypt the archive
|
||||
gpg -a \
|
||||
@@ -167,7 +186,11 @@ extract_backup() {
|
||||
"$BACKUP_SH_ARCHIVE_PATH"
|
||||
|
||||
# Extract archive
|
||||
tar -xzf backup.sh.tar.gz 1> /dev/null 2>&1
|
||||
if [ "$BACKUP_SH_VERBOSE" -eq 1 ]; then
|
||||
tar -xzvf backup.sh.tar.gz
|
||||
else
|
||||
tar -xzf backup.sh.tar.gz > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# If specified, use SHA256 file to compute checksum of files
|
||||
if [ -n "$BACKUP_SH_SHA256_FILE" ]; then
|
||||
@@ -179,10 +202,11 @@ extract_backup() {
|
||||
SHA256="$(gethash "$file")"
|
||||
# Check if checksum file contains hash
|
||||
if ! grep -wq "$SHA256" "$BACKUP_SH_SHA256_FILE"; then
|
||||
printf "[FATAL] - integrity error for '%s'.\n" "$file"
|
||||
rm -rf backup.sh.tar.gz backup.sh.tmp
|
||||
printf "[FATAL] - integrity error for '%s'.\n" "$file"
|
||||
exit 1
|
||||
fi
|
||||
printf "[OK] - integrity check for '%s' passed.\n" "$file"
|
||||
done
|
||||
shopt -u globstar dotglob
|
||||
fi
|
||||
@@ -194,13 +218,14 @@ helper() {
|
||||
CLI_NAME="$1"
|
||||
|
||||
cat <<EOF
|
||||
backup.sh - POSIX compliant, modular and lightweight backup utility.
|
||||
backup.sh v1.0.0 - POSIX compliant, modular and lightweight backup utility.
|
||||
|
||||
Syntax: $CLI_NAME [-b|-c|-e|-h]
|
||||
Syntax: $CLI_NAME [-b|-e|-c|-V|-h]
|
||||
options:
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-V|--verbose Enable verbose mode.
|
||||
-h|--help Show this helper.
|
||||
|
||||
General help with the software: https://github.com/ceticamarco/backup.sh
|
||||
@@ -219,6 +244,7 @@ main() {
|
||||
fi
|
||||
|
||||
CHECKSUM_FLAG=0
|
||||
VERBOSE_FLAG=0
|
||||
# Parse CLI arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
@@ -233,20 +259,11 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$CHECKSUM_FLAG" -eq 1 ]; then
|
||||
[ -f "$BACKUP_SH_SOURCES_PATH" ] || { echo "Sources file does not exist"; exit 1; }
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 1
|
||||
else
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 0
|
||||
fi
|
||||
[ -f "$BACKUP_SH_SOURCES_PATH" ] || { echo "Sources file does not exist"; exit 1; }
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" "$CHECKSUM_FLAG" "$VERBOSE_FLAG"
|
||||
|
||||
exit 0
|
||||
;;
|
||||
-c|--checksum)
|
||||
[ $# -eq 1 ] && { echo "Use this option with '--backup' or '--extract'"; exit 1; }
|
||||
CHECKSUM_FLAG=1
|
||||
shift 1
|
||||
;;
|
||||
-e|--extract)
|
||||
BACKUP_SH_ARCHIVE_FILE="$2"
|
||||
BACKUP_SH_ARCHIVE_PW="$3"
|
||||
@@ -261,21 +278,33 @@ main() {
|
||||
else
|
||||
if [ -z "$BACKUP_SH_ARCHIVE_FILE" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ]; then
|
||||
echo "Please, specify an encrypted archive and a password."
|
||||
echo "For more informatio, try --help"
|
||||
echo "For more information, try --help"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check whether backup file exists or not
|
||||
[ -f "$BACKUP_SH_ARCHIVE_FILE" ] || { echo "Backup file does not exist"; exit 1; }
|
||||
|
||||
if [ "$CHECKSUM_FLAG" -eq 1 ]; then
|
||||
[ -f "$BACKUP_SH_SHA256_FILE" ] || { echo "Checksum file does not exist"; exit 1; }
|
||||
[ -f "$BACKUP_SH_ARCHIVE_FILE" ] || { echo "Backup file does not exist"; exit 1; }
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW" "$BACKUP_SH_SHA256_FILE"
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW" "$BACKUP_SH_SHA256_FILE" "$VERBOSE_FLAG"
|
||||
else
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW"
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW" "" "$VERBOSE_FLAG"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
;;
|
||||
-c|--checksum)
|
||||
[ $# -eq 1 ] && { echo "Use '--checksum' with '--backup' or '--extract'"; exit 1; }
|
||||
CHECKSUM_FLAG=1
|
||||
shift 1
|
||||
;;
|
||||
-V|--verbose)
|
||||
[ $# -eq 1 ] && { echo "Use '--verbose' with '--backup' or '--extract'"; exit 1; }
|
||||
VERBOSE_FLAG=1
|
||||
shift 1
|
||||
;;
|
||||
-h|--help)
|
||||
helper "$0"
|
||||
exit 0
|
||||
|
||||
367
backup.sh.1
367
backup.sh.1
@@ -1,39 +1,24 @@
|
||||
.\" Automatically generated by Pandoc 2.17.1.1
|
||||
.\" Automatically generated by Pandoc 3.5
|
||||
.\"
|
||||
.\" Define V font for inline verbatim, using C font in formats
|
||||
.\" that render this, and otherwise B font.
|
||||
.ie "\f[CB]x\f[]"x" \{\
|
||||
. ftr V B
|
||||
. ftr VI BI
|
||||
. ftr VB B
|
||||
. ftr VBI BI
|
||||
.\}
|
||||
.el \{\
|
||||
. ftr V CR
|
||||
. ftr VI CI
|
||||
. ftr VB CB
|
||||
. ftr VBI CBI
|
||||
.\}
|
||||
.TH "backup.sh" "1" "April 4, 2024" "Marco Cetica" "General Commands Manual"
|
||||
.hy
|
||||
.TH "backup.sh" "1" "October 21, 2024" "Marco Cetica" "General Commands Manual"
|
||||
.SH NAME
|
||||
.PP
|
||||
\f[B]backup.sh\f[R] - POSIX compliant, modular and lightweight backup
|
||||
utility to save and encrypt your files.
|
||||
\f[B]backup.sh\f[R] \- POSIX compliant, modular and lightweight backup
|
||||
utility.
|
||||
.SH SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
Syntax: ./backup.sh [-b|-c|-e|-h]
|
||||
.EX
|
||||
Syntax: ./backup.sh [\-b|\-e|\-c|\-V|\-h]
|
||||
options:
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-h|--help Show this helper.
|
||||
\f[R]
|
||||
.fi
|
||||
\-b|\-\-backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
\-e|\-\-extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
\-c|\-\-checksum Generate/check SHA256 of a backup.
|
||||
\-V|\-\-verbose Enable verbose mode.
|
||||
\-h|\-\-help Show this helper.
|
||||
|
||||
General help with the software: https://github.com/ceticamarco/backup.sh
|
||||
Report bugs to: Marco Cetica(<email\[at]marcocetica.com>)
|
||||
.EE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\f[B]backup.sh\f[R] 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
|
||||
@@ -42,7 +27,6 @@ VPS, small servers and workstations.
|
||||
\f[I]sha256sum\f[R] and \f[I]gpg\f[R] to copy, compress, verify and
|
||||
encrypt the backup.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\f[B]backup.sh\f[R] supports three options: \f[B]backup creation\f[R],
|
||||
\f[B]backup extraction\f[R] and \f[B]checksum\f[R] to verify the
|
||||
integrity of a backup.
|
||||
@@ -51,163 +35,142 @@ not.
|
||||
The checksum option must be used in combination of one of the previous
|
||||
options.
|
||||
.SS Backup creation
|
||||
.PP
|
||||
To specify the directories to back up, \f[V]backup.sh\f[R] uses an
|
||||
To specify the directories to back up, \f[CR]backup.sh\f[R] uses an
|
||||
associative array defined in a text file(called \f[I]sources file\f[R])
|
||||
with the following syntax:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
.EX
|
||||
<LABEL>=<PATH>
|
||||
\f[R]
|
||||
.fi
|
||||
.EE
|
||||
.PP
|
||||
Where \f[V]<LABEL>\f[R] is the name of the backup and \f[V]<PATH>\f[R]
|
||||
Where \f[CR]<LABEL>\f[R] is the name of the backup and \f[CR]<PATH>\f[R]
|
||||
is its path.
|
||||
For example, if you want to back up \f[V]/etc/nginx\f[R] and
|
||||
\f[V]/etc/ssh\f[R], add the following entries to the \f[I]sources
|
||||
For example, if you want to back up \f[CR]/etc/nginx\f[R] and
|
||||
\f[CR]/etc/ssh\f[R], add the following entries to the \f[I]sources
|
||||
file\f[R]:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
.EX
|
||||
nginx=/etc/nginx/
|
||||
ssh=/etc/ssh/
|
||||
\f[R]
|
||||
.fi
|
||||
.EE
|
||||
.PP
|
||||
\f[V]backup.sh\f[R] will create two folders inside the backup archive
|
||||
\f[CR]backup.sh\f[R] will create two folders inside the backup archive
|
||||
with the following syntax:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
backup-<LABEL>-<YYYYMMDD>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
backup\-<LABEL>\-<YYYYMMDD>
|
||||
.EE
|
||||
.PP
|
||||
In the previous example, this would be:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
backup-nginx-<YYYYMMDD>
|
||||
backup-ssh-<YYYYMMDD>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
backup\-nginx\-<YYYYMMDD>
|
||||
backup\-ssh\-<YYYYMMDD>
|
||||
.EE
|
||||
.PP
|
||||
You can add as many entries as you want, just be sure to use the proper
|
||||
syntax.
|
||||
In particular, the \f[I]sources file\f[R], \f[B]should not\f[R] include:
|
||||
- Spaces between the label and the equal sign;
|
||||
\- Spaces between the label and the equal sign;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- Empty lines;
|
||||
\- Empty lines;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- Comments.
|
||||
\- Comments.
|
||||
.PP
|
||||
You can find a sample \f[I]sources file\f[R] at \f[V]sources.bk\f[R](or
|
||||
at \f[V]/usr/local/etc/sources.bk\f[R]).
|
||||
You can find a sample \f[I]sources file\f[R] at \f[CR]sources.bk\f[R](or
|
||||
at \f[CR]/usr/local/etc/sources.bk\f[R]).
|
||||
.PP
|
||||
After having defined the \f[I]sources file\f[R], you can invoke
|
||||
\f[V]backup.sh\f[R] using the following syntax:
|
||||
\f[CR]backup.sh\f[R] using the following syntax:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> sudo ./backup.sh --backup <SOURCES_FILE> <DEST> <ENCRYPTION_PASSWORD>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> sudo ./backup.sh \-\-backup <SOURCES_FILE> <DEST> <ENCRYPTION_PASSWORD>
|
||||
.EE
|
||||
.PP
|
||||
Where \f[V]<SOURCES_FILE>\f[R] is the \f[I]sources file\f[R],
|
||||
\f[V]<DEST>\f[R] is the absolute path of the output of the backup
|
||||
\f[B]without trailing slashes\f[R] and \f[V]<ENCRYPTION_PASSWORD>\f[R]
|
||||
Where \f[CR]<SOURCES_FILE>\f[R] is the \f[I]sources file\f[R],
|
||||
\f[CR]<DEST>\f[R] is the absolute path of the output of the backup
|
||||
\f[B]without trailing slashes\f[R] and \f[CR]<ENCRYPTION_PASSWORD>\f[R]
|
||||
is the password to encrypt the compressed archive.
|
||||
.PP
|
||||
In the previous example, this would be:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> sudo ./backup.sh --backup sources.bk /home/john badpw1234
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> sudo ./backup.sh \-\-backup sources.bk /home/john badpw1234
|
||||
.EE
|
||||
.PP
|
||||
You can also tell \f[V]backup.sh\f[R] to generate a SHA256 file
|
||||
containing the hash of each file using the \f[V]-c\f[R] option.
|
||||
You can also tell \f[CR]backup.sh\f[R] to generate a SHA256 file
|
||||
containing the hash of each file using the \f[CR]\-c\f[R] option.
|
||||
In the previous example, this would be:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> sudo ./backup.sh --checksum --backup sources.bk /home/john badpw1234
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> sudo ./backup.sh \-\-checksum \-\-backup sources.bk /home/john badpw1234
|
||||
.EE
|
||||
.PP
|
||||
The backup utility will begin to copy the files defined in the
|
||||
\f[I]sources file\f[R]:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
.EX
|
||||
Copying nginx(1/2)
|
||||
Copying ssh(2/2)
|
||||
Compressing backup...
|
||||
Encrypting backup...
|
||||
File name: /home/john/backup-<HOSTNAME>-<YYYYMMDD>.tar.gz.enc
|
||||
Checksum file: /home/john/backup-<HOSTNAME>-<YYYYMMDD>.sha256
|
||||
File name: /home/john/backup\-<HOSTNAME>\-<YYYYMMDD>.tar.gz.enc
|
||||
Checksum file: /home/john/backup\-<HOSTNAME>\-<YYYYMMDD>.sha256
|
||||
File size: 7336400696(6.9G)
|
||||
Elapsed time: 259 seconds.
|
||||
\f[R]
|
||||
.fi
|
||||
.EE
|
||||
.PP
|
||||
After that, you will find the backup archive and the checksum file in
|
||||
\f[V]/home/john/backup-<HOSTNAME>-<YYYYMMDD>.tar.gz.enc\f[R] and
|
||||
\f[V]/home/john/backup-<HOSTNAME>-<YYYYMMDD>.sha256\f[R], respectively.
|
||||
\f[CR]/home/john/backup\-<HOSTNAME>\-<YYYYMMDD>.tar.gz.enc\f[R] and
|
||||
\f[CR]/home/john/backup\-<HOSTNAME>\-<YYYYMMDD>.sha256\f[R],
|
||||
respectively.
|
||||
.PP
|
||||
You can also use \f[V]backup.sh\f[R] from a crontab rule:
|
||||
You can also use \f[CR]backup.sh\f[R] from a crontab rule:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> sudo crontab -e
|
||||
30 03 * * 6 EKEY=$(cat /home/john/.ekey) bash -c \[aq]/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY\[aq] > /dev/null 2>&1
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> sudo crontab \-e
|
||||
30 03 * * 6 EKEY=$(cat /home/john/.ekey) bash \-c \[aq]/usr/local/bin/backup.sh \-b /usr/local/etc/sources.bk /home/john $EKEY\[aq] > /dev/null 2>&1
|
||||
.EE
|
||||
.PP
|
||||
This will automatically run \f[V]backup.sh\f[R] every Saturday morning
|
||||
This will automatically run \f[CR]backup.sh\f[R] 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 \f[V]--extract\f[R]
|
||||
You can also adopt this practice while using the \f[CR]\-\-extract\f[R]
|
||||
option to avoid password leaking in shell history.
|
||||
.SS Backup extraction
|
||||
.PP
|
||||
By default \f[CR]backup.sh\f[R] is very quiet, to add some verbosity to
|
||||
the output, be sure to use the \f[CR]\-V\f[R](\f[CR]\-\-verbose\f[R])
|
||||
option.
|
||||
.SS Backup extraction
|
||||
\f[B]backup.sh\f[R] can also be used to extract and to verify the
|
||||
encrypted backup.
|
||||
To do so, use the following commands:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> ./backup.sh \-\-extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD>
|
||||
.EE
|
||||
.PP
|
||||
Where \f[V]<ENCRYPTED_ARCHIVE>\f[R] is the encrypted backup and
|
||||
\f[V]<ARCHIVE_PASSWORD>\f[R] is the backup password.
|
||||
Where \f[CR]<ENCRYPTED_ARCHIVE>\f[R] is the encrypted backup and
|
||||
\f[CR]<ARCHIVE_PASSWORD>\f[R] is the backup password.
|
||||
.PP
|
||||
For instance:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> ./backup.sh --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> ./backup.sh \-\-extract backup\-<hostname>\-<YYYYMMDD>.tar.gz.enc badpw1234
|
||||
.EE
|
||||
.PP
|
||||
This will create a new folder called \f[V]backup.sh.tmp\f[R] in your
|
||||
This will create a new folder called \f[CR]backup.sh.tmp\f[R] in your
|
||||
local directory with the following content:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
backup-nginx-<YYYYMMDD>
|
||||
backup-ssh-<YYYYMMDD>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
backup\-nginx\-<YYYYMMDD>
|
||||
backup\-ssh\-<YYYYMMDD>
|
||||
.EE
|
||||
.PP
|
||||
\f[B]note\f[R]: be sure to rename any directory with that name to avoid
|
||||
collisions.
|
||||
@@ -215,48 +178,39 @@ collisions.
|
||||
If you also want to verify the integrity of the backup data, use the
|
||||
following commands:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH>
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> ./backup.sh \-\-checksum \-\-extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH>
|
||||
.EE
|
||||
.PP
|
||||
For instance:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 backup-<hostname>-<YYYYMMDD>.sha256
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> ./backup.sh \-\-checksum \-\-extract backup\-<hostname>\-<YYYYMMDD>.tar.gz.enc badpw1234 backup\-<hostname>\-<YYYYMMDD>.sha256
|
||||
.EE
|
||||
.SS How does backup.sh work?
|
||||
.PP
|
||||
\f[B]backup.sh\f[R] uses \f[I]rsync\f[R] to copy the files,
|
||||
\f[I]tar\f[R] to compress the backup, \f[I]gpg\f[R] to encrypt it and
|
||||
\f[I]sha256sum\f[R] to verify it.
|
||||
By default, rsync is being used with the following parameters:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> rsync -aPhrq --delete
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> rsync \-aPhrq \-\-delete
|
||||
.EE
|
||||
.PP
|
||||
That is:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
- a: archive mode: rsync copies files recursively while preserving as much metadata as possible;
|
||||
- P: progress/partial: 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.
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
\- a: archive mode: rsync copies files recursively while preserving as much metadata as possible;
|
||||
\- P: progress/partial: 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.
|
||||
.EE
|
||||
.PP
|
||||
If specified(\f[V]--checksum\f[R] option), \f[V]backup.sh\f[R] can also
|
||||
generate the checksum of each file of the backup.
|
||||
To do so, it uses \f[V]sha256sum(1)\f[R] to compute the hash of every
|
||||
If specified(\f[CR]\-\-checksum\f[R] option), \f[CR]backup.sh\f[R] can
|
||||
also generate the checksum of each file of the backup.
|
||||
To do so, it uses \f[CR]sha256sum(1)\f[R] to compute the hash of every
|
||||
single file using the SHA256 hashing algorithm.
|
||||
The checksum file contains nothing but the checksums of the files, no
|
||||
other information about the files stored on the backup archive is
|
||||
@@ -267,60 +221,59 @@ section for more information).
|
||||
After that the backup folder is being encrypted using gpg.
|
||||
By default, it is used with the following parameters:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> gpg -a \[rs]
|
||||
--symmetric \[rs]
|
||||
--cipher-algo=AES256 \[rs]
|
||||
--no-symkey-cache \[rs]
|
||||
--pinentry-mode=loopback \[rs]
|
||||
--batch --passphrase \[dq]$PASSWORD\[dq] \[rs]
|
||||
--output \[dq]$OUTPUT\[dq] \[rs]
|
||||
.EX
|
||||
$> gpg \-a \[rs]
|
||||
\-\-symmetric \[rs]
|
||||
\-\-cipher\-algo=AES256 \[rs]
|
||||
\-\-no\-symkey\-cache \[rs]
|
||||
\-\-pinentry\-mode=loopback \[rs]
|
||||
\-\-batch \-\-passphrase \[dq]$PASSWORD\[dq] \[rs]
|
||||
\-\-output \[dq]$OUTPUT\[dq] \[rs]
|
||||
\[dq]$INPUT\[dq]
|
||||
\f[R]
|
||||
.fi
|
||||
.EE
|
||||
.PP
|
||||
This command encrypts the backup using the AES-256 symmetric encryption
|
||||
This command encrypts the backup using the AES\-256 symmetric encryption
|
||||
algorithm with a 256bit key.
|
||||
Here is what each flag do: - \f[V]--symmetric\f[R]: Use symmetric
|
||||
Here is what each flag do: \- \f[CR]\-\-symmetric\f[R]: Use symmetric
|
||||
encryption;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]--cipher-algo=AES256\f[R]: Use AES256 algorithm;
|
||||
\- \f[CR]\-\-cipher\-algo=AES256\f[R]: Use AES256 algorithm;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]--no-symkey-cache\f[R]: Do not save password on GPG\[cq]s cache;
|
||||
\- \f[CR]\-\-no\-symkey\-cache\f[R]: Do not save password on GPG\[cq]s
|
||||
cache;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]--pinentry-mode=loopback --batch\f[R]: Do not prompt the user;
|
||||
\- \f[CR]\-\-pinentry\-mode=loopback \-\-batch\f[R]: Do not prompt the
|
||||
user;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]--passphrase-fd 3 3<< \[dq]$PASSWORD\[dq]\f[R]: Read password
|
||||
without revealing it on \f[V]ps\f[R];
|
||||
\- \f[CR]\-\-passphrase\-fd 3 3<< \[dq]$PASSWORD\[dq]\f[R]: Read
|
||||
password without revealing it on \f[CR]ps\f[R];
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]--output\f[R]: Specify output file;
|
||||
\- \f[CR]\-\-output\f[R]: Specify output file;
|
||||
.PD 0
|
||||
.P
|
||||
.PD
|
||||
- \f[V]$INPUT\f[R]: Specify input file.
|
||||
\- \f[CR]$INPUT\f[R]: Specify input file.
|
||||
.SS Plausible Deniability
|
||||
.PP
|
||||
While \f[V]backup.sh\f[R] provide some pretty strong security against
|
||||
While \f[CR]backup.sh\f[R] provide some pretty strong security against
|
||||
bruteforce attack(assuming a strong passphrase is being used) it should
|
||||
by no means considered a viable tool against a cryptanalysis
|
||||
investigation.
|
||||
Many of the copying, compressing and encrypting operations made by
|
||||
\f[V]backup.sh\f[R] during the backup process can be used to invalidate
|
||||
\f[CR]backup.sh\f[R] during the backup process can be used to invalidate
|
||||
plausible deniability.
|
||||
In particular, you should pay attention to the following details:
|
||||
.IP "1." 3
|
||||
The \f[V]--checksum\f[R] option generates an \f[B]UNENCRYPTED\f[R]
|
||||
The \f[CR]\-\-checksum\f[R] option generates an \f[B]UNENCRYPTED\f[R]
|
||||
checksum file containing the \f[I]digests\f[R] of \f[B]EVERY\f[R] file
|
||||
in your backup archive.
|
||||
If your files are known to your adversary(e.g., a banned book), they may
|
||||
@@ -330,74 +283,64 @@ voiding your plausible deniability;
|
||||
.P
|
||||
.PD
|
||||
.IP "2." 3
|
||||
Since \f[V]backup.sh\f[R] is essentially a set of shell commands, an
|
||||
Since \f[CR]backup.sh\f[R] is essentially a set of shell commands, an
|
||||
eavesdropper could monitor the whole backup process to extract the name
|
||||
of the files or the encryption password.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Below there are some examples that demonstrate \f[B]backup.sh\f[R]\[cq]s
|
||||
usage.
|
||||
.IP "1." 3
|
||||
Create a backup of \f[V]/etc/ssh\f[R], \f[V]/var/www\f[R] and
|
||||
\f[V]/var/log\f[R] inside the \f[V]/tmp\f[R] directory using a password
|
||||
stored in \f[V]/home/op1/.backup_pw\f[R]
|
||||
Create a backup of \f[CR]/etc/ssh\f[R], \f[CR]/var/www\f[R] and
|
||||
\f[CR]/var/log\f[R] inside the \f[CR]/tmp\f[R] directory using a
|
||||
password stored in \f[CR]/home/op1/.backup_pw\f[R]
|
||||
.PP
|
||||
The first thing to do is to define the source paths inside a
|
||||
\f[I]sources file\f[R]:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
.EX
|
||||
$> cat sources.bk
|
||||
ssh=/etc/ssh
|
||||
web_root=/var/www
|
||||
logs=/var/log
|
||||
\f[R]
|
||||
.fi
|
||||
ssh=/etc/ssh/
|
||||
web_root=/var/www/
|
||||
singleFile=/home/john/file.txt
|
||||
logs=/var/log/
|
||||
.EE
|
||||
.PP
|
||||
After that we can load our encryption key from the specified file inside
|
||||
an environment variable:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
.EX
|
||||
$> ENC_KEY=$(cat /home/op1/.backup_pw)
|
||||
\f[R]
|
||||
.fi
|
||||
.EE
|
||||
.PP
|
||||
Finally, we can start the backup process with:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> sudo backup.sh --backup sources.bk /tmp $ENC_KEY
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> sudo backup.sh \-\-backup sources.bk /tmp $ENC_KEY
|
||||
.EE
|
||||
.IP "2." 3
|
||||
Extract the content of a backup made on 2023-03-14 with the password
|
||||
Extract the content of a backup made on 2023\-03\-14 with the password
|
||||
`Ax98f!'
|
||||
.PP
|
||||
To do this, we can simply issue the following command:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> backup.sh --extract backup-af9a8e6bfe15-20230314.tar.gz.enc \[dq]Ax98f!\[dq]
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> backup.sh \-\-extract backup\-af9a8e6bfe15\-20230314.tar.gz.enc \[dq]Ax98f!\[dq]
|
||||
.EE
|
||||
.IP "3." 3
|
||||
Extract the content of a backup made on 2018-04-25 using the password in
|
||||
\f[V]/home/john/.pw\f[R]
|
||||
Extract the content of a backup made on 2018\-04\-25 using the password
|
||||
in \f[CR]/home/john/.pw\f[R]
|
||||
.PP
|
||||
This example is very similar to the previous one, we just need to read
|
||||
the password from the text file:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
$> backup.sh --extract backup-af9a8e6bfe15-20180425.tar.gz.enc \[dq]$(cat /home/john/.pw)\[dq]
|
||||
\f[R]
|
||||
.fi
|
||||
.EX
|
||||
$> backup.sh \-\-extract backup\-af9a8e6bfe15\-20180425.tar.gz.enc \[dq]$(cat /home/john/.pw)\[dq]
|
||||
.EE
|
||||
.SH AUTHORS
|
||||
.PP
|
||||
\f[B]backup.sh\f[R] was written by Marco Cetica on late 2018.
|
||||
\f[B]backup.sh\f[R] is being developed by Marco Cetica since late 2018.
|
||||
.SH BUGS
|
||||
.PP
|
||||
Submit bug reports online at: <email@marcocetica.com> or open an issue
|
||||
on the issue tracker of the GitHub page of this project:
|
||||
https://github.com/ice-bit/backup.sh
|
||||
Submit bug reports at: \c
|
||||
.MT email@marcocetica.com
|
||||
.ME \c
|
||||
\ or open an issue on the issue tracker of the GitHub page of this
|
||||
project: https://github.com/ice\-bit/backup.sh
|
||||
|
||||
BIN
bin/backup.sh-1.0.0-2.x86_64.rpm
Normal file
BIN
bin/backup.sh-1.0.0-2.x86_64.rpm
Normal file
Binary file not shown.
BIN
bin/backup.sh-1.0.0.x86_64.deb
Normal file
BIN
bin/backup.sh-1.0.0.x86_64.deb
Normal file
Binary file not shown.
25
man.md
25
man.md
@@ -3,20 +3,24 @@ title: backup.sh
|
||||
section: 1
|
||||
header: General Commands Manual
|
||||
footer: Marco Cetica
|
||||
date: April 4, 2024
|
||||
date: October 21, 2024
|
||||
---
|
||||
|
||||
# NAME
|
||||
**backup.sh** - POSIX compliant, modular and lightweight backup utility to save and encrypt your files.
|
||||
**backup.sh** - POSIX compliant, modular and lightweight backup utility.
|
||||
|
||||
# SYNOPSIS
|
||||
```
|
||||
Syntax: ./backup.sh [-b|-c|-e|-h]
|
||||
Syntax: ./backup.sh [-b|-e|-c|-V|-h]
|
||||
options:
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-V|--verbose Enable verbose mode.
|
||||
-h|--help Show this helper.
|
||||
|
||||
General help with the software: https://github.com/ceticamarco/backup.sh
|
||||
Report bugs to: Marco Cetica(<email@marcocetica.com>)
|
||||
```
|
||||
|
||||
# DESCRIPTION
|
||||
@@ -109,6 +113,8 @@ This will automatically run `backup.sh` every Saturday morning at 03:30 AM. In t
|
||||
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.
|
||||
|
||||
By default `backup.sh` is very quiet, to add some verbosity to the output, be sure to use the `-V`(`--verbose`) option.
|
||||
|
||||
## Backup extraction
|
||||
**backup.sh** can also be used to extract and to verify the encrypted backup.
|
||||
To do so, use the following commands:
|
||||
@@ -216,9 +222,10 @@ The first thing to do is to define the source paths inside a _sources file_:
|
||||
|
||||
```
|
||||
$> cat sources.bk
|
||||
ssh=/etc/ssh
|
||||
web_root=/var/www
|
||||
logs=/var/log
|
||||
ssh=/etc/ssh/
|
||||
web_root=/var/www/
|
||||
singleFile=/home/john/file.txt
|
||||
logs=/var/log/
|
||||
```
|
||||
|
||||
After that we can load our encryption key from the specified file inside an environment variable:
|
||||
@@ -252,8 +259,8 @@ $> backup.sh --extract backup-af9a8e6bfe15-20180425.tar.gz.enc "$(cat /home/john
|
||||
```
|
||||
|
||||
# AUTHORS
|
||||
**backup.sh** was written by Marco Cetica on late 2018.
|
||||
**backup.sh** is being developed by Marco Cetica since late 2018.
|
||||
|
||||
# BUGS
|
||||
Submit bug reports online at: <email@marcocetica.com> or open an issue
|
||||
Submit bug reports at: <email@marcocetica.com> or open an issue
|
||||
on the issue tracker of the GitHub page of this project: https://github.com/ice-bit/backup.sh
|
||||
|
||||
4
tests.sh
4
tests.sh
@@ -51,13 +51,13 @@ create_files() {
|
||||
}
|
||||
|
||||
execute_backup() {
|
||||
./backup.sh -c -b sources.bk "$PWD" badpw
|
||||
./backup.sh -V -c -b sources.bk "$PWD" badpw
|
||||
}
|
||||
|
||||
extract_backup() {
|
||||
host="$(uname -n)"
|
||||
date="$(date +'%Y%m%d')"
|
||||
./backup.sh -c -e "$PWD"/backup-"$host"-"$date".tar.gz.enc badpw "$PWD"/backup-"$host"-"$date".sha256
|
||||
./backup.sh -V -c -e "$PWD"/backup-"$host"-"$date".tar.gz.enc badpw "$PWD"/backup-"$host"-"$date".sha256
|
||||
}
|
||||
|
||||
test_backup() {
|
||||
|
||||
Reference in New Issue
Block a user