ডিজাইন docs/architecture/23-ops.mdৰ section 8-ত। Docker Compose product-ৰ বাবে এই runbook। ইয়াক অনুসৰণ কৰা ব্যক্তিজনে লিখা নাছিল বুলি ধৰি লিখা হৈছে; কোনো step অস্পষ্ট হ’লে এই নথিৰ দোষ।
কি সুৰক্ষিত, আৰু কেনেকৈ
| Asset | কেনেকৈ | ক’ত |
|---|---|---|
| Database | প্ৰথম boot-ৰ পৰা অবিৰতভাৱে, সৰ্বাধিক প্ৰতি 60 ছেকেণ্ডত WAL archive | pgwal volume |
| Database | pg_basebackupৰে base backup, ডিফল্টভাৱে দৈনিক (backup-scheduler) |
pgbackup volume |
| Database | Base backup আৰু WAL-ৰ encrypted copy, প্ৰতি পাঁচ মিনিটত (backup-offsite) |
আপোনাৰ নাম দিয়া পৃথক store |
| File | files volume। Host backup tool-ৰে copy কৰক অথবা version থকা object storage ব্যৱহাৰ কৰক |
files volume |
| Secret | docker/.env, বিশেষকৈ QUIRE_MASTER_KEY (আৰু এতিয়াও ব্যৱহৃত QUIRE_MASTER_KEY_RETIRED), QUIRE_BACKUP_ENCRYPTION_KEY, আৰু docker/secrets/audit-signing-key.pem |
এই host-ৰ বাহিৰত copy ৰাখক |
| Search index, cache, rendition | Backup নহয়; পুনৰ নিৰ্মাণ কৰা হয় |
লক্ষ্য: বিফলতাৰ 60 ছেকেণ্ডৰ ভিতৰত recovery point, আৰু 500 GB database-ৰ বাবে 60 মিনিটৰ ভিতৰত restore।
দুটা ভুল সাধাৰণ। File অবিহনে restore কৰা database-এ ভঙা page দেখুৱায়। QUIRE_MASTER_KEY অবিহনে restore কৰা database-এ ইয়াৰ SSO, webhook আৰু integration credential decrypt কৰিব নোৱাৰে; একো unresolved নথকাকৈ master key rotation সম্পূৰ্ণ নোহোৱালৈ (key-rotation.md), ইয়াত retired key-ও অন্তৰ্ভুক্ত। দুয়োটাই backup-ৰ অংশ।
Backup লওক
সম্পূৰ্ণ cluster-ৰ base backup:
docker compose -f docker/compose.yaml --profile backup run --rm backupই আটাইতকৈ নতুন QUIRE_BACKUP_KEEPটা base backup ৰাখে (ডিফল্ট 5) আৰু আটাইতকৈ পুৰণিটোৱে আৰু নলগা WAL prune কৰে, যাতে archive সীমাহীনভাৱে নাবাঢ়ে। Host-ত cron বা systemd timer-ৰে দৈনিক schedule কৰক:
15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1অথবা stack-ক schedule কৰিবলৈ দিয়ক: backup profile-এ backup-scheduler চলায়, যিয়ে প্ৰতিটো QUIRE_BACKUP_INTERVAL_HOURS ঘণ্টাত base backup লয় (ডিফল্ট 24), আৰু তলত বৰ্ণনা কৰা backup-offsite-ও চলে।
docker compose -f docker/compose.yaml --profile backup up -dHost-ৰ বাহিৰত encrypted copy
দুয়োটা volume database-ৰ সৈতে একে host-ত থাকে; বিফল হোৱা machine-ত থকা backup backup নহয়। backup-offsite-এ প্ৰতিটো base backup আৰু archived WAL segment পৃথক store-লৈ storage port-ৰে encrypted copy কৰে আৰু retention নিয়মত ৰাখে:
- Encryption.
QUIRE_BACKUP_ENCRYPTION_KEY(অথবাQUIRE_BACKUP_ENCRYPTION_KEY_FILE-এ নাম দিয়া file)-সহ AES-256-GCM:openssl rand -hex 32ৰে সৃষ্টি কৰা 32 byte। প্ৰতিটো file-ৰ নিজা nonce আৰু authentication tag থাকে, সেয়ে key অবিহনে copy পঢ়িব নোৱাৰি আৰু পৰিৱৰ্তন হ’লে ধৰা পৰে। Key-টোQUIRE_MASTER_KEYৰ সৈতে, এই host আৰু backup store-ৰ পৰা আঁতৰত ৰাখক। Key নাথাকিলে restore নহয়। - ক’ত.
QUIRE_BACKUP_STORAGE_DRIVERহৈছেs3,azureঅথবাlocal(QUIRE_BACKUP_STORAGE_ROOTত mount কৰা remote disk)। Setting-সমূহ file storage-ৰেইQUIRE_BACKUP_prefix-সহ:QUIRE_BACKUP_S3_ENDPOINT,QUIRE_BACKUP_S3_BUCKET,QUIRE_BACKUP_S3_ACCESS_KEY_IDআদি। File-ৰ পৰা বেলেগ bucket, ভাল হ’লে বেলেগ account ব্যৱহাৰ কৰি provider-এ অনুমতি দিলে লিখিব পৰা কিন্তু delete কৰিব নোৱাৰা credential দিয়ক। - Retention. আটাইতকৈ নতুন
QUIRE_BACKUP_OFFSITE_KEEPটা base backup (ডিফল্টQUIRE_BACKUP_KEEP, নহ’লে 7) আৰু আটাইতকৈ পুৰণিটোক লগা WAL; পুৰণি set আৰু segment store-ৰ পৰা delete হয়। - কেতিয়া. প্ৰতিটো
QUIRE_BACKUP_SHIP_INTERVAL_SECONDSছেকেণ্ডত (ডিফল্ট 300)। Shipping idempotent: আগতে store হোৱা বস্তু skip হয়; manifest শেষত লিখাৰ পিছতহে base backup store হোৱা বুলি গণ্য হয়।
হাতেৰে একে command চলে:
docker compose -f docker/compose.yaml run --rm backup-offsite bun apps/worker/src/backups/main.ts ship
docker compose -f docker/compose.yaml run --rm backup-offsite bun apps/worker/src/backups/main.ts verifyনতুন host-ত restore কৰিবলৈ, আগতে এটা set ঘূৰাই আনি তাৰ পিছত তলৰ step অনুসৰণ কৰক; download কৰা directory-টো pgbackup volume-ৰ সলনি আৰু download কৰা wal-archiveটো pgwalৰ সলনি ব্যৱহাৰ কৰক:
bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restoreসময়ৰ এটা বিন্দুলৈ restore
Data হেৰালে ব্যৱহাৰ কৰক: ভুল import, মচি পেলোৱা পাঠ্যক্ৰম, অথবা বাতিল কৰিবলগীয়া contract migration। ই live database সলনি কৰে, সেয়ে তলৰ drill-ৰে আগতে অভ্যাস কৰক।
- Target time বাছক, UTC-ত ক্ষতিৰ ঠিক আগৰ সময়:
2026-09-24 09:30:00+00। Audit log (/admin/audit)-এ সাধাৰণতে সেই মুহূৰ্ত দেখুৱায়। - লিখা কৰা সকলো বন্ধ কৰক:
docker compose -f docker/compose.yaml stop web content worker scheduler collab - Restore পৰীক্ষা নোহোৱালৈ ক্ষতিগ্ৰস্ত cluster ৰাখক:
docker compose -f docker/compose.yaml stop postgres docker run --rm -v quire_postgres18-data:/from -v quire_postgres-damaged:/to alpine cp -a /from/. /to/ - Target-তকৈ পুৰণি আটাইতকৈ নতুন base backup data volume-ত unpack কৰি targeted recovery বিচাৰক:
docker run --rm -v quire_pgbackup:/backups:ro -v quire_postgres18-data:/var/lib/postgresql postgres:18-alpine sh -euc ' base="$(ls -1d /backups/base-* | sort | tail -n 1)" # or the one before the target rm -rf /var/lib/postgresql/18/docker && mkdir -p /var/lib/postgresql/18/docker tar -xzf "$base/base.tar.gz" -C /var/lib/postgresql/18/docker touch /var/lib/postgresql/18/docker/recovery.signal chown -R postgres:postgres /var/lib/postgresql/18/docker && chmod 700 /var/lib/postgresql/18/docker' - Recover: স্বাভাৱিক file নসলনি কৰিবলৈ Compose override-ৰ পৰা recovery setting-সহ এবাৰ Postgres আৰম্ভ কৰক:
Override-এ সম্পূৰ্ণ command সলনি কৰে, সেয়ে recovery-ৰ প্ৰয়োজনীয় দুটা setting পুনৰ দিয়ে:# docker/compose.recover.yaml services: postgres: command: [postgres, -c, "restore_command=cp /var/lib/postgresql/wal-archive/%f %p", -c, "recovery_target_time=2026-09-24 09:30:00+00", -c, recovery_target_action=promote, -c, archive_mode=off, -c, max_connections=200, -c, hba_file=/etc/postgresql/pg_hba.conf]max_connectionsprimary-তকৈ কম নহ’ব (নহ’লে recovery “insufficient parameter settings”ৰে বন্ধ হয়) আৰু mount কৰাpg_hba.conf।docker compose -f docker/compose.yaml -f docker/compose.recover.yaml up -d postgres docker compose -f docker/compose.yaml logs -f postgres # wait for "database system is ready" - মানুহক সোমাবলৈ দিয়াৰ আগতে পৰীক্ষা কৰক: audit chain (
docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts) আৰু হেৰোৱা data ঘূৰি আহিছে নে। - স্বাভাৱিক অৱস্থালৈ ঘূৰক:
docker compose -f docker/compose.yaml up -d। ই archiving অন কৰি Postgres পুনৰ আৰম্ভ কৰে আৰু নতুন WAL timeline আৰম্ভ হয়। লগে লগে নতুন base backup লওক।
Project name quire প্ৰতিটো volume-ৰ আগত যোগ হয়; docker volume ls-এ হুবহু নাম দেখুৱায়।
Schedule কৰা verification drill
backup-offsite-এ প্ৰতিটো QUIRE_BACKUP_DRILL_INTERVAL_HOURS ঘণ্টাত (ডিফল্ট 168, সাপ্তাহিক) আৰু বিফলতাৰ পিছৰ পৰৱৰ্তী pass-ত drill চলায়। ই host-ৰ বাহিৰৰ নতুনতম base backup আৰু তাৰ পিছৰ প্ৰতিটো WAL segment fetch কৰি decrypt কৰে (key-এ এতিয়াও খুলিব পাৰে আৰু একো সলনি হোৱা নাই প্ৰমাণ হয়), প্ৰতিটো file manifest-ৰ সৈতে তুলনা কৰে, archive Postgres data directory নে পৰীক্ষা কৰে আৰু backup-ৰ পিছৰ WAL-ত gap নাই বুলি নিশ্চিত কৰে। Report-টো reports/drill-<time>.json হিচাপে store আৰু service log-ত লিখা হয়; বিফল drill-এ file বা প্ৰথম missing segment-ৰ নাম কয়।
Restore drill
কেতিয়াও restore নকৰা backup, backup নহয়। Drill-এ target-ৰ আগতে লোৱা নতুনতম সম্পূৰ্ণ base backup আৰু WAL archive live-ৰ পৰা একো share নকৰা scratch Postgres-ত restore কৰি ফল প্ৰমাণ কৰে:
docker/scripts/restore-drill.sh # to ninety minutes ago
docker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"Target হুবহু এই format-ৰ UTC সময়। ইয়াৰ আগৰ এটা base backup আৰু তাৰ পিছৰ archived WAL লাগে: নতুন install-ত base backup লৈ পৰৱৰ্তী archive segment আহিবলৈ (write থাকিলে সৰ্বাধিক এক মিনিট) অপেক্ষা কৰি তাৰ পিছৰ target বাছক। Host-ত Docker আৰু bash-হে লাগে।
প্ৰতিটো step-এ drill fail কৰে:
- Recoverability: scratch cluster-এ target-লৈ replay কৰি খোলে।
- Completeness: live database-ৰ বিপৰীতে প্ৰতিটো table-ৰ row count (
tooling/restore-drill)। Live database target-ৰ পিছত আগবাঢ়িছে; সেয়ে যিকোনো দিশত table-ৰ পাৰ্থক্য 500 row বা size-ৰ এক-দশমাংশৰ ভিতৰত যিটো ডাঙৰ সেইখিনি হ’ব পাৰে (write-এ restore পিছত ৰাখে, deletion-এ restore-ত বেছি ৰাখে); target-ৰ পিছত সৃষ্টি হোৱা partition হেৰোৱা table নহয়। অধিক ব্যস্ত install-তQUIRE_DRILL_MAX_BEHINDআৰুQUIRE_DRILL_MAX_DRIFT_RATIOৰে allowance বঢ়াওক। Missing বা খালী table-এ fail কৰে। - Integrity: restored copy-ত audit hash chain verify হয়।
- ব্যৱহাৰযোগ্যতা: application role-এ row-level security-ৰে পঢ়ে।
- সময়: আৰম্ভণিৰ পৰা সফল হোৱালৈ
QUIRE_DRILL_RTO_SECONDSৰ বিপৰীতে (ডিফল্ট 3600)।
ই live database বা volume-ত কেতিয়াও লিখা নকৰে: backup আৰু WAL volume read-only mount হয় আৰু pass বা fail যিয়েই হওক শেষত scratch cluster আঁতৰোৱা হয়।
JSON report (pass বা fail) লিখিবলৈ QUIRE_DRILL_REPORTক path দিয়ক আৰু Docker host-ৰ পৰা schedule কৰক:
30 3 1 * * cd /srv/quire && QUIRE_DRILL_REPORT=/var/log/quire-drill.json docker/scripts/restore-drill.sh >> /var/log/quire-drill.log 2>&1মাহে এবাৰ আৰু প্ৰতিটো upgrade-ৰ আগতে চলাওক। বিফল drill-এ upgrade বন্ধ কৰে। প্ৰতি quarter-ত এই runbook নিলিখা কোনোবাক কেৱল এই নথি ব্যৱহাৰ কৰি spare host-ত প্ৰকৃত point-in-time restore কৰিবলৈ দিয়ক।
File
Local file files volume-ত থাকে। Database-ৰ সৈতে একে সময়তে backup লৈ দুয়ো একেলগে restore কৰক:
docker run --rm -v quire_files:/files:ro -v "$PWD":/out alpine tar -czf /out/files-$(date -u +%Y%m%d).tar.gz -C /files .Object storage-ত bucket versioning অন কৰি 35 দিনৰ noncurrent version ৰাখক; তেতিয়া file-ৰ point-in-time recovery bucket-ৰ নিজা কাম।