apps/ntfy/backup.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
app_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$app_dir"
env_file="${FOSSARY_ENV_FILE:-$app_dir/.env}"
[[ -f "$env_file" ]] || { echo "Missing $env_file" >&2; exit 2; }
set -a
# shellcheck disable=SC1091
. "$env_file"
set +a
compose=(docker compose --project-name "${COMPOSE_PROJECT_NAME:-ntfy}" --env-file "$env_file" --file "$app_dir/compose.yaml")
backup_dir="${NTFY_BACKUP_DIR:-$app_dir/backups}"
mkdir -p "$backup_dir"
backup_dir="$(cd "$backup_dir" && pwd)"
staging="$(mktemp -d)"
restart_containers=()
cleanup() {
status=$?
trap - EXIT INT TERM
for container in "${restart_containers[@]}"; do docker start "$container" >/dev/null || true; done
rm -rf "$staging"
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT TERM
container="$("${compose[@]}" ps --all --quiet ntfy)"
[[ -n "$container" ]] || { echo 'Start the recipe before backup' >&2; exit 1; }
volume="$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/var/cache/ntfy"}}{{.Name}}{{end}}{{end}}' "$container")"
[[ -n "$volume" ]] || { echo 'Expected a named data volume' >&2; exit 1; }
if [[ "$(docker inspect --format '{{.State.Running}}' "$container")" == true ]]; then restart_containers+=("$container"); fi
"${compose[@]}" stop ntfy
docker run --rm -v "$volume:/data:ro" -v "$staging:/backup" alpine:3.22 tar -C /data -czf /backup/data.tar.gz .
cp -- "$env_file" "$staging/configuration.env"
cp -- "$app_dir/compose.yaml" "$staging/compose.yaml"
archive="$backup_dir/ntfy-$(date -u +%Y%m%dT%H%M%S.%NZ).tar"
tar -C "$staging" -cf "$archive" data.tar.gz configuration.env compose.yaml
echo "Backup created: $archive"
echo 'The archive contains cached messages, attachments, accounts, ACLs, tokens, and bootstrap hashes. Encrypt it and copy it off-server.'