fix(deploy): repair backup directory permissions
CI and Deploy / test (push) Successful in 2m24s
CI and Deploy / deploy (push) Successful in 2m14s

This commit is contained in:
cesnimda
2026-07-30 21:42:51 +02:00
parent 56fed05d70
commit f8a7cf5205
2 changed files with 18 additions and 7 deletions
+1 -1
View File
@@ -147,7 +147,7 @@ means "stop and tell me".
`deploy/deploy.sh` takes a backup **before** it builds, stops or replaces anything, and **aborts the `deploy/deploy.sh` takes a backup **before** it builds, stops or replaces anything, and **aborts the
deploy if the backup fails**. Nothing else in the deploy runs without a restore point. deploy if the backup fails**. Nothing else in the deploy runs without a restore point.
- **Location:** `/opt/job-tracker/backups` — override with `BACKUP_DIR`. - **Location:** `/opt/job-tracker/backups` — override with `BACKUP_DIR`. If an earlier root-run deploy owns the directory, the deploy script repairs its ownership through Docker before writing.
- **Selection:** driven solely by `DATABASE_PROVIDER`, which must be set. - **Selection:** driven solely by `DATABASE_PROVIDER`, which must be set.
- `mariadb` / `mysql` → SQL dump, `jobtracker-<database>-<UTC timestamp>.sql.gz`, e.g. - `mariadb` / `mysql` → SQL dump, `jobtracker-<database>-<UTC timestamp>.sql.gz`, e.g.
`jobtracker-jobtracker-20260719T153759Z.sql.gz` `jobtracker-jobtracker-20260719T153759Z.sql.gz`
+17 -6
View File
@@ -161,6 +161,15 @@ backup_database() {
local stamp local stamp
stamp="$(date -u +%Y%m%dT%H%M%SZ)" stamp="$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$BACKUP_DIR" mkdir -p "$BACKUP_DIR"
if [ ! -w "$BACKUP_DIR" ]; then
echo "Backup directory ${BACKUP_DIR} is not writable; repairing ownership via Docker."
docker run --rm -v "$BACKUP_DIR":/backup mariadb:11 \
chown "$(id -u):$(id -g)" /backup
fi
if [ ! -w "$BACKUP_DIR" ]; then
echo "Backup directory ${BACKUP_DIR} is still not writable. Aborting deploy."
return 1
fi
if [ "$provider" = "sqlite" ]; then if [ "$provider" = "sqlite" ]; then
# SQLite lives in the jobtracker_data volume. Tar it from a throwaway container # SQLite lives in the jobtracker_data volume. Tar it from a throwaway container
@@ -219,33 +228,35 @@ backup_database() {
# The password goes via MYSQL_PWD, never on the command line, so it cannot leak # The password goes via MYSQL_PWD, never on the command line, so it cannot leak
# into the process list or the deploy log. # into the process list or the deploy log.
local dump_status=0 local dump_status=0 error_file
error_file="$(mktemp "${TMPDIR:-/tmp}/jobtracker-backup.XXXXXX.err")"
if command -v mariadb-dump >/dev/null 2>&1; then if command -v mariadb-dump >/dev/null 2>&1; then
MYSQL_PWD="$db_pass" mariadb-dump \ MYSQL_PWD="$db_pass" mariadb-dump \
--host="$db_host" --port="$db_port" --user="$db_user" \ --host="$db_host" --port="$db_port" --user="$db_user" \
--single-transaction --routines --events --quick \ --single-transaction --routines --events --quick \
"$db_name" 2>/tmp/jobtracker-backup.err | gzip -c > "$target" || dump_status=$? "$db_name" 2>"$error_file" | gzip -c > "$target" || dump_status=$?
elif command -v mysqldump >/dev/null 2>&1; then elif command -v mysqldump >/dev/null 2>&1; then
MYSQL_PWD="$db_pass" mysqldump \ MYSQL_PWD="$db_pass" mysqldump \
--host="$db_host" --port="$db_port" --user="$db_user" \ --host="$db_host" --port="$db_port" --user="$db_user" \
--single-transaction --routines --events --quick \ --single-transaction --routines --events --quick \
"$db_name" 2>/tmp/jobtracker-backup.err | gzip -c > "$target" || dump_status=$? "$db_name" 2>"$error_file" | gzip -c > "$target" || dump_status=$?
else else
# No client on the host: run one in a container. --network host so the same # No client on the host: run one in a container. --network host so the same
# host/port from the connection string resolves identically. # host/port from the connection string resolves identically.
docker run --rm --network host -e MYSQL_PWD="$db_pass" mariadb:11 \ docker run --rm --network host -e MYSQL_PWD="$db_pass" mariadb:11 \
mariadb-dump --host="$db_host" --port="$db_port" --user="$db_user" \ mariadb-dump --host="$db_host" --port="$db_port" --user="$db_user" \
--single-transaction --routines --events --quick \ --single-transaction --routines --events --quick \
"$db_name" 2>/tmp/jobtracker-backup.err | gzip -c > "$target" || dump_status=$? "$db_name" 2>"$error_file" | gzip -c > "$target" || dump_status=$?
fi fi
if [ "$dump_status" -ne 0 ]; then if [ "$dump_status" -ne 0 ]; then
echo "Database dump FAILED (exit ${dump_status}). Aborting deploy." echo "Database dump FAILED (exit ${dump_status}). Aborting deploy."
sed -e 's/password=[^ ]*/password=***/gI' /tmp/jobtracker-backup.err >&2 || true sed -e 's/password=[^ ]*/password=***/gI' "$error_file" >&2 || true
rm -f "$target" rm -f "$error_file" "$target"
return 1 return 1
fi fi
rm -f "$error_file"
verify_sql_backup "$target" verify_sql_backup "$target"
} }