backup scripts

This commit is contained in:
Mayel de Borniol 2025-04-21 15:17:05 +01:00
parent d52472eb3b
commit 853832355a
4 changed files with 148 additions and 52 deletions

View File

@ -1,4 +1,4 @@
export APP_ENTRYPOINT_VERSION=v1 export APP_ENTRYPOINT_VERSION=v1
export PG_BACKUP_VERSION=v2 export PG_BACKUP_VERSION=v4
export MEILI_BACKUP_VERSION=v2 export MEILI_BACKUP_VERSION=v4

View File

@ -9,7 +9,7 @@ services:
- SEARCH_MEILI_INSTANCE=http://${STACK_NAME}_search:7700 - SEARCH_MEILI_INSTANCE=http://${STACK_NAME}_search:7700
search: search:
image: getmeili/meilisearch:v1.11 # TODO: upgrade to 1.14 image: getmeili/meilisearch:v1.11 # WIP: upgrade from v1.11 to 1.14
secrets: secrets:
- meili_master_key - meili_master_key
volumes: volumes:

137
meili_backup.sh Normal file → Executable file
View File

@ -1,44 +1,107 @@
#!/bin/bash #!/bin/sh
set -e set -e
BACKUP_FILE='/var/lib/postgresql/data/backup.sql' backup() {
SECRET=$(cat /run/secrets/meili_master_key)
function backup { # Create dump
export SECRET=$(cat /run/secrets/meili_master_key) echo "Creating new Meilisearch dump..."
// pre-hook command for compose.meilisearch.yml RESPONSE=$(curl -s -X POST 'http://localhost:7700/dumps' -H "Authorization: Bearer $SECRET")
TASK_UID=$(curl -s -X POST 'http://localhost:7700/dumps' -H 'Authorization: Bearer $SECRET' | grep -o '\"uid\":[0-9]*' | cut -d':' -f2) && \ echo "Response: $RESPONSE"
echo "Waiting for dump creation (task $TASK_UID)..." && \
MAX_ATTEMPTS=600 && \ # More robust extraction of task UID
ATTEMPT=0 && \ TASK_UID=$(echo "$RESPONSE" | sed -n 's/.*"taskUid":\([0-9]*\).*/\1/p')
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do \
TASK_STATUS=$(curl -s "http://localhost:7700/tasks/$TASK_UID" -H "Authorization: Bearer $SECRET" | grep -o '\"status\":\"[^\"]*\"' | cut -d':' -f2 | tr -d '\"'); \ if [ -z "$TASK_UID" ]; then
if [ "$TASK_STATUS" = "succeeded" ]; then \ echo "Failed to extract task UID from response. Aborting."
echo "Dump creation succeeded" && \ exit 1
break; \ fi
elif [ "$TASK_STATUS" = "enqueued" ] || [ "$TASK_STATUS" = "processing" ]; then \
echo "Dump creation in progress... ($TASK_STATUS)" && \ echo "Waiting for dump creation (task $TASK_UID)..."
ATTEMPT=$((ATTEMPT+1)) && \
sleep 2; \ MAX_ATTEMPTS=600
else \ ATTEMPT=0
echo "Dump creation in unexpected state: $TASK_STATUS" && \ while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
exit 1; \ RESPONSE=$(curl -s "http://localhost:7700/tasks/$TASK_UID" -H "Authorization: Bearer $SECRET")
fi; \ echo "Task status response: $RESPONSE"
done && \
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then \ TASK_STATUS=$(echo "$RESPONSE" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p')
echo "Timed out waiting for dump creation" && \
exit 1; \ if [ -z "$TASK_STATUS" ]; then
fi && \ echo "Failed to extract task status. Retrying..."
DUMP_UID=$(curl -s "http://localhost:7700/tasks/$TASK_UID" -H "Authorization: Bearer $SECRET" | grep -o '\"dumpUid\":\"[^\"]*\"' | cut -d':' -f2 | tr -d '\"') && \ ATTEMPT=$((ATTEMPT+1))
echo "Using dump $DUMP_UID" && \ sleep 5
cp -f "/meili_dumps/$DUMP_UID.dump" "/meili_dumps/meilisearch_latest.dump" && \ continue
echo "Dump created and copied successfully" fi
echo "Current status: $TASK_STATUS"
if [ "$TASK_STATUS" = "succeeded" ]; then
echo "Dump creation succeeded"
break
elif [ "$TASK_STATUS" = "enqueued" ] || [ "$TASK_STATUS" = "processing" ]; then
echo "Dump creation in progress... ($TASK_STATUS)"
ATTEMPT=$((ATTEMPT+1))
sleep 5
else
echo "Dump creation in unexpected state: $TASK_STATUS. Giving up."
exit 1
fi
done
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "Timed out waiting for dump creation"
exit 1
fi
# Extract dump UID more reliably
DUMP_UID=$(echo "$RESPONSE" | sed -n 's/.*"dumpUid":"\([^"]*\)".*/\1/p')
if [ -z "$DUMP_UID" ]; then
echo "Failed to extract dump UID. Aborting."
exit 1
fi
echo "Using dump $DUMP_UID"
# Check if file exists before copying
if [ ! -f "/meili_dumps/$DUMP_UID.dump" ]; then
echo "Dump file /meili_dumps/$DUMP_UID.dump not found!"
ls -la /meili_dumps/
exit 1
fi
cp -f "/meili_dumps/$DUMP_UID.dump" "/meili_dumps/meilisearch_latest.dump"
echo "Dump created and copied successfully. You can find it at /meili_dumps/meilisearch_latest.dump"
} }
function restore { restore() {
echo 'Restarting Meilisearch with imported dump, may take a while to become available...' echo 'Restarting Meilisearch with imported dump, may take a while to become available...'
pkill meilisearch
MEILI_NO_ANALYTICS=true /bin/meilisearch --import-dump /meili_dumps/meilisearch_latest.dump & # Check if dump file exists
if [ ! -f "/meili_dumps/meilisearch_latest.dump" ]; then
echo "Error: Dump file not found at /meili_dumps/meilisearch_latest.dump"
exit 1
fi
pkill meilisearch || echo "No Meilisearch process found to kill"
echo "Starting Meilisearch with import dump option..."
MEILI_NO_ANALYTICS=true /bin/meilisearch --import-dump /meili_dumps/meilisearch_latest.dump &
echo "Meilisearch restore process initiated..."
} }
$@ # Handle command line argument
case "$1" in
backup)
backup
;;
restore)
restore
;;
*)
echo "Usage: $0 {backup|restore}"
exit 1
;;
esac

57
pg_backup.sh Normal file → Executable file
View File

@ -2,36 +2,69 @@
set -e set -e
BACKUP_PATH='/var/lib/postgresql/data' BACKUP_PATH="/var/lib/postgresql/data"
LATEST_BACKUP_FILE='$BACKUP_PATH/backup.sql' LATEST_BACKUP_FILE="${BACKUP_PATH}/backup.sql"
function backup { function backup {
export FILE_WITH_DATE='$BACKUP_PATH/backup_`date +%F`.sql' FILE_WITH_DATE="${BACKUP_PATH}/backup_$(date +%F).sql"
export PGPASSWORD=$(cat $POSTGRES_PASSWORD_FILE)
pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > $FILE_WITH_DATE if [ -f "$POSTGRES_PASSWORD_FILE" ]; then
cp -f $FILE_WITH_DATE $LATEST_BACKUP_FILE 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 { function restore {
echo "Restoring database from ${LATEST_BACKUP_FILE}..."
cd /var/lib/postgresql/data/ cd /var/lib/postgresql/data/
restore_config(){
# Restore allowed connections function restore_config {
echo "Restoring original pg_hba.conf configuration..."
cat pg_hba.conf.bak > pg_hba.conf cat pg_hba.conf.bak > pg_hba.conf
su postgres -c 'pg_ctl reload' su postgres -c 'pg_ctl reload'
} }
# Don't allow any other connections than local # 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 cp pg_hba.conf pg_hba.conf.bak
echo "local all all trust" > pg_hba.conf echo "local all all trust" > pg_hba.conf
su postgres -c 'pg_ctl reload' su postgres -c 'pg_ctl reload'
trap restore_config EXIT INT TERM trap restore_config EXIT INT TERM
# Recreate Database # Recreate Database
psql -U ${POSTGRES_USER} -d postgres -c "DROP DATABASE ${POSTGRES_DB} WITH (FORCE);" echo "Dropping existing database ${POSTGRES_DB:-postgres}..."
createdb -U ${POSTGRES_USER} ${POSTGRES_DB} psql -U "${POSTGRES_USER:-postgres}" -d postgres -c "DROP DATABASE \"${POSTGRES_DB:-postgres}\" WITH (FORCE);"
psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -1 -f $LATEST_BACKUP_FILE
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 trap - EXIT INT TERM
restore_config 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