This commit is contained in:
Geoffrey Frogeye 2019-08-02 19:25:33 +02:00
parent ed2afd876c
commit 4e3fa8285b
3 changed files with 121 additions and 13 deletions

View file

@ -1,10 +1,52 @@
# ckupeye # ckupeye
Small bash script for entire server backups. Small bash script for entire filesystem backups.
It backups filesystems, sure, but also creates workable version of It backups filesystems, sure, but also creates workable version of
PostgreSQL / MariaDB backups, Pacman / Apt software list, ACL. PostgreSQL / MariaDB backups, Pacman / Apt software list, ACL.
It then uses [BorgBackup](https://www.borgbackup.org/) to create, compress, encrypt and send the backups. It then uses [BorgBackup](https://www.borgbackup.org/) to create, compress, encrypt and send the backups.
You'd probably want to be familiar with the latter if you want to understand this script fully.
**DISCLAIMER:** This program is just a publication of my personal script.
It haven't been tested outside of my (very) specific use case.
You'd probably better use it as a reference rather than as is.
## Usage
Basically it's just the `ckupeye` script.
Have some example installation instructions, for the client.
```bash
git clone https://git.frogeye.fr/geoffrey/ckupeye.git /opt/ckupeye
ln -s /opt/ckupeye/ckupeye /usr/local/bin/ckupeye
mkdir /etc/ckupeye
mkdir /var/lib/ckupeye
cp /opt/ckupeye/config.sample.sh /etc/ckupeye/config.sh
ssh-keygen -t ed25519 -C ckupeye@$(cat /etc/hostname) -f /etc/ckupeye/id_ed25519
$EDITOR /etc/ckupeye/config.sh
```
And to run it, just `ckupeye`.
Or, if you don't want to pollute your '/' namespace,
provide an argument to the configuration file, as so:
```bash
/path/to/ckupeye /path/to/config.sh
```
For the server, I would recommend having an account for backups (or one account per backup for extra security),
and use a [ssh forced command](https://borgbackup.readthedocs.io/en/stable/usage/serve.html#examples).
Add something like the following to the user's `~/.ssh/authorized_keys`:
```
restrict,command="borg serve --restrict-to-repository=/var/lib/borg/clientname --append-only --storage-quota=150G" ssh-ed25519 ... ckupeye@clientname
```
## Configuration
At minimum you will need to set `BORG_REPO` and a `BORG_PASSPHRASE` in the config file.
## Notation ## Notation

View file

@ -42,7 +42,7 @@ fi
# Default configuration # Default configuration
# #
: "${BASE_DIR:="/var/ckupeye"}" : "${BASE_DIR:="/var/lib/ckupeye"}"
# Directories to backup # Directories to backup
[ -z ${BACKUP_FILES+x} ] && BACKUP_FILES=("/") # What to include in the backup [ -z ${BACKUP_FILES+x} ] && BACKUP_FILES=("/") # What to include in the backup
@ -76,7 +76,7 @@ fi
: "${EXPORT_MARIADB_CREDENTIALS:="$BASE_DIR/mariadb.cnf"}" : "${EXPORT_MARIADB_CREDENTIALS:="$BASE_DIR/mariadb.cnf"}"
# Pruning the backup # Pruning the backup
: "${PRUNE:="true"}" : "${PRUNE:="false"}"
: "${PRUNE_OPTIONS:="--keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 10"}" : "${PRUNE_OPTIONS:="--keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 10"}"
# Borg specific # Borg specific
@ -88,15 +88,18 @@ fi
: "${BORG_ENCRYPTION:="repokey-blake2"}" # Passed `borg init` : "${BORG_ENCRYPTION:="repokey-blake2"}" # Passed `borg init`
# Answer borg questions # Answer borg questions
: "${BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK:=no}" : "${BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK:="no"}"
: "${BORG_RELOCATED_REPO_ACCESS_IS_OK:=no}" : "${BORG_RELOCATED_REPO_ACCESS_IS_OK:="no"}"
: "${BORG_CHECK_I_KNOW_WHAT_I_AM_DOING:=NO}" : "${BORG_CHECK_I_KNOW_WHAT_I_AM_DOING:="NO"}"
: "${BORG_DELETE_I_KNOW_WHAT_I_AM_DOING:=NO}" : "${BORG_DELETE_I_KNOW_WHAT_I_AM_DOING:="NO"}"
: "${BORG_RECREATE_I_KNOW_WHAT_I_AM_DOING:=NO}" : "${BORG_RECREATE_I_KNOW_WHAT_I_AM_DOING:="NO"}"
# Ckupeye specific # Ckupeye specific
: "${CLIENT_RUNFILE:="$BASE_DIR/ckupeye.pid"}" : "${CLIENT_RUNFILE:="$BASE_DIR/ckupeye.pid"}"
# Vim macro to copy the above defaults to the config file (minus the arrays):
# :%s/: "\${\(\w\+\):=\(.\+\)}"/\1=\2
# Export borg environment variables # Export borg environment variables
export BORG_REPO export BORG_REPO
export BORG_PASSPHRASE export BORG_PASSPHRASE
@ -129,7 +132,7 @@ echo $$ > $CLIENT_RUNFILE
if [ ! -z "$BORG_SSH_IDENTITY_FILE" ] if [ ! -z "$BORG_SSH_IDENTITY_FILE" ]
then then
export BORG_RSH="ssh -oBatchMode=yes -i $BORG_SSH_IDENTITY_FILE $BORG_RSH_EXTRA" export BORG_RSH="ssh -oIdentitiesOnly=yes -oBatchMode=yes -i $BORG_SSH_IDENTITY_FILE $BORG_RSH_EXTRA"
fi fi
echo "→ Opening repository" echo "→ Opening repository"
@ -164,24 +167,25 @@ then
etckeeper commit "$EXPORT_ETCKEEPER_MESSAGE" &> /dev/null & etckeeper commit "$EXPORT_ETCKEEPER_MESSAGE" &> /dev/null &
fi fi
export EXPORT_FILEs=""
function _feedExport() { # export_file function _feedExport() { # export_file
touch "$1" touch "$1"
chmod 700 "$1" chmod 700 "$1"
cat - > "$1" cat - > "$1"
export EXPORT_FILES="$1 $EXPORT_FILES"
} }
EXPORT_FILEs=""
if $EXPORT_ACL if $EXPORT_ACL
then then
echo → Exporting ACL echo → Exporting ACL
sudo getfacl -R "$EXPORT_ACL_DESTINATION[@]" 2> /dev/null | _feedExport "$EXPORT_ACL_FILE" sudo getfacl -R "$EXPORT_ACL_DESTINATION[@]" 2> /dev/null | _feedExport "$EXPORT_ACL_FILE"
EXPORT_FILES="$EXPORT_ACL_FILE $EXPORT_FILES"
fi fi
if $EXPORT_POSTGRESQL if $EXPORT_POSTGRESQL
then then
echo → Exporting PostgreSQL echo → Exporting PostgreSQL
pg_dumpall $EXPORT_POSTGRESQL_OPTIONS | _feedExport "$EXPORT_POSTGRESQL_FILE" pg_dumpall $EXPORT_POSTGRESQL_OPTIONS | _feedExport "$EXPORT_POSTGRESQL_FILE"
EXPORT_FILES="$EXPORT_POSTGRESQL_FILE $EXPORT_FILES"
fi fi
if $EXPORT_MARIADB if $EXPORT_MARIADB
@ -192,28 +196,31 @@ then
EXPORT_MARIADB_OPTIONS="--defaults-extra-file=$EXPORT_MARIADB_CREDENTIALS $EXPORT_MARIADB_OPTIONS" EXPORT_MARIADB_OPTIONS="--defaults-extra-file=$EXPORT_MARIADB_CREDENTIALS $EXPORT_MARIADB_OPTIONS"
fi fi
mysqldump $EXPORT_MARIADB_OPTIONS | _feedExport "$EXPORT_MARIADB_FILE" mysqldump $EXPORT_MARIADB_OPTIONS | _feedExport "$EXPORT_MARIADB_FILE"
EXPORT_FILES="$EXPORT_MARIADB_FILE $EXPORT_FILES"
fi fi
if $EXPORT_PACMAN if $EXPORT_PACMAN
then then
echo → Exporting Pacman package list echo → Exporting Pacman package list
pacman -Qeq | _feedExport "$EXPORT_PACMAN_FILE" pacman -Qeq | _feedExport "$EXPORT_PACMAN_FILE"
EXPORT_FILES="$EXPORT_PACMAN_FILE $EXPORT_FILES"
fi fi
if $EXPORT_APT if $EXPORT_APT
then then
echo → Exporting Apt package list echo → Exporting Apt package list
apt list --installed 2> /dev/null | _feedExport "$EXPORT_APT_FILE" apt list --installed 2> /dev/null | _feedExport "$EXPORT_APT_FILE"
EXPORT_FILES="$EXPORT_APT_FILE $EXPORT_FILES"
fi fi
echo "→ Transfering files" echo "→ Transfering files"
for exclude in "${BACKUP_EXCLUDES[@]}" for exclude in "${BACKUP_EXCLUDES[@]}"
do do
BACKUP_OPTIONS="$BORG_CREATE_OPTIONS --exclude=$exclude" BACKUP_OPTIONS="$BACKUP_OPTIONS --exclude=$exclude"
done done
$BORG_EXECUTABLE $BORG_OPTIONS create --stats $BACKUP_OPTIONS "${BORG_REPO}::${BACKUP_TAG}" ${BACKUP_FILES[@]} 2>&1 $BORG_EXECUTABLE $BORG_OPTIONS create --stats $BACKUP_OPTIONS "${BORG_REPO}::${BACKUP_TAG}" ${BACKUP_FILES[@]} $EXPORT_FILES 2>&1
echo "→ Remove temporary files" echo "→ Remove temporary files"
rm -f $EXPORT_FILES rm -f $EXPORT_FILES

59
config.sample.sh Normal file
View file

@ -0,0 +1,59 @@
#!/usr/bin/env bash
BASE_DIR="/var/lib/ckupeye"
BORG_REPO="ssh://user@server:port/~/client"
BORG_PASSPHRASE=""
# Directories to backup
BACKUP_FILES=("/") # What to include in the backup
BACKUP_EXCLUDES=("/var/cache" "**.lock" "**/.cache/") # What to exclue from the backup
BACKUP_TAG="$(date -Isec)" # “Name” of the backup
BACKUP_OPTIONS="--one-file-system --compression auto,zstd" # Configuration of the backup
# Default folder where the database / package managers / ACL exported data will be stored.
EXPORT_DIR="$BASE_DIR"
# Things to export the data of
EXPORT_MARIADB="false"
EXPORT_POSTGRESQL="false"
EXPORT_APT="false"
EXPORT_PACMAN="false"
EXPORT_ACL="false"
EXPORT_ETCKEEPER="false"
# Where to put the exported data
EXPORT_MARIADB_FILE="$EXPORT_DIR/mariadb.sql"
EXPORT_POSTGRESQL_FILE="$EXPORT_DIR/postgresql.sql"
EXPORT_APT_FILE="$EXPORT_DIR/apt.list"
EXPORT_PACMAN_FILE="$EXPORT_DIR/pacman.list"
EXPORT_ACL_FILE="$EXPORT_DIR/acl.list"
# Options for exporting data
EXPORT_ACL_DIRECTORIES=("${BACKUP_FILES[@]}")
EXPORT_ETCKEEPER_MESSAGE="ckupeye backup for $(date -Isec)"
EXPORT_POSTGRESQL_OPTIONS=""
EXPORT_MARIADB_OPTIONS="--all-databases --flush-privileges"
EXPORT_MARIADB_CREDENTIALS="$BASE_DIR/mariadb.cnf"
# Pruning the backup
PRUNE="false"
PRUNE_OPTIONS="--keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 10"
# Borg specific
BORG_BASE_DIR="$BASE_DIR"
BORG_EXECUTABLE="$(command -v borg)" # Path to BorgBackup executable
BORG_SSH_IDENTITY_FILE="/etc/ckupeye/id_ed25519" # Identity file to use to connect to remote repo (will overwrite $BORG_RSH)
BORG_RSH_EXTRA="" # Options to add to $BORG_RSH (even after overriden by BORG_SSH_IDENTITY_FILE)
BORG_OPTIONS="" # Additional options to pass to BorgBackup
BORG_ENCRYPTION="repokey-blake2" # Passed `borg init`
# Answer borg questions
BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK="no"
BORG_RELOCATED_REPO_ACCESS_IS_OK="no"
BORG_CHECK_I_KNOW_WHAT_I_AM_DOING="NO"
BORG_DELETE_I_KNOW_WHAT_I_AM_DOING="NO"
BORG_RECREATE_I_KNOW_WHAT_I_AM_DOING="NO"
# Ckupeye specific
CLIENT_RUNFILE="$BASE_DIR/ckupeye.pid"