commit d68fdbb5ba83b0b937301d1bbe8b7d882f25353f Author: ZoopaMario Date: Sun Aug 4 23:10:36 2024 +0200 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..808053f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.env +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/cryptpad/cryptpad-backup.sh b/cryptpad/cryptpad-backup.sh new file mode 100755 index 0000000..537743d --- /dev/null +++ b/cryptpad/cryptpad-backup.sh @@ -0,0 +1,52 @@ +#!/bin/bash +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +source $SCRIPT_ABS_LOCATION/cryptpad-backup.env +source $SCRIPT_ABS_LOCATION/../logger.sh + +# Container Names +CONTAINER="cryptpad" +BACKUP_CONTAINER="duplicati" + +SOURCE_DIR="/mnt/data/cryptpad" +BACKUP_DESTINATION="$BACKUP_DESTINATION" +BACKUP_ENCR_PASSPHRASE="$BACKUP_ENCR_PASSPHRASE" + +# Cloud Storage Authentication +SFTP_USERNAME="$SFTP_USERNAME" +SFTP_PASSWORD="$SFTP_PASSWORD" +SFTP_FINGERPRINT="$SFTP_FINGERPRINT" + +# Log file +LOG_FILE="$SCRIPT_ABS_LOCATION/cryptpad-backup.log" + +# Cleanup inactive and archive files +log "Cleaning up inactive accounts and files to save space..." +docker exec cryptpad \ + /usr/local/bin/node scripts/evict-inactive.js \ + --workdir=/cryptpad || { log "Error: Failed to clean up inactive files"; exit 1; } + +log "Cleaning up archived beyond retention period files to save space..." +docker exec cryptpad \ + /usr/local/bin/node scripts/evict-archived.js \ + --workdir=/cryptpad || { log "Error: Failed to clean up inactive files"; exit 1; } + +# Backup all files to target destination +log "Backing up cryptpad files and database..." +docker exec $BACKUP_CONTAINER \ + duplicati-cli backup ssh://$BACKUP_DESTINATION \ + $SOURCE_DIR/data \ + $SOURCE_DIR/datastore \ + $SOURCE_DIR/block \ + $SOURCE_DIR/blob \ + $SOURCE_DIR/config/config.js \ + $SOURCE_DIR/customize \ + $SOURCE_DIR/customize.dist \ + --backup-name="$CONTAINER backup" \ + --keep-versions=7 \ + --auth-username=$SFTP_USERNAME \ + --auth-password=$SFTP_PASSWORD \ + --passphrase=$BACKUP_ENCR_PASSPHRASE \ + --ssh-fingerprint="$SFTP_FINGERPRINT" \ + --prefix="cryptpad" || { log "Error: Failed to backup cryptpad files and database."; exit 1; } +log "cryptpad backup completed successfully." diff --git a/duplicati/duplicati-backup.sh b/duplicati/duplicati-backup.sh new file mode 100755 index 0000000..fc7b745 --- /dev/null +++ b/duplicati/duplicati-backup.sh @@ -0,0 +1,66 @@ +#!/bin/bash +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +source $SCRIPT_ABS_LOCATION/duplicati-backup.env +source $SCRIPT_ABS_LOCATION/../logger.sh + +# Container Name +CONTAINER="duplicati" + +SOURCE_DIR="/mnt/data/duplicati" +SSH_DESTINATION="$SSH_DESTINATION" +BACKUP_ENCR_PASSPHRASE="$BACKUP_ENCR_PASSPHRASE" + +# Cloud Storage Authentication +SSH_USERNAME="$SSH_USERNAME" +SSH_PASSWORD="$SSH_PASSWORD" +SSH_KEY="$SSH_KEY" + +# Set default values for parameters +MAX_BACKUPS=7 +BACKUP_FOLDER="" + +# Log file +LOG_FILE="$SCRIPT_ABS_LOCATION/duplicati-backup.log" + +# Override default values with command-line arguments +while getopts ":f:h:u:p:m:b:" opt; do + case $opt in + f) SOURCE_DIR="$OPTARG";; + h) SSH_DESTINATION="$OPTARG";; + u) SSH_USERNAME="$OPTARG";; + p) SSH_PASSWORD="$OPTARG";; + m) MAX_BACKUPS="$OPTARG";; + b) BACKUP_FOLDER="$OPTARG";; + \?) echo "Invalid option: -$OPTARG"; exit 1;; + esac +done + +# Create a temporary file for the encrypted archive +TMP_FILENAME=duplicati_db-$(date +"%Y%m%d").bak && +TMP_FILEPATH=$SCRIPT_ABS_LOCATION || { log "Error: Failed to create a temporary file."; exit 1; } + +# Create the encrypted archive using tar and openssl +log "Compressing and excrypting the Duplicati Databases" +sudo tar -czf - "$SOURCE_DIR" | openssl enc -aes-256-cbc -pbkdf2 -pass pass:$BACKUP_ENCR_PASSPHRASE > $TMP_FILEPATH/$TMP_FILENAME || { log "Error: Failed to create encrypted archive."; exit 1; } + + +# Connect to the backup host and count the number of existing backups +log "Fetching number of backups in destination folder" +EXISTING_BACKUPS=$(ssh $SSH_USERNAME@$SSH_DESTINATION -p 23 -i $SSH_KEY "ls" | sudo wc -l) || { log "Error: Failed to count existing backups."; exit 1; } + +# Remove old backups if there are too many +if (( $EXISTING_BACKUPS > $MAX_BACKUPS )); then + log "Removing old backups in order to save space" + ssh $SSH_USERNAME@$SSH_DESTINATION -p 23 -i $SSH_KEY "ls -t $BACKUP_FOLDER | tail -n +$((MAX_BACKUPS+1)) | xargs rm" || { log "Error: Failed to remove old backups."; exit 1; } +fi + +# Transfer the encrypted archive to the backup host using scp +log "Transfering archive to SSH Destination" +scp -v -P 23 -i "$SSH_KEY" "$TMP_FILEPATH/$TMP_FILENAME" "$SSH_USERNAME@$SSH_DESTINATION:$BACKUP_FOLDER$TMP_FILENAME" || { log "Error: Failed to transfer the encrypted archive."; exit 1; } + +# Remove the temporary file +log "Cleaning up files" +rm "$TMP_FILEPATH/$TMP_FILENAME" || { log "Error: Failed to remove the temporary file."; exit 1; } + +log "Backup completed successfully." diff --git a/full-backup.sh b/full-backup.sh new file mode 100755 index 0000000..27792ce --- /dev/null +++ b/full-backup.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +# Define an array of application names +declare -a apps=("cryptpad" "immich" "duplicati" "nextcloud" "vaultwarden") + +# Function to execute the backup script for each application +backup_app() { + local app=$1 + $SCRIPT_ABS_LOCATION/$app/${app}-backup.sh +} + +# Iterate over each app in the array and call the backup function +for app in "${apps[@]}"; do + backup_app "$app" +done + diff --git a/immich/immich-backup.sh b/immich/immich-backup.sh new file mode 100755 index 0000000..96931d0 --- /dev/null +++ b/immich/immich-backup.sh @@ -0,0 +1,55 @@ +#!/bin/bash +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +source $SCRIPT_ABS_LOCATION/immich-backup.env +source $SCRIPT_ABS_LOCATION/../logger.sh + +# Container Names +APP_CONTAINER="immich_server" +DB_CONTAINER="immich_postgres" +BACKUP_CONTAINER="duplicati" + +# Database Settings +DB_USER="postgres" + +SOURCE_DIR="/mnt/data/immich" +BACKUP_DESTINATION="$BACKUP_DESTINATION" +BACKUP_ENCR_PASSPHRASE="$BACKUP_ENCR_PASSPHRASE" + +# Cloud Storage Authentication +SFTP_USERNAME="$SFTP_USERNAME" +SFTP_PASSWORD="$SFTP_PASSWORD" +SFTP_FINGERPRINT="$SFTP_FINGERPRINT" + +# Log file +LOG_FILE="$SCRIPT_ABS_LOCATION/immich-backup.log" + +# Dump Database +log "Dumping immich postgresql database..." +DB_TMP_BAK_NAME="postgres_$(date +"%Y%m%d").bak" +docker exec -t $DB_CONTAINER pg_dumpall \ + --clean \ + --if-exists \ + --username=postgres \ + --file=/var/lib/postgresql/data/$DB_TMP_BAK_NAME || { log "Error: Failed to dump the immich database."; exit 1; } + +# Backup all files to target destination +log "Backing up immich files and database..." +docker exec $BACKUP_CONTAINER duplicati-cli backup ssh://$BACKUP_DESTINATION \ + $SOURCE_DIR/data/library \ + $SOURCE_DIR/data/upload \ + $SOURCE_DIR/data/profile \ + $SOURCE_DIR/postgres/$DB_TMP_BAK_NAME \ + --backup-name="immich backup" \ + --keep-versions=7 \ + --auth-username=$SFTP_USERNAME \ + --auth-password=$SFTP_PASSWORD \ + --passphrase="$BACKUP_ENCR_PASSPHRASE" \ + --ssh-fingerprint="$SFTP_FINGERPRINT" \ + --prefix="immich" || { log "Error: Failed to backup immich files and database."; exit 1; } + +# Delete temporary backup files +log "Deleting temporary backup files..." +docker exec $DB_CONTAINER rm /var/lib/postgresql/data/$DB_TMP_BAK_NAME || { log "Error: Failed to delete temporary backup files."; exit 1; } + +log "immich backup completed successfully." diff --git a/logger.sh b/logger.sh new file mode 100755 index 0000000..d494d4a --- /dev/null +++ b/logger.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Function to log messages +log() { + local message="$1" + echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE" +} diff --git a/nextcloud/nextcloud-backup.sh b/nextcloud/nextcloud-backup.sh new file mode 100755 index 0000000..39cafde --- /dev/null +++ b/nextcloud/nextcloud-backup.sh @@ -0,0 +1,67 @@ +#!/bin/bash +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +source $SCRIPT_ABS_LOCATION/nextcloud-backup.env +source $SCRIPT_ABS_LOCATION/../logger.sh + +# Container Names +APP_CONTAINER="nextcloud-app" +DB_CONTAINER="nextcloud-db" +BACKUP_CONTAINER="duplicati" + +# Database Settings +DB_USER="nextcloud" +DB_PASSWORD="$DB_PASSWORD" + +SOURCE_DIR="/mnt/data/nextcloud" +BACKUP_DESTINATION="$BACKUP_DESTINATION" +BACKUP_ENCR_PASSPHRASE="$BACKUP_ENCR_PASSPHRASE" + +# Cloud Storage Authentication +SFTP_USERNAME="$SFTP_USERNAME" +SFTP_PASSWORD="$SFTP_PASSWORD" +SFTP_FINGERPRINT="$SFTP_FINGERPRINT" + +# Log file +LOG_FILE="$SCRIPT_ABS_LOCATION/nextcloud-backup.log" + +# Put Nextcloud in Maintenance Mode +log "Putting Nextcloud in maintenance mode..." +docker exec -u www-data $APP_CONTAINER php occ maintenance:mode --on || { log "Error: Failed to put Nextcloud in maintenance mode."; exit 1; } + +# Dump Database +log "Dumping Nextcloud database..." +DB_TMP_BAK_NAME="nextcloud-db_$(date +"%Y%m%d").bak" +docker exec $DB_CONTAINER /usr/bin/mariadb-dump \ + --single-transaction \ + -h localhost \ + -u $DB_USER \ + -p"$DB_PASSWORD" \ + nextcloud > $SOURCE_DIR/$DB_TMP_BAK_NAME || { log "Error: Failed to dump the Nextcloud database."; exit 1; } + +# Backup all files to target destination +log "Backing up Nextcloud files and database..." +docker exec $BACKUP_CONTAINER \ + duplicati-cli backup \ + ssh://$BACKUP_DESTINATION \ + "$SOURCE_DIR/html/data" \ + "$SOURCE_DIR/html/config" \ + "$SOURCE_DIR/html/themes" \ + "$SOURCE_DIR/$DB_TMP_BAK_NAME" \ + --backup-name="nextcloud backup" \ + --keep-versions=7 \ + --auth-username=$SFTP_USERNAME \ + --auth-password=$SFTP_PASSWORD \ + --passphrase=$BACKUP_ENCR_PASSPHRASE \ + --ssh-fingerprint="$SFTP_FINGERPRINT" \ + --prefix="nextcloud" || { log "Error: Failed to backup Nextcloud files and database."; exit 1; } + +# Turn off Maintenance Mode +log "Turning off Nextcloud maintenance mode..." +docker exec -u www-data $APP_CONTAINER php occ maintenance:mode --off || { log "Error: Failed to turn off Nextcloud maintenance mode."; exit 1; } + +# Delete temporary backup files +log "Deleting temporary backup files..." +rm $SOURCE_DIR/$DB_TMP_BAK_NAME || { log "Error: Failed to delete temporary databse file"; exit 1; } + +log "Nextcloud backup completed successfully." diff --git a/vaultwarden/vaultwarden-backup.sh b/vaultwarden/vaultwarden-backup.sh new file mode 100755 index 0000000..4e2df9f --- /dev/null +++ b/vaultwarden/vaultwarden-backup.sh @@ -0,0 +1,45 @@ +#!/bin/bash +SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") + +source $SCRIPT_ABS_LOCATION/vaultwarden-backup.env +source $SCRIPT_ABS_LOCATION/../logger.sh + +# Container Names +CONTAINER="vaultwarden" +BACKUP_CONTAINER="duplicati" + +SOURCE_DIR="/mnt/data/vaultwarden" +BACKUP_DESTINATION="$BACKUP_DESTINATION" +BACKUP_ENCR_PASSPHRASE="$BACKUP_ENCR_PASSPHRASE" + +# Cloud Storage Authentication +SFTP_USERNAME="$SFTP_USERNAME" +SFTP_PASSWORD="$SFTP_PASSWORD" +SFTP_FINGERPRINT="$SFTP_FINGERPRINT" + +# Log file +LOG_FILE="$SCRIPT_ABS_LOCATION/vaultwarden-backup.log" + +# Dump Database +log "Dumping vaultwarden database..." +DB_TMP_BAK_NAME=vaultwarden-db_$(date +"%Y%m%d").sqlite3 +sqlite3 $SOURCE_DIR/db.sqlite3 ".backup '$SOURCE_DIR/$DB_TMP_BAK_NAME'" || { log "Error: Failed to dump the Nextcloud database."; exit 1; } + +# Backup all files to target destination +log "Backing up vaultwarden files and database..." +docker exec $BACKUP_CONTAINER duplicati-cli backup \ + ssh://$BACKUP_DESTINATION \ + $SOURCE_DIR \ + --backup-name="vaultwarden backup" \ + --keep-versions=7 \ + --auth-username=$SFTP_USERNAME \ + --auth-password=$SFTP_PASSWORD \ + --passphrase="$BACKUP_ENCR_PASSPHRASE" \ + --ssh-fingerprint="$SFTP_FINGERPRINT" \ + --prefix="vaultwarden" || { log "Error: Failed to backup vaultwarden files and database."; exit 1; } + +# Delete temporary backup files +log "Deleting temporary backup files..." +rm $SOURCE_DIR/$DB_TMP_BAK_NAME || { log "Error: Failed to delete temporary backup files."; exit 1; } + +log "vaultwarden backup completed successfully."