diff --git a/README.md b/README.md index 947eff9..d0d7033 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,52 @@ # 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 PostgreSQL / MariaDB backups, Pacman / Apt software list, ACL. + 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 diff --git a/backup.sh b/ckupeye similarity index 85% rename from backup.sh rename to ckupeye index f551f20..d769556 100755 --- a/backup.sh +++ b/ckupeye @@ -42,7 +42,7 @@ fi # Default configuration # -: "${BASE_DIR:="/var/ckupeye"}" +: "${BASE_DIR:="/var/lib/ckupeye"}" # Directories to 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"}" # Pruning the backup -: "${PRUNE:="true"}" +: "${PRUNE:="false"}" : "${PRUNE_OPTIONS:="--keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 10"}" # Borg specific @@ -88,15 +88,18 @@ fi : "${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}" +: "${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"}" +# Vim macro to copy the above defaults to the config file (minus the arrays): +# :%s/: "\${\(\w\+\):=\(.\+\)}"/\1=\2 + # Export borg environment variables export BORG_REPO export BORG_PASSPHRASE @@ -129,7 +132,7 @@ echo $$ > $CLIENT_RUNFILE if [ ! -z "$BORG_SSH_IDENTITY_FILE" ] 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 echo "→ Opening repository" @@ -164,24 +167,25 @@ then etckeeper commit "$EXPORT_ETCKEEPER_MESSAGE" &> /dev/null & fi -export EXPORT_FILEs="" function _feedExport() { # export_file touch "$1" chmod 700 "$1" cat - > "$1" - export EXPORT_FILES="$1 $EXPORT_FILES" } +EXPORT_FILEs="" if $EXPORT_ACL then echo → Exporting ACL sudo getfacl -R "$EXPORT_ACL_DESTINATION[@]" 2> /dev/null | _feedExport "$EXPORT_ACL_FILE" + EXPORT_FILES="$EXPORT_ACL_FILE $EXPORT_FILES" fi if $EXPORT_POSTGRESQL then echo → Exporting PostgreSQL pg_dumpall $EXPORT_POSTGRESQL_OPTIONS | _feedExport "$EXPORT_POSTGRESQL_FILE" + EXPORT_FILES="$EXPORT_POSTGRESQL_FILE $EXPORT_FILES" fi if $EXPORT_MARIADB @@ -192,28 +196,31 @@ then EXPORT_MARIADB_OPTIONS="--defaults-extra-file=$EXPORT_MARIADB_CREDENTIALS $EXPORT_MARIADB_OPTIONS" fi mysqldump $EXPORT_MARIADB_OPTIONS | _feedExport "$EXPORT_MARIADB_FILE" + EXPORT_FILES="$EXPORT_MARIADB_FILE $EXPORT_FILES" fi if $EXPORT_PACMAN then echo → Exporting Pacman package list pacman -Qeq | _feedExport "$EXPORT_PACMAN_FILE" + EXPORT_FILES="$EXPORT_PACMAN_FILE $EXPORT_FILES" fi if $EXPORT_APT then echo → Exporting Apt package list apt list --installed 2> /dev/null | _feedExport "$EXPORT_APT_FILE" + EXPORT_FILES="$EXPORT_APT_FILE $EXPORT_FILES" fi echo "→ Transfering files" for exclude in "${BACKUP_EXCLUDES[@]}" do - BACKUP_OPTIONS="$BORG_CREATE_OPTIONS --exclude=$exclude" + BACKUP_OPTIONS="$BACKUP_OPTIONS --exclude=$exclude" 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" rm -f $EXPORT_FILES diff --git a/config.sample.sh b/config.sample.sh new file mode 100644 index 0000000..921e446 --- /dev/null +++ b/config.sample.sh @@ -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" +