#!/bin/sh set -eu compose_file="${COMPOSE_FILE:-compose.yaml}" data_path="${MEMRELAY_DATA_PATH:-./data}" output_dir="${BACKUP_DIR:-./backups}" timestamp="$(date -u +%Y%m%dT%H%M%SZ)" archive="$output_dir/memrelay-$timestamp.tar.gz" manifest="$output_dir/memrelay-$timestamp.json" mkdir -p "$output_dir" data_path="$(cd "$data_path" && pwd -P)" output_dir="$(cd "$output_dir" && pwd -P)" archive="$output_dir/memrelay-$timestamp.tar.gz" manifest="$output_dir/memrelay-$timestamp.json" images="$(docker compose -f "$compose_file" config --images | sort | paste -sd ',' -)" docker compose -f "$compose_file" exec -T memrelay python -c \ "import os, sqlite3; p=os.path.join(os.environ.get('MEMRELAY_DATA_DIR', '/data/memrelay'), 'db', 'memrelay.sqlite3'); c=sqlite3.connect(p); print(c.execute('PRAGMA wal_checkpoint(TRUNCATE)').fetchone()); c.close()" docker compose -f "$compose_file" stop trap 'docker compose -f "$compose_file" start' EXIT INT TERM if ! docker run --rm --user "$(id -u):$(id -g)" \ --mount "type=bind,source=$data_path,target=/source,readonly" \ --mount "type=bind,source=$output_dir,target=/backup" \ alpine:3.22 tar -czf "/backup/$(basename "$archive")" -C /source .; then rm -f "$archive" "$archive.sha256" "$manifest" exit 1 fi hash="$(sha256sum "$archive" | awk '{print $1}')" printf '%s %s\n' "$hash" "$(basename "$archive")" > "$archive.sha256" printf '{"product":"MemRelay","created_at":"%s","archive":"%s","sha256":"%s","compose_file":"%s","images":"%s"}\n' \ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$(basename "$archive")" "$hash" "$compose_file" "$images" > "$manifest" echo "Backup created: $archive"