eduardweb.
DevOps & VPSIntermediar#devops#postgresql#backup#backblaze-b2#bash

Backup automat de Postgres în Backblaze B2 cu pg_dump și cron (testat la restore)

De George Iliescu, 24 iul. 2026 · 11 vizualizări · 3 like-uri

Postat 24 iul. 2026
bash
#!/usr/bin/env bash
set -euo pipefail

# Setare cãi absolute pentru cron
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

DB_NAME="app_prod"
DB_USER="postgres"
B2_BUCKET="s3://my-app-backups-b2/postgres"
B2_ENDPOINT="https://s3.us-west-004.backblazeb2.com"

TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
BACKUP_DIR="/tmp/db_backups"
FILE_NAME="${DB_NAME}_${TIMESTAMP}.dump"
FULL_PATH="${BACKUP_DIR}/${FILE_NAME}"

mkdir -p "${BACKUP_DIR}"

echo "[$(date)] Starting backup for ${DB_NAME}..."

# Backup in format custom compresat
pg_dump -U "${DB_USER}" -F c -b -v -f "${FULL_PATH}" "${DB_NAME}"

echo "[$(date)] Uploading to Backblaze B2..."
aws s3 cp "${FULL_PATH}" "${B2_BUCKET}/${FILE_NAME}" --endpoint-url="${B2_ENDPOINT}"

echo "[$(date)] Cleaning local temp file..."
rm -f "${FULL_PATH}"

echo "[$(date)] Backup completed successfully!"

Am văzut prea multe proiecte unde "avem backup" înseamnă un cron obosit care salvează un fisier .sql pe același disc cu baza de date. Anul trecut, când am preluat o aplicație cu o bază PostgreSQL de vreo 18GB pe un VPS de la Hetzner, primul lucru pe care l-am făcut a fost să mut backup-urile în afara serverului.

Nu voiam să plătesc zeci de dolari pe lună doar pe stocare AWS S3 standard sau alte soluții enterprise. Am ales Backblaze B2, care e absurd de ieftin ($0.006/GB/lună) și oferă API 100% compatibil S3. Pentru 20-30GB de date păstrate pe o perioadă de o lună, factura mea este practic zero virgula câțiva cenți.

De ce formatul custom (pg_dump -Fc)?

Mulți juniori dau pg_dump database > backup.sql și apoi comprimă cu gzip. Nu e greșit, dar e ineficient. Dacă folosești parametrul -Fc (custom format), PostgreSQL generează o arhivă binară deja compresată.

Beneficiul masiv apare la restore: formatul custom îți permite să restaurezi doar anumite tabele, să schimbi schema din mers sau să folosești restore paralel pe mai multe thread-uri cu pg_restore -j. Timpul de restore scade drastic.

Configurarea și cron-ul fără suprize

Principala problemă când pui un script în crontab e mediul de executare. Cron nu încarcă .bashrc sau .zshrc, așa că scriptul tău va eșua tăcut dacă nu declari căile absolute pentru executabile (/usr/bin/pg_dump, /usr/local/bin/aws) sau dacă nu setezi explicit variabila PATH la început.

Adaugi asta în crontab (crontab -e) ca să ruleze în fiecare noapte la ora 02:00:

0 2 * * * /opt/scripts/postgres-backup.sh >> /var/log/db-backup.log 2>&1

Logging-ul într-un fișier local te salvează când se schimbă permisiunile pe un folder sau expiră cheia de API de la Backblaze.

Partea pe care o ignoră toți: Testul de Restore

Un backup netestat este doar o dorință. Am avut odată un șoc la un restore când am realizat că un dump era corupt din cauza unei nepotriviri de versiune între pg_dump și serverul de baza de date.

Ca să testezi că backup-ul chiar funcționează, pașii sunt simpli:

  1. Descarci arhiva din B2: aws s3 cp s3://bucket-ul-tau/db-backups/2023-10-25.dump ./test.dump --endpoint-url=https://s3.us-west-004.backblazeb2.com
  2. Creezi o bază de test curată: createdb -U postgres app_test
  3. Rulezi restore pe 4 thread-uri: pg_restore -U postgres -d app_test -j 4 --clean --if-exists test.dump

Flag-ul -j 4 mi-a redus timpul de restore de la 14 minute la sub 3 minute pe o instanță cu 4 vCPU-uri. Merită fiecare secundă de configurare.

Trade-off-uri sincere

Metoda asta e excelentă pentru proiecte mici și medii (până în 50-100GB). E ieftină, stabilă și simplu de debugat.

Totuși, trebuie să fii conștient de limitări: pg_dump ia un lock scurt pe cataloagele de sistem și creează I/O considerabil pe disc în timpul exportului. În plus, nu ai PITR (Point-In-Time Recovery). Dacă serverul crapă la ora 18:00, pierzi tot ce s-a scris de la ora 02:00 dimineața. Dacă ai nevoie de rpo zero sau aproape zero, renunță la pg_dump și treci pe pgBackRest sau WAL-G cu WAL streaming.

Voi ce soluții folosiți pentru bazele mici de date? Tot scripturi custom sau preferați un unealtă dedicată direct din orchestrator?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.