616b20f285
- init-r2-repository.sh: inicializa repositorio Kopia en R2 - run-backup.sh: ejecuta backup de rutas definidas en backup-paths.txt - pre-backup-dumps.sh: vuelca bases de datos (Postgres, MariaDB) antes del backup - kopia-common.sh: funciones compartidas de autenticación y configuración - restore-smoke-test.sh: test de restauración para verificar integridad - backup-paths.txt / excludes.txt: rutas y exclusiones del backup - systemd/: unidades kopia-server, kopia-docker-backup (service + timer) - traefik-kopia.yml: exposición del servidor Kopia vía Traefik - env.example: plantilla de variables (credenciales R2, contraseña repo) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
88 lines
2.5 KiB
Bash
Executable File
88 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
# shellcheck disable=SC1091
|
|
source "$SCRIPT_DIR/kopia-common.sh"
|
|
|
|
require_cmd docker
|
|
ensure_runtime_dirs
|
|
|
|
DUMP_DIR="$BACKUP_STAGING_DIR/dumps"
|
|
RUN_DIR="$DUMP_DIR/latest"
|
|
mkdir -p "$RUN_DIR"
|
|
find "$RUN_DIR" -type f -name '*.dump' -delete
|
|
find "$RUN_DIR" -type f -name '*.sql.gz' -delete
|
|
|
|
container_running() {
|
|
[[ "$(docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null || true)" == "true" ]]
|
|
}
|
|
|
|
container_env() {
|
|
local container="$1"
|
|
local key="$2"
|
|
docker exec "$container" sh -lc "printenv $key 2>/dev/null || true" | tr -d '\r'
|
|
}
|
|
|
|
dump_postgres() {
|
|
local container="$1"
|
|
local fallback_user="$2"
|
|
local fallback_db="$3"
|
|
|
|
if ! container_running "$container"; then
|
|
log "Skip PostgreSQL dump for $container: container not running"
|
|
return 0
|
|
fi
|
|
|
|
local user db out
|
|
user="$(container_env "$container" POSTGRES_USER)"
|
|
db="$(container_env "$container" POSTGRES_DB)"
|
|
user="${user:-$fallback_user}"
|
|
db="${db:-$fallback_db}"
|
|
out="$RUN_DIR/${container}.dump"
|
|
|
|
log "Dumping PostgreSQL $container/$db"
|
|
docker exec "$container" pg_dump -U "$user" -d "$db" -Fc > "$out"
|
|
}
|
|
|
|
dump_mariadb() {
|
|
local container="$1"
|
|
|
|
if ! container_running "$container"; then
|
|
log "Skip MariaDB dump for $container: container not running"
|
|
return 0
|
|
fi
|
|
|
|
local out
|
|
out="$RUN_DIR/${container}.sql.gz"
|
|
|
|
log "Dumping MariaDB $container"
|
|
docker exec "$container" sh -lc '
|
|
set -eu
|
|
db="${MYSQL_DATABASE:-nextcloud}"
|
|
user="${MYSQL_USER:-nextcloud}"
|
|
pass="${MYSQL_PASSWORD:-}"
|
|
if command -v mariadb-dump >/dev/null 2>&1; then
|
|
MYSQL_PWD="$pass" mariadb-dump --single-transaction --quick -u "$user" "$db"
|
|
else
|
|
MYSQL_PWD="$pass" mysqldump --single-transaction --quick -u "$user" "$db"
|
|
fi
|
|
' | gzip -c > "$out"
|
|
}
|
|
|
|
dump_postgres "paperless-db" "paperless" "paperless"
|
|
dump_postgres "gitea-postgres" "gitea" "gitea"
|
|
dump_postgres "n8n-pg" "n8n" "n8n"
|
|
dump_postgres "vikunja-db" "vikunja" "vikunja"
|
|
dump_postgres "memos-db" "memos" "memos"
|
|
dump_postgres "ths-authentik-postgres" "authentik" "authentik"
|
|
dump_postgres "scheduler-db" "scheduler" "scheduler"
|
|
dump_postgres "guacamole-postgres" "guacamole" "guacamole"
|
|
dump_postgres "kasm_db" "kasmapp" "kasm"
|
|
dump_postgres "thscom-db" "postgres" "postgres"
|
|
dump_postgres "spintools-db" "postgres" "postgres"
|
|
dump_postgres "spintools-authentik-postgres" "authentik" "authentik"
|
|
dump_mariadb "nextcloud-db"
|
|
|
|
log "Database dumps written to $RUN_DIR"
|