Live off-site Postgres copy on 247 replaces the nightly pg_dump; backup retention in deploy.sh
- ops/pgbackup: SSH tunnel + pg_receivewal (slot zareian_247) + daily verified pg_basebackup (keep 7) and a restore check, all run on 78.38.35.247 as systemd units - /api/health reports offsiteBackup (slot active/lag/lost) and warns; OFFSITE_WAL_SLOT setting - removed statuslog backup_db/backup_verify and their health warnings - deploy.sh keeps 3 pre-deploy dumps, 3 local patches, drops manual backups after 30 days - docs: operations backup section, security item 14 closed, CLAUDE.md status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
28
deploy.sh
28
deploy.sh
@@ -222,9 +222,10 @@ printf ' دیتابیس و بکاپها فقط برای %s خواندنی
|
||||
#
|
||||
# با sqlite3.Connection.backup() نه cp: کپیِ ساده وسطِ یک نوشتن فایلِ نیمهکاره میدهد (sqlite3
|
||||
# بهعنوانِ فرمان روی سرور نیست). اگر بکاپ نشد، migrate اجرا نمیشود: دیپلوی بیبکاپ را
|
||||
# عمداً نمیپذیریم. فقط ۲ بکاپِ خودکارِ آخر (db-before-deploy-*: همین انتشار و یکی قبلتر) نگه داشته میشود تا دیسکِ
|
||||
# عمداً نمیپذیریم. فقط ۳ بکاپِ خودکارِ آخر (db-before-deploy-*: همین انتشار و دو تای قبل) نگه داشته میشود تا دیسکِ
|
||||
# مشترک پر نشود؛ بکاپهای دستی با نامِ دیگر دست نمیخورند.
|
||||
# Postgres با pg_dump (آزمودهنشده روی سرور تا انتقال)؛ بکاپ از بیرونِ ماشین که هنوز نیست (بند ۱۷ در چکلیستِ لانچ).
|
||||
# Postgres با pg_dump. این بکاپ فقط برای برگشتن از migrationِ خراب است؛ کپیِ زندهی بیرونِ ماشین جداست
|
||||
# (ops/pgbackup/، docs/operations.md «بکاپ و بازیابی»).
|
||||
step "بکاپِ دیتابیس"
|
||||
python - <<'PYBACKUP' || fail "بکاپِ دیتابیس نشد؛ migrate اجرا نشد و هیچ تغییری روی داده اعمال نشد."
|
||||
import datetime
|
||||
@@ -252,7 +253,7 @@ if db['ENGINE'] == 'django.db.backends.postgresql':
|
||||
# فقط خوانا بودنِ فایل را میسنجد؛ بازیابیِ واقعی روی دیتابیسِ دیگر آزموده نشده.
|
||||
subprocess.run(['pg_restore', '--list', dst], check=True, stdout=subprocess.DEVNULL)
|
||||
print(f' {dst} ({os.path.getsize(dst) // 2**20} MB، pg_restore --list: ok)')
|
||||
old = sorted(glob.glob('.deploy-backups/db-before-deploy-*.pgdump'))[:-2]
|
||||
old = sorted(glob.glob('.deploy-backups/db-before-deploy-*.pgdump'))[:-3]
|
||||
for path in old:
|
||||
os.remove(path)
|
||||
raise SystemExit(0)
|
||||
@@ -285,13 +286,30 @@ if result != 'ok':
|
||||
raise SystemExit(f' بکاپ ساخته شد ولی integrity_check «{result}» داد: {dst}')
|
||||
print(f' {dst} ({os.path.getsize(dst) // 2**20} MB، integrity_check: ok)')
|
||||
|
||||
old = sorted(glob.glob('.deploy-backups/db-before-deploy-*.sqlite3'))[:-2]
|
||||
old = sorted(glob.glob('.deploy-backups/db-before-deploy-*.sqlite3'))[:-3]
|
||||
for path in old:
|
||||
os.remove(path)
|
||||
if old:
|
||||
print(f' {len(old)} بکاپِ خودکارِ قدیمیتر پاک شد (۲ تای آخر میماند).')
|
||||
print(f' {len(old)} بکاپِ خودکارِ قدیمیتر پاک شد (۳ تای آخر میماند).')
|
||||
PYBACKUP
|
||||
|
||||
# ─── ۳.۸ نگهداریِ بکاپها ─────────────────────────────────────────────────
|
||||
# .deploy-backups بیسقف بزرگ میشد و دیسکِ این ماشینِ مشترک ~۸۸٪ پُر است. قاعدهی هر انتشار:
|
||||
# db-before-deploy-* ۳ تای آخر (مرحلهی قبل)
|
||||
# local-changes/commits-* ۳ تای آخر از هر کدام
|
||||
# هر چیزِ دیگر بکاپهای دستیِ پیش از تغییر (env-before-*، db-before-*، unit-*…): پس از ۳۰ روز
|
||||
# پاک. کپیِ .env رمز دارد و یک ماه بعد کسی به آن برنمیگردد.
|
||||
# کپیِ واقعیِ داده اینجا نیست: کپیِ زنده روی سرورِ دیگر است (ops/pgbackup/).
|
||||
step "نگهداریِ بکاپها"
|
||||
if [ -d .deploy-backups ]; then
|
||||
for pattern in 'local-changes-*.patch' 'local-commits-*.patch'; do
|
||||
ls -1t .deploy-backups/$pattern 2>/dev/null | tail -n +4 | xargs -r rm -f --
|
||||
done
|
||||
find .deploy-backups -maxdepth 1 -type f ! -name 'db-before-deploy-*' ! -name 'local-changes-*' \
|
||||
! -name 'local-commits-*' -mtime +30 -print -delete | sed 's/^/ پاک شد: /'
|
||||
printf ' .deploy-backups: %s\n' "$(du -sh .deploy-backups | cut -f1)"
|
||||
fi
|
||||
|
||||
# ─── ۴. دیتابیس ────────────────────────────────────────────────────────────
|
||||
step "اعمالِ مهاجرتهای دیتابیس"
|
||||
python manage.py migrate --noinput || fail "migrate شکست خورد؛ سرویس ریاستارت نشد."
|
||||
|
||||
Reference in New Issue
Block a user