diff --git a/common-backup.sh b/common-backup.sh new file mode 100755 index 0000000..209218c --- /dev/null +++ b/common-backup.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +stop_container() { + local c="$1" + log "Stopping $c..." + docker stop "$c" || { log "Error stopping $c"; exit 1; } +} + +start_container() { + local c="$1" + log "Starting $c..." + docker start "$c" || { log "Error starting $c"; exit 1; } +} + +enable_maintenance_mode() { + local c="$1" + local cmd="$2" + log "Enabling maintenance mode for $c..." + docker exec -u www-data "$c" $cmd || { log "Error enabling maintenance mode"; exit 1; } +} + +disable_maintenance_mode() { + local c="$1" + local cmd="$2" + log "Disabling maintenance mode for $c..." + docker exec -u www-data "$c" $cmd || { log "Error disabling maintenance mode"; exit 1; } +} + +dump_postgres_db() { + local c="$1" + local user="$2" + local path="$3" + log "Dumping PostgreSQL db..." + docker exec -t "$c" pg_dumpall --clean --if-exists --username="$user" --file="$path" || { log "Error dumping PostgreSQL"; exit 1; } +} + +dump_mariadb_db() { + local c="$1" + local user="$2" + local pass="$3" + local db="$4" + local path="$5" + log "Dumping MariaDB/MySQL db..." + docker exec "$c" mariadb-dump --single-transaction -h localhost -u "$user" -p"$pass" "$db" > "$path" || { log "Error dumping MariaDB/MySQL"; exit 1; } +} + +dump_sqlite_db() { + local src="$1" + local dst="$2" + log "Dumping SQLite db..." + sqlite3 "$src" ".backup $dst" || { log "Error dumping SQLite"; exit 1; } +} + +run_duplicati_backup() { + local c="$1" + local dest="$2" + local name="$3" + local versions="$4" + local sftp_user="$5" + local sftp_pass="$6" + local passphrase="$7" + local fingerprint="$8" + shift 8 + local sources=("$@") + log "Running duplicati backup for $name..." + docker exec "$c" duplicati-cli backup "$dest" "${sources[@]}" \ + --backup-name="$name" \ + --keep-versions="$versions" \ + --auth-username="$sftp_user" \ + --auth-password="$sftp_pass" \ + --passphrase="$passphrase" \ + --ssh-fingerprint="$fingerprint" \ + --prefix="$name" || { log "Error in duplicati backup for $name"; exit 1; } + log "$name backup complete." +} + diff --git a/cryptpad/cryptpad-backup.sh b/cryptpad/cryptpad-backup.sh index 590c68a..866960c 100755 --- a/cryptpad/cryptpad-backup.sh +++ b/cryptpad/cryptpad-backup.sh @@ -1,48 +1,38 @@ #!/bin/bash -SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") +SCRIPT_ABS_LOCATION="$(realpath "$(dirname "$0")")" # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/cryptpad-backup.env" +source "$SCRIPT_ABS_LOCATION/cryptpad-backup.env"; \ # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/../logger.sh" +source "$SCRIPT_ABS_LOCATION/../logger.sh"; \ -# Container Names -CONTAINER="cryptpad" -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/cryptpad-backup.log" -SOURCE_DIR="/mnt/data/cryptpad" +log "Cleaning up inactive files..." +docker exec cryptpad /usr/local/bin/node scripts/evict-inactive.js --workdir=/cryptpad || { log "Error cleaning up inactive files"; exit 1; } -# 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 files..." +docker exec cryptpad /usr/local/bin/node scripts/evict-archived.js --workdir=/cryptpad || { log "Error cleaning up archived 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; } +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "cryptpad" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ + "$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 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/forgejo/forgejo-backup.sh b/forgejo/forgejo-backup.sh index 4c6a245..d5bbe28 100755 --- a/forgejo/forgejo-backup.sh +++ b/forgejo/forgejo-backup.sh @@ -1,41 +1,30 @@ #!/bin/bash -SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") +SCRIPT_ABS_LOCATION="$(realpath "$(dirname "$0")")" # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/forgejo-backup.env" +source "$SCRIPT_ABS_LOCATION/forgejo-backup.env"; / # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/../logger.sh" +source "$SCRIPT_ABS_LOCATION/../logger.sh"; / -# Container Names -APP_CONTAINER="forgejo" -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/forgejo-backup.log" -SOURCE_DIR="/mnt/data/forgejo" +stop_container "$APP_CONTAINER" -# Stop forgejo container -log "Stopping forgejo container..." -docker stop $APP_CONTAINER || { log "Error: Failed to stop forgejo."; exit 1; } +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "forgejo" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ + "$SOURCE_DIR" -# Backup all files to target destination -log "Backing up forgejo files (including the SQLite database)..." -docker exec $BACKUP_CONTAINER \ - duplicati-cli backup \ - "ssh://$BACKUP_DESTINATION" \ - "$SOURCE_DIR" \ - --backup-name="forgejo backup" \ - --keep-versions=7 \ - --auth-username="$SFTP_USERNAME" \ - --auth-password="$SFTP_PASSWORD" \ - --passphrase="$BACKUP_ENCR_PASSPHRASE" \ - --ssh-fingerprint="$SFTP_FINGERPRINT" \ - --prefix="forgejo" || { log "Error: Failed to backup forgejo files and database."; exit 1; } +start_container "$APP_CONTAINER" -# Turn off Maintenance Mode -log "Starting forgejo container..." -docker start "$APP_CONTAINER" || { log "Error: Failed to start forgejo container."; exit 1; } - -log "Forgejo backup completed successfully." diff --git a/immich/immich-backup.sh b/immich/immich-backup.sh index 4e2568f..1685442 100755 --- a/immich/immich-backup.sh +++ b/immich/immich-backup.sh @@ -2,49 +2,42 @@ SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/immich-backup.env" +source "$SCRIPT_ABS_LOCATION/immich-backup.env"; \ # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/../logger.sh" +source "$SCRIPT_ABS_LOCATION/../logger.sh"; \ -# Container Names -DB_CONTAINER="immich_postgres" -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/immich-backup.log" -# Database Settings +DB_CONTAINER="immich_postgres" +BACKUP_CONTAINER="duplicati" DB_USER="postgres" - SOURCE_DIR="/mnt/data/immich" - -# 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="$DB_USER" \ - --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" \ +dump_postgres_db "$DB_CONTAINER" "$DB_USER" "/var/lib/postgresql/data/$DB_TMP_BAK_NAME" + +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "immich" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ "$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; } + "$SOURCE_DIR/postgres/$DB_TMP_BAK_NAME" -# 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 "Deleting immich temp DB backup..." +docker exec "$DB_CONTAINER" rm "/var/lib/postgresql/data/$DB_TMP_BAK_NAME" || { + log "Error: Failed to delete temp DB backup." + exit 1 +} -log "immich backup completed successfully." diff --git a/logger.sh b/logger.sh index d494d4a..fa65f32 100755 --- a/logger.sh +++ b/logger.sh @@ -1,7 +1,6 @@ #!/bin/bash -# Function to log messages log() { - local message="$1" - echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE" + 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 index da69855..477ec0e 100755 --- a/nextcloud/nextcloud-backup.sh +++ b/nextcloud/nextcloud-backup.sh @@ -2,61 +2,47 @@ SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/nextcloud-backup.env" +source "$SCRIPT_ABS_LOCATION/nextcloud-backup.env"; \ # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/../logger.sh" +source "$SCRIPT_ABS_LOCATION/../logger.sh"; \ -# Container Names -APP_CONTAINER="nextcloud-app" -DB_CONTAINER="nextcloud-db" -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/nextcloud-backup.log" -# Database Settings -DB_USER="nextcloud" - +APP_CONTAINER="nextcloud-app" +DB_CONTAINER="nextcloud-db" +BACKUP_CONTAINER="duplicati" +DB_USER="nextcloud" SOURCE_DIR="/mnt/data/nextcloud" - -# 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; } +enable_maintenance_mode "$APP_CONTAINER" "php occ maintenance:mode --on" -# 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; } +dump_mariadb_db "$DB_CONTAINER" "$DB_USER" "$DB_PASSWORD" "nextcloud" "$SOURCE_DIR/$DB_TMP_BAK_NAME" -# 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; } +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "nextcloud" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ + "$SOURCE_DIR/html/data" \ + "$SOURCE_DIR/html/config" \ + "$SOURCE_DIR/html/themes" \ + "$SOURCE_DIR/$DB_TMP_BAK_NAME" + +disable_maintenance_mode "$APP_CONTAINER" "php occ maintenance:mode --off" + +log "Deleting Nextcloud temp DB backup..." +rm "$SOURCE_DIR/$DB_TMP_BAK_NAME" || { + log "Error: Failed to delete temp DB backup." + exit 1 +} -log "Nextcloud backup completed successfully." diff --git a/portainer/portainer-backup.sh b/portainer/portainer-backup.sh index 701c0b8..cd73e81 100755 --- a/portainer/portainer-backup.sh +++ b/portainer/portainer-backup.sh @@ -7,35 +7,28 @@ source "$SCRIPT_ABS_LOCATION/portainer-backup.env" # shellcheck disable=SC1090 source "$SCRIPT_ABS_LOCATION/../logger.sh" -# Container Names -APP_CONTAINER="portainer" -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/portainer-backup.log" +APP_CONTAINER="portainer" +BACKUP_CONTAINER="duplicati" SOURCE_DIR="/volumes/portainer" -# Stop portainer container -log "Stopping portainer container..." -docker stop $APP_CONTAINER || { log "Error: Failed to stop portainer."; exit 1; } +stop_container "$APP_CONTAINER" -# Backup all files to target destination -log "Backing up portainer files (including the SQLite database)..." -docker exec "$BACKUP_CONTAINER" \ - duplicati-cli backup \ - "ssh://$BACKUP_DESTINATION" \ - "$SOURCE_DIR" \ - --backup-name="portainer backup" \ - --keep-versions=7 \ - --auth-username="$SFTP_USERNAME" \ - --auth-password="$SFTP_PASSWORD" \ - --passphrase="$BACKUP_ENCR_PASSPHRASE" \ - --ssh-fingerprint="$SFTP_FINGERPRINT" \ - --prefix="portainer" || { log "Error: Failed to backup portainer files and database."; exit 1; } +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "portainer" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ + "$SOURCE_DIR" -# Turn off Maintenance Mode -log "Starting portainer container..." -docker start "$APP_CONTAINER" || { log "Error: Failed to start portainer container."; exit 1; } +start_container "$APP_CONTAINER" -log "portainer backup completed successfully." diff --git a/vaultwarden/vaultwarden-backup.sh b/vaultwarden/vaultwarden-backup.sh index 9c7e2e3..b54724a 100755 --- a/vaultwarden/vaultwarden-backup.sh +++ b/vaultwarden/vaultwarden-backup.sh @@ -2,39 +2,37 @@ SCRIPT_ABS_LOCATION=$(realpath "$(dirname "${0}")") # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/vaultwarden-backup.env" +source "$SCRIPT_ABS_LOCATION/vaultwarden-backup.env"; \ # shellcheck disable=SC1090 -source "$SCRIPT_ABS_LOCATION/../logger.sh" +source "$SCRIPT_ABS_LOCATION/../logger.sh"; \ -# Container Names -BACKUP_CONTAINER="duplicati" +# shellcheck disable=SC1090 +source "$SCRIPT_ABS_LOCATION/../common-backup.sh" # shellcheck disable=SC2034 LOG_FILE="$SCRIPT_ABS_LOCATION/vaultwarden-backup.log" +BACKUP_CONTAINER="duplicati" SOURCE_DIR="/mnt/data/vaultwarden" +DB_TMP_BAK_NAME="vaultwarden-db_$(date +"%Y%m%d").sqlite3" -# 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; } +dump_sqlite_db "$SOURCE_DIR/db.sqlite3" "$SOURCE_DIR/$DB_TMP_BAK_NAME" -# 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; } +run_duplicati_backup \ + "$BACKUP_CONTAINER" \ + "$BACKUP_DESTINATION" \ + "vaultwarden" \ + 7 \ + "$SFTP_USERNAME" \ + "$SFTP_PASSWORD" \ + "$BACKUP_ENCR_PASSPHRASE" \ + "$SFTP_FINGERPRINT" \ + "$SOURCE_DIR" -# 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 "Deleting vaultwarden temp DB backup..." +rm "$SOURCE_DIR/$DB_TMP_BAK_NAME" || { + log "Error: Failed to delete temp DB backup." + exit 1 +} -log "vaultwarden backup completed successfully."