notebookvb

This commit is contained in:
Administrator
2026-05-23 06:54:13 +02:00
parent bfa049e0c2
commit 13065aab94
11 changed files with 677 additions and 237 deletions
+68
View File
@@ -0,0 +1,68 @@
# PostgreSQL Backup - Tower
PostgreSQL 18 (Docker: `postgresql18`) na Tower (192.168.1.76).
## Konfigurace
| Parametr | Hodnota |
|----------|---------|
| Server | Tower (192.168.1.76) |
| Container | `postgresql18` |
| Port | 5432 |
| User | `vladimir.buzalka` |
| Metoda | `pg_dumpall` (všechny DB najednou) |
| Záloha | `/mnt/user/Backup/Critical/PostgreSQLBackup/tower/YYYY-MM-DD_HHMM/` |
| Retence | 7 dní / posledních 7 záloh |
## Skripty
### `postgresqlbackup_with_gzip.sh`
Provede `pg_dumpall` všech databází, rolí a tablespaces. Výstup je komprimovaný gzip soubor `all_databases.sql.gz`.
```bash
bash postgresqlbackup_with_gzip.sh
```
Výsledná struktura:
```
/mnt/user/Backup/Critical/PostgreSQLBackup/tower/
└── 2026-05-23_0200/
└── all_databases.sql.gz
```
### `postgresqlrestore_from_backup.sh`
Obnoví všechny databáze z nejnovější zálohy (nebo ze zadané cesty).
```bash
# Nejnovější záloha (automaticky)
bash postgresqlrestore_from_backup.sh
# Konkrétní záloha
bash postgresqlrestore_from_backup.sh /mnt/user/Backup/Critical/PostgreSQLBackup/tower/2026-05-23_0200
```
> **POZOR:** Dump obsahuje `--clean --if-exists`, takže restore přepíše existující data.
### `verify_backup_integrity.sh`
Ověří po restore že jsou všechny DB, tabulky, indexy a role přítomny a funkční.
```bash
bash verify_backup_integrity.sh
```
## Nastavení Unraid User Script
Na Tower přidat User Script `POSTGRESQL_BACKUP`:
```bash
#!/bin/bash
bash /boot/config/plugins/user.scripts/scripts/POSTGRESQL_BACKUP/postgresqlbackup_with_gzip.sh
```
Schedule: **Daily**
## Windows přístup k zálohám
```
\\tower\Backup\Critical\PostgreSQLBackup\
```
@@ -0,0 +1,84 @@
#!/bin/bash
set -x
# ==========================================================
# CONFIGURATION
# ==========================================================
CONTAINER_NAME="postgresql18"
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="vladimir.buzalka"
export PGPASSWORD="Vlado7309208104++"
UNRAID_NAME="tower"
BASE_PATH="/mnt/user/Backup/Critical/PostgreSQLBackup"
KEEP_DAYS=7
KEEP_COUNT=7 # počet posledních záloh k udržení (mimo time-based)
# ==========================================================
# START
# ==========================================================
echo "Starting PostgreSQL full backup (pg_dumpall)"
START_TS=$(date '+%Y-%m-%d %H:%M:%S')
DATE=$(date +%Y-%m-%d_%H%M)
FINAL_PATH="$BASE_PATH/$UNRAID_NAME/$DATE"
mkdir -p "$FINAL_PATH"
DUMP_FILE="$FINAL_PATH/all_databases.sql.gz"
ERR_FILE="$FINAL_PATH/all_databases.err"
# ==========================================================
# DUMP + GZIP
# pg_dumpall zachovává: všechny DB, role, tablespaces, grants
# Streamuje přes stdout, nepotřebuje volume mount
# ==========================================================
docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
pg_dumpall \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--clean \
--if-exists \
| gzip > "$DUMP_FILE" 2> "$ERR_FILE"
EXIT_CODE=${PIPESTATUS[0]}
# ==========================================================
# VALIDATION
# ==========================================================
if [ $EXIT_CODE -eq 0 ] && [ -s "$DUMP_FILE" ] && [ ! -s "$ERR_FILE" ]; then
echo "SUCCESS: Full PostgreSQL backup completed"
echo "Dump size: $(du -h "$DUMP_FILE" | cut -f1)"
rm -f "$ERR_FILE"
else
echo "ERROR: Backup failed"
echo "Exit code: $EXIT_CODE"
echo "Dump file:"
ls -lh "$DUMP_FILE" 2>/dev/null || echo " (not created)"
echo "Error output:"
[ -s "$ERR_FILE" ] && cat "$ERR_FILE" || echo " (no stderr output)"
fi
# ==========================================================
# CLEANUP OLD BACKUPS
# 1. Smaž zálohy starší než KEEP_DAYS dnů
# 2. Z toho co zbyde, ponech jen posledních KEEP_COUNT
# ==========================================================
echo "Cleaning up old backups..."
find "$BASE_PATH/$UNRAID_NAME" \
-mindepth 1 -maxdepth 1 -type d -mtime +$KEEP_DAYS \
-exec rm -rf {} \;
# Nech jen posledních KEEP_COUNT záloh
ls -td "$BASE_PATH/$UNRAID_NAME"/*/ 2>/dev/null \
| tail -n +$((KEEP_COUNT + 1)) \
| xargs -r rm -rf
echo "------------------------------------------"
echo "Backup task completed at $(date)"
echo "Started at: $START_TS"
set +x
@@ -0,0 +1,87 @@
#!/bin/bash
set -x
# ==========================================================
# CONFIGURATION
# ==========================================================
CONTAINER_NAME="postgresql18"
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="vladimir.buzalka"
export PGPASSWORD="Vlado7309208104++"
# Cesta k záloze kterou chceš obnovit
# Lze předat jako argument, nebo nechá najít nejnovější
# Např: $0 /mnt/user/Backup/Critical/PostgreSQLBackup/tower/2026-05-23_0200
BACKUP_DIR="$1"
BASE_PATH="/mnt/user/Backup/Critical/PostgreSQLBackup/tower"
# ==========================================================
# FIND BACKUP
# ==========================================================
if [ -z "$BACKUP_DIR" ]; then
echo "No backup path specified - using latest available backup"
BACKUP_DIR=$(ls -td "$BASE_PATH"/*/ 2>/dev/null | head -1)
if [ -z "$BACKUP_DIR" ]; then
echo "ERROR: No backups found in $BASE_PATH"
exit 1
fi
fi
if [ ! -d "$BACKUP_DIR" ]; then
echo "ERROR: Backup directory does not exist: $BACKUP_DIR"
exit 1
fi
BACKUP_FILE="$BACKUP_DIR/all_databases.sql.gz"
if [ ! -f "$BACKUP_FILE" ]; then
echo "ERROR: Backup file not found: $BACKUP_FILE"
exit 1
fi
echo "Starting PostgreSQL restore from: $BACKUP_FILE"
echo "Backup date: $(stat -c %y "$BACKUP_FILE" | cut -d' ' -f1-2)"
echo "Backup size: $(du -h "$BACKUP_FILE" | cut -f1)"
START_TS=$(date '+%Y-%m-%d %H:%M:%S')
ERR_FILE="$BACKUP_DIR/all_databases.restore.err"
# ==========================================================
# RESTORE
# pg_dumpall dump se obnovuje přes psql
# --clean + --if-exists v dumpu zajišťuje drop před recreate
# ==========================================================
echo "Restoring all databases to PostgreSQL..."
gunzip -c "$BACKUP_FILE" \
| docker exec -i \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="postgres" \
2> "$ERR_FILE"
RESTORE_EXIT=${PIPESTATUS[1]}
# ==========================================================
# VALIDATION
# ==========================================================
if [ $RESTORE_EXIT -eq 0 ]; then
echo "SUCCESS: All databases restored successfully"
rm -f "$ERR_FILE"
else
echo "ERROR: Restore failed"
echo "Exit code: $RESTORE_EXIT"
echo "Error output:"
[ -s "$ERR_FILE" ] && cat "$ERR_FILE" || echo " (no stderr output)"
fi
echo "------------------------------------------"
echo "Restore task completed at $(date)"
echo "Started at: $START_TS"
set +x
+171
View File
@@ -0,0 +1,171 @@
#!/bin/bash
set -x
# ==========================================================
# VERIFY BACKUP INTEGRITY
# Kontroluje že se všechny DB, tabulky a data
# správně obnovily po restore
# ==========================================================
CONTAINER_NAME="postgresql18"
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="vladimir.buzalka"
export PGPASSWORD="Vlado7309208104++"
echo "Starting PostgreSQL backup integrity verification..."
echo "=========================================="
ALL_OK=true
# ==========================================================
# 1. CONNECTIVITY CHECK
# ==========================================================
echo ""
echo "Checking PostgreSQL connectivity..."
docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="postgres" \
--tuples-only \
--command="SELECT 'connected';" > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "ERROR: Cannot connect to PostgreSQL!"
exit 1
fi
echo "OK: Connected to PostgreSQL"
# ==========================================================
# 2. LIST ALL DATABASES
# ==========================================================
echo ""
echo "Databases present:"
docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="postgres" \
--tuples-only \
--command="SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;"
# Ulož seznam DB do proměnné pro iteraci
DATABASES=$(docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="postgres" \
--tuples-only \
--command="SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;" \
| tr -d ' ')
# ==========================================================
# 3. PER-DATABASE CHECKS
# ==========================================================
for DB_NAME in $DATABASES; do
[ -z "$DB_NAME" ] && continue
echo ""
echo "Verifying database: $DB_NAME"
echo "------------------------------------------"
# Počet tabulek
TABLE_COUNT=$(docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="$DB_NAME" \
--tuples-only \
--command="SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" \
| tr -d ' ')
echo "OK: Tables in public schema: $TABLE_COUNT"
# Seznam tabulek s počtem řádků
echo " Table row counts:"
docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="$DB_NAME" \
--tuples-only \
--command="
SELECT
schemaname || '.' || relname AS table_name,
n_live_tup AS estimated_rows,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_stat_user_tables
ORDER BY relname;"
# Počet indexů
INDEX_COUNT=$(docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="$DB_NAME" \
--tuples-only \
--command="SELECT COUNT(*) FROM pg_indexes WHERE schemaname = 'public';" \
| tr -d ' ')
echo "OK: Indexes in public schema: $INDEX_COUNT"
# Celková velikost DB
DB_SIZE=$(docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="$DB_NAME" \
--tuples-only \
--command="SELECT pg_size_pretty(pg_database_size('$DB_NAME'));" \
| tr -d ' ')
echo "OK: Database size: $DB_SIZE"
done
# ==========================================================
# 4. CHECK ROLES / USERS
# ==========================================================
echo ""
echo "PostgreSQL roles:"
docker exec \
-e PGPASSWORD="$PGPASSWORD" \
"$CONTAINER_NAME" \
psql \
--host="$PG_HOST" \
--port="$PG_PORT" \
--username="$PG_USER" \
--dbname="postgres" \
--command="SELECT rolname, rolsuper, rolcreatedb, rolcanlogin FROM pg_roles WHERE rolname NOT LIKE 'pg_%' ORDER BY rolname;"
echo ""
echo "=========================================="
if [ "$ALL_OK" = true ]; then
echo "OK: All verifications passed!"
else
echo "ERROR: Some verifications failed!"
exit 1
fi
set +x