From ddb114083c917b3f61aff56930b8efe594dd362a Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 14:37:16 +0200 Subject: [PATCH 1/9] Added the backup strategy --- compose-dev.yml | 2 +- compose.yml | 2 +- config/backup/backup.sh | 28 +++++++++++++++++++ config/backup/compose-backup.yml | 20 +++++++++++++ config/backup/readme.md | 48 ++++++++++++++++++++++++++++++++ config/backup/restore.sh | 29 +++++++++++++++++++ config/example.env | 22 ++++++++++++--- 7 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 config/backup/backup.sh create mode 100644 config/backup/compose-backup.yml create mode 100644 config/backup/readme.md create mode 100644 config/backup/restore.sh diff --git a/compose-dev.yml b/compose-dev.yml index f0534969..9afd5b4b 100644 --- a/compose-dev.yml +++ b/compose-dev.yml @@ -1,6 +1,6 @@ services: lucee: - image: ${LUCEE_IMAGE} + image: ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} ports: - "${LUCEE_PORT}:80" restart: always diff --git a/compose.yml b/compose.yml index 839357c8..d5150727 100644 --- a/compose.yml +++ b/compose.yml @@ -1,6 +1,6 @@ services: lucee: - image: ${LUCEE_IMAGE} + image: ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} ports: - "${LUCEE_PORT}:80" restart: always diff --git a/config/backup/backup.sh b/config/backup/backup.sh new file mode 100644 index 00000000..40af3eaf --- /dev/null +++ b/config/backup/backup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Activates the automatic export of variables +set -a + +# Load the .env file +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$PROJECT_ROOT/.env" + +# Deactivates the automatic export of variables +set +a + +# Checks whether the /backup folder exists and creates it if required +if [ ! -d "/backup" ]; then + mkdir -p /backup +fi + +# Backup database +docker compose -f compose-backup.yml run db_backup +scp -i ${SSH_KEY_PATH} /backup/database.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} + +# Backup userdata +docker compose -f compose-backup.yml run userdata_backup +scp -i ${SSH_KEY_PATH} /backup/userdata.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} + +# Backup Lucee image +docker compose -f compose-backup.yml run lucee_image_backup +scp -i ${SSH_KEY_PATH} /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} \ No newline at end of file diff --git a/config/backup/compose-backup.yml b/config/backup/compose-backup.yml new file mode 100644 index 00000000..5e3908da --- /dev/null +++ b/config/backup/compose-backup.yml @@ -0,0 +1,20 @@ +services: + db_backup: + image: alpine + volumes: + - ${COMPOSE_PROJECT_NAME}_db_volume:/volume + - /backup:/backup + command: tar -czf /backup/database.tar.gz -C /volume . + + userdata_backup: + image: alpine + volumes: + - ${COMPOSE_PROJECT_NAME}_userdata_volume:/volume + - /backup:/backup + command: tar -czf /backup/userdata.tar.gz -C /volume . + + lucee_image_backup: + image: alpine + volumes: + - /backup:/backup + command: docker save -o /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} \ No newline at end of file diff --git a/config/backup/readme.md b/config/backup/readme.md new file mode 100644 index 00000000..f0aab81f --- /dev/null +++ b/config/backup/readme.md @@ -0,0 +1,48 @@ +***Backup for the Production Environment*** + +**Purpose** + +This directory contains the configurations and scripts for backing up and restoring the database, user data, and the Lucee image. These backups are intended only for the production environment. + +By utilizing Docker Compose and shell scripts, the backup process is automated to ensure consistent and reliable data backups with minimal manual intervention. + +**Structure** + +- .env: This file contains environment variables specifically for backup and restoration in the production environment. Variables like volume names, image versions, and SSH credentials are defined here. + +- compose-backup.yml: This file defines the container services needed to create backups. Each service performs a backup for the database, user data, or the Lucee image. + +- backup.sh: A shell script that automates the process of backing up the database, user data, and Lucee image. It uses Docker Compose and secure copying (SCP) to transfer backups to the designated backup server. + +- restore.sh: A shell script that automates the process of restoring the database, user data, and Lucee image. It retrieves backups from the backup server and restores them to the appropriate volumes. + +**Usage** + +*Backup* + +To create a backup, run the following command from this directory: + + sh backup.sh + +This will: +1. Backup the database volume. +2. Backup the user data volume. +3. Backup the Lucee image. +4. Securely transfer all backups to the remote backup server. + +*Restore* +To restore from a backup, run the following command: + + sh restore.sh + +This will: + +1. Retrieve the latest backups from the remote backup server. +2. Restore the database volume. +3. Restore the user data volume. +4. Load the Lucee image into Docker. + +**Notes** +- The backups created by this process are only for the **production environment**. Please ensure that the environment variables in the `.env` file are configured correctly before running any backups or restores. + +- Make sure to update the `.env` file with the correct values (such as volume names, SSH keys, and server IP) specific to the production setup. \ No newline at end of file diff --git a/config/backup/restore.sh b/config/backup/restore.sh new file mode 100644 index 00000000..eb41a72a --- /dev/null +++ b/config/backup/restore.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Activates the automatic export of variables +set -a + +# Load the .env file +source /.env + +# Deactivates the automatic export of variables +set +a + +# Checks whether the /restore folder exists and creates it if required +if [ ! -d "/restore" ]; then + mkdir -p /restore +fi + +# Restore database +scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/database.tar.gz /restore/ +docker run --rm -v ${COMPOSE_PROJECT_NAME}_db_volume:/volume -v /restore:/backup alpine sh -c "cd /volume && tar -xzf /backup/database.tar.gz" +docker restart ${MYSQL_CONTAINER_NAME} + +# Restore userdata +scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata.tar.gz /restore/ +docker run --rm -v ${COMPOSE_PROJECT_NAME}_userdata_volume:/volume -v /restore:/backup alpine sh -c "cd /volume && tar -xzf /backup/userdata.tar.gz" +docker restart ${LUCEE_CONTAINER_NAME} + +# Restore Lucee image +scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar /restore/ +docker load -i /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar diff --git a/config/example.env b/config/example.env index 8682c6c8..d92e5209 100644 --- a/config/example.env +++ b/config/example.env @@ -1,8 +1,11 @@ ## Project name COMPOSE_PROJECT_NAME=saaster # Must be unique on docker host. -## Lucee settings (default: lucee/lucee:6.0-nginx) -LUCEE_IMAGE=lucee/lucee:6.0-nginx # For the initial setup, please leave it as is, then use your own image name afterward. +## Lucee settings +# Keep the Lucee image name for setup, then replace with your own later. +# Default: lucee/lucee:6.0-nginx +LUCEE_IMAGE=lucee/lucee +LUCEE_IMAGE_VERSION=6.0-nginx LUCEE_CONTAINER_NAME=saaster_lucee # Must be unique on docker host. LUCEE_PORT=8080 # Must be unique on docker host. LUCEE_ADMIN_PASSWORD=defaultpass @@ -22,8 +25,19 @@ FLYWAY_DB_FOLDER=core # core or myapp FLYWAY_MIGRATION_TYPE=migrate # migrate or repair FLYWAY_CONTAINER_NAME=saaster_flyway # Must be unique on docker host. -## Inbucket settings (dev) +## Inbucket settings (development environment) INBUCKET_CONTAINER_NAME=saaster_inbucket # Will be used as the SMTP server in Lucee. INBUCKET_SMTP_PORT=2500 # Must be unique on docker host. In Lucee Admin please set to 2500. INBUCKET_WEB_PORT=9000 # Must be unique on docker host. -INBUCKET_POP3_PORT=1100 # Must be unique on docker host. \ No newline at end of file +INBUCKET_POP3_PORT=1100 # Must be unique on docker host. + + +# Backup settings (production environment) + +# Backup path on the remote server +REMOTE_BACKUP_PATH=/backups + +# Server information for SCP Transfer +SERVER_USER=root +SERVER_IP=xxx.xxx.xxx.xxx +SSH_KEY_PATH=~/.ssh/id_rsa \ No newline at end of file From 6219e678156fe789feda9f841e54e38458789bc7 Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 15:17:25 +0200 Subject: [PATCH 2/9] Change readme --- config/backup/readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/backup/readme.md b/config/backup/readme.md index f0aab81f..e78d97ec 100644 --- a/config/backup/readme.md +++ b/config/backup/readme.md @@ -8,8 +8,6 @@ By utilizing Docker Compose and shell scripts, the backup process is automated t **Structure** -- .env: This file contains environment variables specifically for backup and restoration in the production environment. Variables like volume names, image versions, and SSH credentials are defined here. - - compose-backup.yml: This file defines the container services needed to create backups. Each service performs a backup for the database, user data, or the Lucee image. - backup.sh: A shell script that automates the process of backing up the database, user data, and Lucee image. It uses Docker Compose and secure copying (SCP) to transfer backups to the designated backup server. From 9dc664c0c009b216fa95273286d12c6ed437ee1d Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 15:49:20 +0200 Subject: [PATCH 3/9] Change path of .env --- config/backup/backup.sh | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/config/backup/backup.sh b/config/backup/backup.sh index 40af3eaf..e5930753 100644 --- a/config/backup/backup.sh +++ b/config/backup/backup.sh @@ -4,17 +4,11 @@ set -a # Load the .env file -PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -source "$PROJECT_ROOT/.env" +source ../.env # Deactivates the automatic export of variables set +a -# Checks whether the /backup folder exists and creates it if required -if [ ! -d "/backup" ]; then - mkdir -p /backup -fi - # Backup database docker compose -f compose-backup.yml run db_backup scp -i ${SSH_KEY_PATH} /backup/database.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} From e5322bdb454b5d21342f5487400bc7723f354952 Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 15:50:20 +0200 Subject: [PATCH 4/9] Check the /backup path --- config/backup/backup.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/backup/backup.sh b/config/backup/backup.sh index e5930753..4f76771b 100644 --- a/config/backup/backup.sh +++ b/config/backup/backup.sh @@ -9,6 +9,11 @@ source ../.env # Deactivates the automatic export of variables set +a +# Checks whether the /backup folder exists and creates it if required +if [ ! -d "/backup" ]; then + mkdir -p /backup +fi + # Backup database docker compose -f compose-backup.yml run db_backup scp -i ${SSH_KEY_PATH} /backup/database.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} From 0e20f52836f31b9bd1a561849eaf18ccee720a0a Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 15:53:48 +0200 Subject: [PATCH 5/9] Change the .env path --- config/backup/backup.sh | 2 +- config/backup/restore.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/backup/backup.sh b/config/backup/backup.sh index 4f76771b..f636da44 100644 --- a/config/backup/backup.sh +++ b/config/backup/backup.sh @@ -4,7 +4,7 @@ set -a # Load the .env file -source ../.env +source ../../.env # Deactivates the automatic export of variables set +a diff --git a/config/backup/restore.sh b/config/backup/restore.sh index eb41a72a..cee61469 100644 --- a/config/backup/restore.sh +++ b/config/backup/restore.sh @@ -4,7 +4,7 @@ set -a # Load the .env file -source /.env +source ../../.env # Deactivates the automatic export of variables set +a From ba723441579da22d1fd9f754f50b6c239a6892e5 Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 16:08:13 +0200 Subject: [PATCH 6/9] Test with env path --- config/backup/restore.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config/backup/restore.sh b/config/backup/restore.sh index cee61469..adbeea5d 100644 --- a/config/backup/restore.sh +++ b/config/backup/restore.sh @@ -3,8 +3,14 @@ # Activates the automatic export of variables set -a -# Load the .env file -source ../../.env +# Get the directory of the current script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set the project root (assuming the script is two levels below the project root) +PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" + +# Load the .env file from the project root +source "$PROJECT_ROOT/.env" # Deactivates the automatic export of variables set +a From 0070875bec8c6c93729bad8f563c721465b33d9b Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 16:09:24 +0200 Subject: [PATCH 7/9] Test with env path --- config/backup/backup.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config/backup/backup.sh b/config/backup/backup.sh index f636da44..775b247f 100644 --- a/config/backup/backup.sh +++ b/config/backup/backup.sh @@ -3,8 +3,14 @@ # Activates the automatic export of variables set -a -# Load the .env file -source ../../.env +# Get the directory of the current script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set the project root (assuming the script is two levels below the project root) +PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" + +# Load the .env file from the project root +source "$PROJECT_ROOT/.env" # Deactivates the automatic export of variables set +a From d79172797807421ea557f0b31c622d2f338a36d8 Mon Sep 17 00:00:00 2001 From: ptruessel Date: Mon, 21 Oct 2024 16:21:48 +0200 Subject: [PATCH 8/9] Transferring the .env file --- config/backup/compose-backup.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/backup/compose-backup.yml b/config/backup/compose-backup.yml index 5e3908da..3e9a4fd9 100644 --- a/config/backup/compose-backup.yml +++ b/config/backup/compose-backup.yml @@ -5,6 +5,8 @@ services: - ${COMPOSE_PROJECT_NAME}_db_volume:/volume - /backup:/backup command: tar -czf /backup/database.tar.gz -C /volume . + env_file: + - ../../.env userdata_backup: image: alpine @@ -12,9 +14,13 @@ services: - ${COMPOSE_PROJECT_NAME}_userdata_volume:/volume - /backup:/backup command: tar -czf /backup/userdata.tar.gz -C /volume . + env_file: + - ../../.env lucee_image_backup: image: alpine volumes: - /backup:/backup - command: docker save -o /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} \ No newline at end of file + command: docker save -o /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} + env_file: + - ../../.env \ No newline at end of file From 797aa941ec1ea1fe51b7301fecf51e1a2bd6aa85 Mon Sep 17 00:00:00 2001 From: ptruessel Date: Tue, 22 Oct 2024 14:09:50 +0200 Subject: [PATCH 9/9] Added new backup strategy --- config/backup/backup.sh | 55 +++++++++++------ config/backup/compose-backup.yml | 26 -------- config/backup/readme.md | 80 ++++++++++++++++-------- config/backup/restore.sh | 102 ++++++++++++++++++++++++------- config/example.env | 2 +- 5 files changed, 170 insertions(+), 95 deletions(-) delete mode 100644 config/backup/compose-backup.yml diff --git a/config/backup/backup.sh b/config/backup/backup.sh index 775b247f..085d2087 100644 --- a/config/backup/backup.sh +++ b/config/backup/backup.sh @@ -1,33 +1,48 @@ #!/bin/bash -# Activates the automatic export of variables +# Enable automatic export of variables set -a -# Get the directory of the current script -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Set the project root (assuming the script is two levels below the project root) -PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" - # Load the .env file from the project root -source "$PROJECT_ROOT/.env" +source "$(dirname "$0")/../../.env" -# Deactivates the automatic export of variables -set +a +# Dynamically generate volume names based on the project +DB_VOLUME="${COMPOSE_PROJECT_NAME}_db_volume" +USERDATA_VOLUME="${COMPOSE_PROJECT_NAME}_userdata_volume" -# Checks whether the /backup folder exists and creates it if required +# Date format for versioning (e.g., 20241022_2300) +TIMESTAMP=$(date +"%Y%m%d_%H%M") + +# Check if the /backup folder exists and create it if necessary if [ ! -d "/backup" ]; then mkdir -p /backup fi -# Backup database -docker compose -f compose-backup.yml run db_backup -scp -i ${SSH_KEY_PATH} /backup/database.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} +# Create remote directories if they don't exist +ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "mkdir -p ${REMOTE_BACKUP_PATH}/db ${REMOTE_BACKUP_PATH}/userdata ${REMOTE_BACKUP_PATH}/lucee" + +# Backup database volume and store in the remote db directory +docker run --rm -v ${DB_VOLUME}:/volume -v /backup:/backup alpine sh -c "tar -czf /backup/database_${TIMESTAMP}.tar.gz -C /volume ." +scp -i ${SSH_KEY_PATH} /backup/database_${TIMESTAMP}.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/db/ + +# Backup userdata volume and store in the remote userdata directory +docker run --rm -v ${USERDATA_VOLUME}:/volume -v /backup:/backup alpine sh -c "tar -czf /backup/userdata_${TIMESTAMP}.tar.gz -C /volume ." +scp -i ${SSH_KEY_PATH} /backup/userdata_${TIMESTAMP}.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata/ -# Backup userdata -docker compose -f compose-backup.yml run userdata_backup -scp -i ${SSH_KEY_PATH} /backup/userdata.tar.gz ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} +# Backup Lucee image and store in the remote lucee directory +docker save -o /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}_${TIMESTAMP}.tar ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} +scp -i ${SSH_KEY_PATH} /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}_${TIMESTAMP}.tar ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/lucee/ -# Backup Lucee image -docker compose -f compose-backup.yml run lucee_image_backup -scp -i ${SSH_KEY_PATH} /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH} \ No newline at end of file +# Rotate backups: Keep only the latest 30 backups per type + +# For database backups +ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "cd ${REMOTE_BACKUP_PATH}/db && ls -tp | grep -v '/$' | tail -n +31 | xargs -I {} rm -- {}" + +# For userdata backups +ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "cd ${REMOTE_BACKUP_PATH}/userdata && ls -tp | grep -v '/$' | tail -n +31 | xargs -I {} rm -- {}" + +# For Lucee image backups +ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "cd ${REMOTE_BACKUP_PATH}/lucee && ls -tp | grep -v '/$' | tail -n +31 | xargs -I {} rm -- {}" + +# Disable automatic export of variables +set +a diff --git a/config/backup/compose-backup.yml b/config/backup/compose-backup.yml deleted file mode 100644 index 3e9a4fd9..00000000 --- a/config/backup/compose-backup.yml +++ /dev/null @@ -1,26 +0,0 @@ -services: - db_backup: - image: alpine - volumes: - - ${COMPOSE_PROJECT_NAME}_db_volume:/volume - - /backup:/backup - command: tar -czf /backup/database.tar.gz -C /volume . - env_file: - - ../../.env - - userdata_backup: - image: alpine - volumes: - - ${COMPOSE_PROJECT_NAME}_userdata_volume:/volume - - /backup:/backup - command: tar -czf /backup/userdata.tar.gz -C /volume . - env_file: - - ../../.env - - lucee_image_backup: - image: alpine - volumes: - - /backup:/backup - command: docker save -o /backup/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar ${LUCEE_IMAGE}:${LUCEE_IMAGE_VERSION} - env_file: - - ../../.env \ No newline at end of file diff --git a/config/backup/readme.md b/config/backup/readme.md index e78d97ec..fd6089ef 100644 --- a/config/backup/readme.md +++ b/config/backup/readme.md @@ -1,46 +1,74 @@ -***Backup for the Production Environment*** + +# Backup for the Production and Staging Environments **Purpose** -This directory contains the configurations and scripts for backing up and restoring the database, user data, and the Lucee image. These backups are intended only for the production environment. +This directory contains the necessary configurations and scripts for backing up and restoring the **database**, **user data**, and the **Lucee image** in the **production** and **staging** environments. The backup and restore processes are automated using Docker and shell scripts to ensure consistency, reliability, and minimal manual intervention. -By utilizing Docker Compose and shell scripts, the backup process is automated to ensure consistent and reliable data backups with minimal manual intervention. +Note: These scripts are not intended for use in the **development** environment. -**Structure** -- compose-backup.yml: This file defines the container services needed to create backups. Each service performs a backup for the database, user data, or the Lucee image. +## **Structure** -- backup.sh: A shell script that automates the process of backing up the database, user data, and Lucee image. It uses Docker Compose and secure copying (SCP) to transfer backups to the designated backup server. +- **backup.sh**: A shell script that automates the process of creating backups for the **database volume**, **user data volume**, and **Lucee image**. Each backup is timestamped to ensure that multiple versions can be maintained. The script also uses `scp` to transfer the backups securely to a remote server. -- restore.sh: A shell script that automates the process of restoring the database, user data, and Lucee image. It retrieves backups from the backup server and restores them to the appropriate volumes. +- **restore.sh**: A shell script that automates the process of restoring backups from the remote server. It retrieves the backups for the **database**, **user data**, and **Lucee image**, and restores them to the appropriate Docker volumes. -**Usage** +- **.env**: Contains environment variables required for the backup and restore processes, such as volume names, SSH key, server IP, and remote paths. The backup does not have its own `.env` file; instead, it uses the `.env` file from the main project. -*Backup* +## **Usage** -To create a backup, run the following command from this directory: +### **Backup** - sh backup.sh +To create a backup of the **database**, **user data**, and **Lucee image**, follow these steps: -This will: -1. Backup the database volume. -2. Backup the user data volume. -3. Backup the Lucee image. -4. Securely transfer all backups to the remote backup server. +1. Ensure that the `.env` file is correctly configured with your **production** or **staging** environment settings (e.g., volume names, remote server path, SSH keys, and server IP). -*Restore* -To restore from a backup, run the following command: +2. Navigate to the `config/backup/` directory: + `cd config/backup/` - sh restore.sh +3. Run the backup script: +`bash backup.sh` This will: -1. Retrieve the latest backups from the remote backup server. -2. Restore the database volume. -3. Restore the user data volume. -4. Load the Lucee image into Docker. +- Backup the **database volume**. +- Backup the **user data volume**. +- Backup the **Lucee image**. +- Securely transfer all backups to the remote backup server. + +Each backup will be **timestamped** in the format `YYYYMMDD_HHMM`, ensuring you can differentiate between multiple backup versions. + +### **Restore** + +To restore from a backup, first navigate to the `config/backup/` directory: +`cd config/backup/` + +Then, if you run the restore script without any parameters: +`bash restore.sh` + +It will display a list of available options, such as: +Usage: restore.sh [--db [TIMESTAMP]] [--userdata [TIMESTAMP]] [--lucee-image [TIMESTAMP]] [--list] + +To perform a restore, you need to specify which backup you want to restore by using one of the following options: + - To restore the **latest** backup for the **database**: + `bash restore.sh --db` + + - To restore a **specific** database backup by **timestamp**: + `bash restore.sh --db 20241019_2300` + +- To list all available backups on the remote server: + `bash restore.sh --list` + + +## **Automating Backups** + +To automate the backup process, you can set up a **cron job** to run the backup script at regular intervals (e.g., daily). For example, to run the backup every night at midnight, add the following entry to your crontab: +`0 0 * * * /path/to/your/project/config/backup/backup.sh` + -**Notes** -- The backups created by this process are only for the **production environment**. Please ensure that the environment variables in the `.env` file are configured correctly before running any backups or restores. +## **Notes** -- Make sure to update the `.env` file with the correct values (such as volume names, SSH keys, and server IP) specific to the production setup. \ No newline at end of file +- These backups are intended for the **production** and **staging** environments. Ensure that the environment variables in the `.env` file are correctly configured before running any backups or restores. +- The backup script automatically **rotates** backups, keeping only the **latest 30 backups** per backup type (database, user data, Lucee image) by removing older backups on the remote server. +- Always ensure that your **SSH keys** and **server information** are secure, as they are used for transferring backups between the production or staging environment and the remote server. diff --git a/config/backup/restore.sh b/config/backup/restore.sh index adbeea5d..2018c52b 100644 --- a/config/backup/restore.sh +++ b/config/backup/restore.sh @@ -1,35 +1,93 @@ #!/bin/bash -# Activates the automatic export of variables +# Enable automatic export of variables set -a -# Get the directory of the current script -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Set the project root (assuming the script is two levels below the project root) -PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" - # Load the .env file from the project root -source "$PROJECT_ROOT/.env" +source "$(dirname "$0")/../../.env" -# Deactivates the automatic export of variables -set +a +# Dynamically generate volume names based on the project +DB_VOLUME="${COMPOSE_PROJECT_NAME}_db_volume" +USERDATA_VOLUME="${COMPOSE_PROJECT_NAME}_userdata_volume" -# Checks whether the /restore folder exists and creates it if required +# Check if the /restore folder exists and create it if necessary if [ ! -d "/restore" ]; then mkdir -p /restore fi -# Restore database -scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/database.tar.gz /restore/ -docker run --rm -v ${COMPOSE_PROJECT_NAME}_db_volume:/volume -v /restore:/backup alpine sh -c "cd /volume && tar -xzf /backup/database.tar.gz" -docker restart ${MYSQL_CONTAINER_NAME} +# Functions for the various restore processes + +restore_db() { + if [ -z "$1" ]; then + echo "Restoring the latest database backup..." + # Get the latest database backup + LATEST_DB_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/db | head -n 1") + else + echo "Restoring database backup from $1..." + LATEST_DB_BACKUP="database_$1.tar.gz" + fi + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/db/${LATEST_DB_BACKUP} /restore/database.tar.gz + docker run --rm -v ${DB_VOLUME}:/volume -v /restore:/restore alpine sh -c "tar -xzf /restore/database.tar.gz -C /volume" + docker restart ${MYSQL_CONTAINER_NAME} +} + +restore_userdata() { + if [ -z "$1" ]; then + echo "Restoring the latest userdata backup..." + # Get the latest userdata backup + LATEST_USERDATA_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/userdata | head -n 1") + else + echo "Restoring userdata backup from $1..." + LATEST_USERDATA_BACKUP="userdata_$1.tar.gz" + fi + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata/${LATEST_USERDATA_BACKUP} /restore/userdata.tar.gz + docker run --rm -v ${USERDATA_VOLUME}:/volume -v /restore:/restore alpine sh -c "tar -xzf /restore/userdata.tar.gz -C /volume" + docker restart ${LUCEE_CONTAINER_NAME} +} -# Restore userdata -scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata.tar.gz /restore/ -docker run --rm -v ${COMPOSE_PROJECT_NAME}_userdata_volume:/volume -v /restore:/backup alpine sh -c "cd /volume && tar -xzf /backup/userdata.tar.gz" -docker restart ${LUCEE_CONTAINER_NAME} +restore_lucee_image() { + if [ -z "$1" ]; then + echo "Restoring the latest Lucee image backup..." + # Get the latest Lucee image backup + LATEST_LUCEE_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/lucee | head -n 1") + else + echo "Restoring Lucee image backup from $1..." + LATEST_LUCEE_BACKUP="image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}_$1.tar" + fi + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/lucee/${LATEST_LUCEE_BACKUP} /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar + docker load -i /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar +} -# Restore Lucee image -scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar /restore/ -docker load -i /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar +list_backups() { + echo "Available backups on remote server:" + echo "Database backups:" + ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/db" + echo "" + echo "Userdata backups:" + ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/userdata" + echo "" + echo "Lucee image backups:" + ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/lucee" + echo "" +} + +# Show help if no options have been specified +if [ $# -eq 0 ]; then + echo "Usage: $0 [--db [TIMESTAMP]] [--userdata [TIMESTAMP]] [--lucee-image [TIMESTAMP]] [--list]" + exit 1 +fi + +# Process the specified options +while [[ "$#" -gt 0 ]]; do + case $1 in + --db) restore_db "$2"; shift ;; + --userdata) restore_userdata "$2"; shift ;; + --lucee-image) restore_lucee_image "$2"; shift ;; + --list) list_backups; exit 0 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac + shift +done + +# Disable automatic export of variables +set +a diff --git a/config/example.env b/config/example.env index d92e5209..47b9efd9 100644 --- a/config/example.env +++ b/config/example.env @@ -32,7 +32,7 @@ INBUCKET_WEB_PORT=9000 # Must be unique on docker host. INBUCKET_POP3_PORT=1100 # Must be unique on docker host. -# Backup settings (production environment) +## Backup settings # Backup path on the remote server REMOTE_BACKUP_PATH=/backups