From e7ce372e5d0a8753dbbf455f2c85b6394815e299 Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:08:40 +0000 Subject: [PATCH 1/8] backup: append timestamp to mongo-volume backup filename --- backup.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100755 backup.sh diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..87e983c --- /dev/null +++ b/backup.sh @@ -0,0 +1,8 @@ +docker service scale utility-bills-tracker_mongo=0 + +TIMESTAMP=$(date +"%Y-%m-%d-%H-%M") +BACKUP_FILE="mongo-volume-backup-$TIMESTAMP.tar.gz" + +sudo tar -czvpf "$BACKUP_FILE" mongo-volume + +docker service scale utility-bills-tracker_mongo=1 From 8c46cd5e47eb8c98eb48bf3400eb78c8c32d81ad Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:10:52 +0000 Subject: [PATCH 2/8] gitignore: ignore mongo-volume backup tarballs --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3e78d8e..f0b378e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ postgres mongo mongo-volume + +# backup files created by backup.sh +mongo-volume-backup-*.tar.gz From dda78da81550b0a196a75a971cbd2cc74dcdfe36 Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:13:57 +0000 Subject: [PATCH 3/8] backup: write backups to backups/ and rotate (keep 7), gitignore backups/ --- .gitignore | 3 +++ backup.sh | 27 ++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f0b378e..9750d07 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ mongo-volume # backup files created by backup.sh mongo-volume-backup-*.tar.gz + +# backups directory for mongo-volume tarballs +/backups/ diff --git a/backup.sh b/backup.sh index 87e983c..461cce3 100755 --- a/backup.sh +++ b/backup.sh @@ -1,8 +1,33 @@ +#!/usr/bin/env bash +set -euo pipefail + +# scale down mongo service while we copy its volume docker service scale utility-bills-tracker_mongo=0 +# timestamp for filename TIMESTAMP=$(date +"%Y-%m-%d-%H-%M") -BACKUP_FILE="mongo-volume-backup-$TIMESTAMP.tar.gz" + +# backup directory and retention (can be overridden via env) +BACKUP_DIR="${BACKUP_DIR:-backups}" +KEEP="${KEEP:-7}" + +mkdir -p "$BACKUP_DIR" + +BACKUP_FILE="$BACKUP_DIR/mongo-volume-backup-$TIMESTAMP.tar.gz" sudo tar -czvpf "$BACKUP_FILE" mongo-volume +# rotate old backups: keep only the newest $KEEP files +if [ "$KEEP" -gt 0 ]; then + # gather files sorted newest-first + mapfile -t files < <(ls -1t "$BACKUP_DIR"/mongo-volume-backup-*.tar.gz 2>/dev/null || true) + if [ "${#files[@]}" -gt "$KEEP" ]; then + for f in "${files[@]:$KEEP}"; do + echo "Removing old backup: $f" + rm -f -- "$f" + done + fi +fi + +# bring mongo service back up docker service scale utility-bills-tracker_mongo=1 From 64496b8cd89a5ac391da8dfd037e6a2786651a31 Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:22:23 +0000 Subject: [PATCH 4/8] restore: add restore.sh script to restore mongo backups by timestamp --- restore.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 restore.sh diff --git a/restore.sh b/restore.sh new file mode 100755 index 0000000..6be2b93 --- /dev/null +++ b/restore.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: ./restore.sh +# Example: ./restore.sh 2025-08-24-14-30 + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 2025-08-24-14-30" + echo "" + echo "Available backups:" + ls -1t backups/mongo-volume-backup-*.tar.gz 2>/dev/null | sed 's/.*mongo-volume-backup-\(.*\)\.tar\.gz/ \1/' || echo " No backups found" + exit 1 +fi + +TIMESTAMP="$1" +BACKUP_DIR="${BACKUP_DIR:-backups}" +BACKUP_FILE="$BACKUP_DIR/mongo-volume-backup-$TIMESTAMP.tar.gz" + +# Check if backup file exists +if [ ! -f "$BACKUP_FILE" ]; then + echo "Error: Backup file '$BACKUP_FILE' not found" + echo "" + echo "Available backups:" + ls -1t "$BACKUP_DIR"/mongo-volume-backup-*.tar.gz 2>/dev/null | sed 's/.*mongo-volume-backup-\(.*\)\.tar\.gz/ \1/' || echo " No backups found" + exit 1 +fi + +echo "Restoring from backup: $BACKUP_FILE" +echo "WARNING: This will replace the current mongo-volume data!" +read -p "Are you sure you want to continue? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Restore cancelled" + exit 0 +fi + +# Scale down mongo service +echo "Scaling down mongo service..." +docker service scale utility-bills-tracker_mongo=0 + +# Backup current volume (just in case) +SAFETY_BACKUP="mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" +echo "Creating safety backup: $SAFETY_BACKUP" +sudo tar -czf "$SAFETY_BACKUP" mongo-volume 2>/dev/null || true + +# Remove current volume +echo "Removing current mongo-volume..." +sudo rm -rf mongo-volume + +# Extract backup +echo "Extracting backup..." +sudo tar -xzf "$BACKUP_FILE" + +# Set proper permissions +echo "Setting permissions..." +sudo chown -R 999:999 mongo-volume + +# Scale mongo service back up +echo "Scaling mongo service back up..." +docker service scale utility-bills-tracker_mongo=1 + +echo "Restore completed successfully!" +echo "Safety backup saved as: $SAFETY_BACKUP" From 9c298380926b534cb01bf6c33425b0f2fcd42e8a Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:29:01 +0000 Subject: [PATCH 5/8] backup/restore: use MONGO_SERVICE variable for service name --- backup.sh | 7 +++++-- restore.sh | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/backup.sh b/backup.sh index 461cce3..6783abc 100755 --- a/backup.sh +++ b/backup.sh @@ -1,8 +1,11 @@ #!/usr/bin/env bash set -euo pipefail +# Configuration +MONGO_SERVICE="utility-bills-tracker_mongo" + # scale down mongo service while we copy its volume -docker service scale utility-bills-tracker_mongo=0 +docker service scale "$MONGO_SERVICE"=0 # timestamp for filename TIMESTAMP=$(date +"%Y-%m-%d-%H-%M") @@ -30,4 +33,4 @@ if [ "$KEEP" -gt 0 ]; then fi # bring mongo service back up -docker service scale utility-bills-tracker_mongo=1 +docker service scale "$MONGO_SERVICE"=1 diff --git a/restore.sh b/restore.sh index 6be2b93..0854e6a 100755 --- a/restore.sh +++ b/restore.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash set -euo pipefail +# Configuration +MONGO_SERVICE="utility-bills-tracker_mongo" + # Usage: ./restore.sh # Example: ./restore.sh 2025-08-24-14-30 @@ -37,7 +40,7 @@ fi # Scale down mongo service echo "Scaling down mongo service..." -docker service scale utility-bills-tracker_mongo=0 +docker service scale "$MONGO_SERVICE"=0 # Backup current volume (just in case) SAFETY_BACKUP="mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" @@ -58,7 +61,7 @@ sudo chown -R 999:999 mongo-volume # Scale mongo service back up echo "Scaling mongo service back up..." -docker service scale utility-bills-tracker_mongo=1 +docker service scale "$MONGO_SERVICE"=1 echo "Restore completed successfully!" echo "Safety backup saved as: $SAFETY_BACKUP" From 99f65b1433b552d581f7abe93daf47c83145835d Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:46:22 +0000 Subject: [PATCH 6/8] restore: store pre-restore safety backups in backups/ directory --- restore.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restore.sh b/restore.sh index 0854e6a..f65caae 100755 --- a/restore.sh +++ b/restore.sh @@ -43,7 +43,7 @@ echo "Scaling down mongo service..." docker service scale "$MONGO_SERVICE"=0 # Backup current volume (just in case) -SAFETY_BACKUP="mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" +SAFETY_BACKUP="$BACKUP_DIR/mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" echo "Creating safety backup: $SAFETY_BACKUP" sudo tar -czf "$SAFETY_BACKUP" mongo-volume 2>/dev/null || true From b4a6b8d4d3cb8747259e7313ff9dc9e3f8a3fd37 Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:49:21 +0000 Subject: [PATCH 7/8] restore: add interactive pre-backup prompt with automation flags --- restore.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/restore.sh b/restore.sh index f65caae..eef355c 100755 --- a/restore.sh +++ b/restore.sh @@ -4,19 +4,44 @@ set -euo pipefail # Configuration MONGO_SERVICE="utility-bills-tracker_mongo" -# Usage: ./restore.sh -# Example: ./restore.sh 2025-08-24-14-30 +# Parse command line options +SKIP_PRE_BACKUP=false +NO_PRE_BACKUP=false -if [ $# -ne 1 ]; then - echo "Usage: $0 " +while [[ $# -gt 0 ]]; do + case $1 in + --skip-pre-backup) + SKIP_PRE_BACKUP=true + shift + ;; + --no-pre-backup) + NO_PRE_BACKUP=true + shift + ;; + *) + TIMESTAMP="$1" + shift + ;; + esac +done + +# Usage: ./restore.sh [options] +# Example: ./restore.sh 2025-08-24-14-30 +# Options: --skip-pre-backup (skip interactive prompt, create backup) +# --no-pre-backup (skip interactive prompt, no backup) + +if [ -z "${TIMESTAMP:-}" ]; then + echo "Usage: $0 [options] " echo "Example: $0 2025-08-24-14-30" echo "" + echo "Options:" + echo " --skip-pre-backup Skip interactive prompt, create pre-restore backup" + echo " --no-pre-backup Skip interactive prompt, no pre-restore backup" + echo "" echo "Available backups:" ls -1t backups/mongo-volume-backup-*.tar.gz 2>/dev/null | sed 's/.*mongo-volume-backup-\(.*\)\.tar\.gz/ \1/' || echo " No backups found" exit 1 fi - -TIMESTAMP="$1" BACKUP_DIR="${BACKUP_DIR:-backups}" BACKUP_FILE="$BACKUP_DIR/mongo-volume-backup-$TIMESTAMP.tar.gz" @@ -42,10 +67,28 @@ fi echo "Scaling down mongo service..." docker service scale "$MONGO_SERVICE"=0 -# Backup current volume (just in case) -SAFETY_BACKUP="$BACKUP_DIR/mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" -echo "Creating safety backup: $SAFETY_BACKUP" -sudo tar -czf "$SAFETY_BACKUP" mongo-volume 2>/dev/null || true +# Handle pre-restore backup +CREATE_PRE_BACKUP=true +if [ "$NO_PRE_BACKUP" = true ]; then + CREATE_PRE_BACKUP=false +elif [ "$SKIP_PRE_BACKUP" = false ]; then + # Ask user interactively + read -p "Create pre-restore safety backup? (Y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Nn]$ ]]; then + CREATE_PRE_BACKUP=false + fi +fi + +# Create pre-restore backup if requested +if [ "$CREATE_PRE_BACKUP" = true ]; then + SAFETY_BACKUP="$BACKUP_DIR/mongo-volume-pre-restore-$(date +%Y-%m-%d-%H-%M).tar.gz" + echo "Creating safety backup: $SAFETY_BACKUP" + sudo tar -czf "$SAFETY_BACKUP" mongo-volume 2>/dev/null || true +else + echo "Skipping pre-restore backup" + SAFETY_BACKUP="" +fi # Remove current volume echo "Removing current mongo-volume..." @@ -64,4 +107,6 @@ echo "Scaling mongo service back up..." docker service scale "$MONGO_SERVICE"=1 echo "Restore completed successfully!" -echo "Safety backup saved as: $SAFETY_BACKUP" +if [ -n "$SAFETY_BACKUP" ]; then + echo "Safety backup saved as: $SAFETY_BACKUP" +fi From 044645a1ca2ab25b3555b377779b5756760c8442 Mon Sep 17 00:00:00 2001 From: knee-cola Date: Sun, 24 Aug 2025 08:54:45 +0000 Subject: [PATCH 8/8] restore: replace dual flags with single --do-pre-backup=true/false parameter --- restore.sh | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/restore.sh b/restore.sh index eef355c..095e711 100755 --- a/restore.sh +++ b/restore.sh @@ -5,17 +5,12 @@ set -euo pipefail MONGO_SERVICE="utility-bills-tracker_mongo" # Parse command line options -SKIP_PRE_BACKUP=false -NO_PRE_BACKUP=false +DO_PRE_BACKUP="" while [[ $# -gt 0 ]]; do case $1 in - --skip-pre-backup) - SKIP_PRE_BACKUP=true - shift - ;; - --no-pre-backup) - NO_PRE_BACKUP=true + --do-pre-backup=*) + DO_PRE_BACKUP="${1#*=}" shift ;; *) @@ -27,16 +22,15 @@ done # Usage: ./restore.sh [options] # Example: ./restore.sh 2025-08-24-14-30 -# Options: --skip-pre-backup (skip interactive prompt, create backup) -# --no-pre-backup (skip interactive prompt, no backup) +# Options: --do-pre-backup=true/false (skip interactive prompt) if [ -z "${TIMESTAMP:-}" ]; then echo "Usage: $0 [options] " echo "Example: $0 2025-08-24-14-30" echo "" echo "Options:" - echo " --skip-pre-backup Skip interactive prompt, create pre-restore backup" - echo " --no-pre-backup Skip interactive prompt, no pre-restore backup" + echo " --do-pre-backup=true Skip interactive prompt, create pre-restore backup" + echo " --do-pre-backup=false Skip interactive prompt, no pre-restore backup" echo "" echo "Available backups:" ls -1t backups/mongo-volume-backup-*.tar.gz 2>/dev/null | sed 's/.*mongo-volume-backup-\(.*\)\.tar\.gz/ \1/' || echo " No backups found" @@ -69,15 +63,20 @@ docker service scale "$MONGO_SERVICE"=0 # Handle pre-restore backup CREATE_PRE_BACKUP=true -if [ "$NO_PRE_BACKUP" = true ]; then +if [ "$DO_PRE_BACKUP" = "false" ]; then CREATE_PRE_BACKUP=false -elif [ "$SKIP_PRE_BACKUP" = false ]; then +elif [ "$DO_PRE_BACKUP" = "true" ]; then + CREATE_PRE_BACKUP=true +elif [ -z "$DO_PRE_BACKUP" ]; then # Ask user interactively read -p "Create pre-restore safety backup? (Y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Nn]$ ]]; then CREATE_PRE_BACKUP=false fi +else + echo "Error: --do-pre-backup must be 'true' or 'false'" + exit 1 fi # Create pre-restore backup if requested