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:
2026-10-10 16:53:10 +03:30
parent 19072ee534
commit a9cccc6550
22 changed files with 374 additions and 447 deletions

View File

@@ -328,7 +328,7 @@ reliably pull the final answer out of a solution and produced ~40% broken output
## Known gaps (per README pre-deploy checklist)
- Postgres is live; no off-machine backup yet (owner waiting for the destination from the senior).
- Postgres is live and streamed live to the backup server (see «بکاپ» below); restoring onto 249 itself never rehearsed.
- Throttle rates need periodic review against real traffic.
- `DEV_MASTER_OTP` (`0000`) must stay gated behind `DEBUG` — never enabled in prod.
- No video content exists yet, though `Lesson.kind`/`video_url` can express it.
@@ -445,6 +445,29 @@ preferred setup, because there is then no key to leak. **Never let the server ru
`django-insecure-…` fallback from `config/settings.py`: that string is committed here, so
anyone who can read this repo can forge a token for any user.**
## بکاپ: کپیِ زنده روی سرورِ ۲۴۷ — از ۲۰۲۶-۱۰-۱۰
**هر تغییرِ دیتابیس لحظه‌ای به سرورِ دیگری می‌رود؛ بکاپِ شبانه‌ی خودمان (`backup_db`/`backup_verify`/cron) حذف شد.**
شرحِ کامل و رویه‌ی بازیابی: `docs/operations.md` «بکاپ و بازیابی». فایل‌ها: `ops/pgbackup/`.
- **سرورِ بکاپ:** `administrator@78.38.35.247`، همان رمزِ ۲۴۹ (همان فایلِ رمز). شبکه‌ی داخلی: ۲۴۹ = `192.168.200.164`،
۲۴۷ = `192.168.200.167`. **۲۴۷ هم ماشینِ مشترک است** (artina، judge0، metaverse، docker، و `postgresql@14-main`ِ
دیگران روی ۵۴۳۲): همان قواعدِ «The server» این‌جا هم هست. مالِ ما فقط `~/zareian-pgbackup/` و یونیت‌های
`zareian-pg-*` است. Postgresِ آن‌جا را به کار نمی‌گیریم؛ فقط ابزارهای Postgres 14 را اجرا می‌کنیم.
- **چطور:** روی ۲۴۷ `zareian-pg-tunnel` (SSH با کلیدِ `~/.ssh/zareian_pgbackup` که در `authorized_keys`ِ ۲۴۹ به
`permitopen="127.0.0.1:5440"` محدود است، شِل نمی‌دهد) → `zareian-pg-wal` (`pg_receivewal`، اسلاتِ `zareian_247`،
نقشِ `zareian_replicator`، رمزش فقط در `~/.pgpass`ِ ۲۴۷) → `wal/`؛ و `zareian-pg-basebackup.timer` هر روز ۰۴:۳۰ →
`base/` (۷ تا، با `pg_verifybackup`؛ WALِ قدیمی‌تر از قدیمی‌ترین پاک می‌شود).
- **۲۴۹ را نمی‌خواباند:** تکثیر ناهمزمان است (`sync_state: async`)؛ `max_slot_wal_keep_size=1GB` (با `ALTER SYSTEM`،
نه `/etc`) سقفِ چیزی است که در قطعیِ ۲۴۷ روی دیسکِ ۲۴۹ جمع می‌شود. قطعیِ طولانی‌تر اسلات را `lost` می‌کند (رویه در docs).
- **پایش:** `OFFSITE_WAL_SLOT=zareian_247` در `.env`ِ ۲۴۹؛ `/api/health` (با کلید) `offsiteBackup` و هشدار می‌دهد
(`config/tests_offsite_backup.py`). شکستِ نسخه‌ی روزانه فقط در `journalctl -u zareian-pg-basebackup`ِ ۲۴۷ دیده می‌شود.
- **سنجیده (۲۰۲۶-۱۰-۱۰):** کلید شِل نمی‌گیرد و تونل به پورتِ دیگر رد می‌شود؛ `restore-check.sh` روی ۲۴۷ شمارش و آخرین
زمانِ کاربر/ورود/سفارش/تراکنش/تغییرِ وضعیت را برابرِ ۲۴۹ داد؛ یک ردیفِ آزمایشی که بعد از نسخه‌ی کامل روی ۲۴۹ نوشته شد
۲ ثانیه بعد در بازیابیِ ۲۴۷ بود (جدولش پاک شد). **نسنجیده:** ری‌بوتِ ۲۴۷، قطعیِ طولانی تا `lost`، اجرای خودکارِ timer
(اولین بار ۲۰۲۶-۱۰-۱۱ ۰۴:۳۰)، و برگرداندنِ بازیابی روی خودِ ۲۴۹.
- ایمیجِ روزانه‌ی کلِ ماشین کارِ ادمینِ سرور است؛ محتوایش را ما نسنجیده‌ایم. کپیِ ما به آن تکیه نمی‌کند.
## اشتراک و دیوارِ پرداخت — روی سرور از ۲۰۲۶-۱۰-۱۰ ۰۱:۱۹ (بک‌اند `64c4c09`، فرانت `a8a5351`)
- **فقط فصلِ اولِ هر پایه رایگان است** (`content.views.unit_is_free`). بیرون از آن، بی‌اشتراکِ فعال، سوال‌های درس،
@@ -903,9 +926,9 @@ migrationها اعمال شدند، سه‌یار و `nextLessonId` از بیر
(`templates/tadrisino/`) تا متنِ فارسی راست‌به‌چپ رندر شود. قالبِ drf-spectacular
دست‌نخورده است و با `{{ block.super }}` گسترش داده شده.
**بکاپ:** `deploy.sh` پیش از `migrate` خودش بکاپ می‌گیرد (`db-before-deploy-*`، ۲ تای آخر،
بی‌بکاپ migrate نمی‌شود)؛ روی سرور هم اجرا شد (۲۰۲۶-۱۰-۰۷، `integrity_check: ok`). بیرون از ماشین بکاپی
نیست.
**بکاپ:** `deploy.sh` پیش از `migrate` خودش بکاپ می‌گیرد (`db-before-deploy-*`، ۳ تای آخر، بی‌بکاپ
migrate نمی‌شود) و مرحله‌ی «نگه‌داریِ بکاپ‌ها» بقیه‌ی `.deploy-backups` را مرتب می‌کند (بکاپِ دستیِ پیش از
تغییر بعد از ۳۰ روز پاک می‌شود). کپیِ واقعیِ داده بیرون از ماشین است؛ بخشِ پایین.
**⚠️ Gitea از روی سرور:** از ۲۰۲۶-۱۰-۰۷ `https://gitea.tadrisino2.ir` از خودِ سرور (حل‌شده به IPهای
ArvanCloud) ۵۰۴ می‌دهد و از لپ‌تاپ ۲۰۰؛ علتش پیدا نشد (مسیرِ آروان↔سرور). `deploy.sh` در `git fetch` می‌ایستد.