diff --git a/abra.sh b/abra.sh index 2f68918..c137b75 100644 --- a/abra.sh +++ b/abra.sh @@ -1,4 +1,5 @@ export LOOMIO_ENTRYPOINT_VERSION=v8 +export PG_BACKUP_VERSION=v1 # cannot be integrated into entrypoint.sh as it requires the operator to create a user first function make_last_user_admin() diff --git a/compose.yml b/compose.yml index e5dd138..d523e0f 100644 --- a/compose.yml +++ b/compose.yml @@ -115,12 +115,14 @@ services: PGDATA: /pgdata deploy: labels: - backupbot.backup: "${ENABLE_BACKUPS:-true}" - backupbot.backup.pre-hook: sh -c 'pg_dump -U "$$POSTGRES_USER" -Fc "$$POSTGRES_DB" | gzip > "/postgres.dump.gz"' - backupbot.backup.path: "/postgres.dump.gz" - backupbot.backup.post-hook: "rm -f /postgres.dump.gz" - backupbot.restore: "true" - backupbot.restore.post-hook: sh -c 'gzip -d /postgres.dump.gz && pg_restore --clean -U "$$POSTGRES_USER" --dbname="$$POSTGRES_DB" < /postgres.dump && rm -f /postgres.dump' + backupbot.backup: ${ENABLE_BACKUPS:-true} + backupbot.backup.volumes.pgdata.path: "backup.sql" + backupbot.backup.pre-hook: "/pg_backup.sh backup" + backupbot.restore.post-hook: '/pg_backup.sh restore' + configs: + - source: pg_backup + target: /pg_backup.sh + mode: 0555 redis: image: redis:8.0 networks: @@ -203,6 +205,9 @@ configs: entrypoint: name: ${STACK_NAME}_entrypoint_${LOOMIO_ENTRYPOINT_VERSION} file: entrypoint.sh + pg_backup: + name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION} + file: pg_backup.sh secrets: devise_secret: diff --git a/pg_backup.sh b/pg_backup.sh new file mode 100755 index 0000000..77b682f --- /dev/null +++ b/pg_backup.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e + +BACKUP_PATH="/pgdata" +LATEST_BACKUP_FILE="${BACKUP_PATH}/backup.sql" + +function backup { + FILE_WITH_DATE="${BACKUP_PATH}/backup_$(date +%F).sql" + + if [ -f "$POSTGRES_PASSWORD_FILE" ]; then + export PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE") + fi + + echo "Creating backup at ${FILE_WITH_DATE}..." + pg_dump -U "${POSTGRES_USER:-postgres}" "${POSTGRES_DB:-postgres}" > "${FILE_WITH_DATE}" + + echo "Copying to ${LATEST_BACKUP_FILE}..." + cp -f "${FILE_WITH_DATE}" "${LATEST_BACKUP_FILE}" + + echo "Backup done. You will find it at ${LATEST_BACKUP_FILE}" +} + +function restore { + echo "Restoring database from ${LATEST_BACKUP_FILE}..." + + cd ${BACKUP_PATH} + + function restore_config { + echo "Restoring original pg_hba.conf configuration..." + cat pg_hba.conf.bak > pg_hba.conf + su postgres -c 'pg_ctl reload' + } + + # Don't allow any other connections than local + echo "Setting up temporary pg_hba.conf to only allow local connections..." + cp pg_hba.conf pg_hba.conf.bak + echo "local all all trust" > pg_hba.conf + su postgres -c 'pg_ctl reload' + trap restore_config EXIT INT TERM + + # Recreate Database + echo "Dropping existing database ${POSTGRES_DB:-postgres}..." + psql -U "${POSTGRES_USER:-postgres}" -d postgres -c "DROP DATABASE \"${POSTGRES_DB:-postgres}\" WITH (FORCE);" + + echo "Creating fresh database ${POSTGRES_DB:-postgres}..." + createdb -U "${POSTGRES_USER:-postgres}" "${POSTGRES_DB:-postgres}" + + echo "Restoring data from ${LATEST_BACKUP_FILE}..." + psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-postgres}" -1 -f "${LATEST_BACKUP_FILE}" + + trap - EXIT INT TERM + restore_config + + echo "Database restore completed successfully." +} + +# Execute the function passed as argument +case "$1" in + backup) + backup + ;; + restore) + restore + ;; + *) + echo "Usage: $0 {backup|restore}" + exit 1 + ;; +esac \ No newline at end of file