ንድፉ በdocs/architecture/23-ops.md ክፍል 8 ውስጥ ነው። ይህ ለDocker Compose ምርት የስራ መመሪያ ነው። ያልጻፈው ሰው እንዲከተለው ተዘጋጅቷል፤ ደረጃ ግልጽ ካልሆነ የዚህ ሰነድ ጉድለት ነው።
የሚጠበቀውና እንዴት እንደሚጠበቅ
| ንብረት | ዘዴ | ቦታ |
|---|---|---|
| ውሂብ ጎታ | ከመጀመሪያው ማስነሻ ጀምሮ WAL በየ60 ሰከንዱ ቢበዛ በቀጣይነት ይቀመጣል | pgwal ድምጽ |
| ውሂብ ጎታ | በነባሪ በየቀኑ በpg_basebackup የመነሻ ምትኬ፤ (backup-scheduler) |
pgbackup ድምጽ |
| ውሂብ ጎታ | የመነሻ ምትኬና WAL በየ5 ደቂቃው የሚወሰዱ የተመሰጠሩ ቅጂዎች (backup-offsite) |
እርስዎ የሰየሙት የተለየ ማከማቻ |
| ፋይሎች | files ድምጹን በአገልጋይዎ ምትኬ መሣሪያ ይቅዱ ወይም ስሪት የሚይዝ የobject storage ይጠቀሙ |
files ድምጽ |
| ሚስጥሮች | docker/.env፣ በተለይ QUIRE_MASTER_KEY (አሁንም በጥቅም ላይ ካሉ የQUIRE_MASTER_KEY_RETIRED ቁልፎች)፣ QUIRE_BACKUP_ENCRYPTION_KEY እና docker/secrets/audit-signing-key.pem |
ከዚህ አገልጋይ ውጭ ቅጂ ያቆዩ |
| የፍለጋ ኢንዴክሶች፣ cacheዎች፣ የፋይል ቅጂዎች | ምትኬ አይወሰድም፤ እንደገና ይገነባሉ |
ዓላማው ከመውደቁ በ60 ሰከንድ ውስጥ ያለ የማገገሚያ ነጥብ፣ እና 500 GB ውሂብ ጎታን በ60 ደቂቃ ውስጥ መመለስ ነው።
ሁለት ስህተቶች በተደጋጋሚ ይፈጠራሉ። ፋይሎቹ ሳይመለሱ የተመለሰ ውሂብ ጎታ የተሰበሩ ገጾችን ያሳያል። QUIRE_MASTER_KEY ሳይመለስ የተመለሰ ውሂብ ጎታ ያለበትን የSSO፣ የwebhookና የውህደት ምስክርነቶች መፍታት አይችልም፤ ከቁልፍ ማሽከርከሩ ምንም ያልተፈታ ሳይቀር እስኪጠናቀቅ ድረስ (key-rotation.md) የተወገዱ ቁልፎችም ያስፈልጋሉ። ሁለቱም የምትኬው አካል ናቸው።
ምትኬ መውሰድ
የሙሉ ክላስተሩ መነሻ ምትኬ፦
docker compose -f docker/compose.yaml --profile backup run --rm backupአዲሶቹን QUIRE_BACKUP_KEEP የመነሻ ምትኬዎች (በነባሪ 5) ያቆያል፤ ከእንግዲህ የማያስፈልገውን አሮጌ WAL ይሰርዛል፣ ስለዚህ መዝገቡ ያለገደብ አያድግም። በአገልጋዩ ላይ በcron ወይም systemd timer በየቀኑ እንዲያካሂድ ያቀናብሩ፦
15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1ወይም stackው በራሱ እንዲያቀናጅ ያድርጉ፦ backup profile backup-schedulerን ያስነሳል፤ ይህም በየQUIRE_BACKUP_INTERVAL_HOURS (በነባሪ 24) የመነሻ ምትኬ ይወስዳል፣ ቀጥሎም backup-offsiteን እንደሚከተለው ያስኬዳል።
docker compose -f docker/compose.yaml --profile backup up -dከአገልጋዩ ውጭ የተመሰጠሩ ቅጂዎች
ሁለቱም ድምጾች ከውሂብ ጎታው ጋር በአንድ አገልጋይ ላይ ናቸው፤ የወደቀው ማሽን ላይ ያለ ምትኬ ምትኬ አይደለም። backup-offsite እያንዳንዱን የመነሻ ምትኬና የተቀመጠ WAL ክፍል በstorage port በኩል ወደ የተለየ ማከማቻ በምስጠር ይቅዳል፣ በretention መሠረትም እዚያ ያቆያል፦
- ምስጠራ። AES-256-GCM ከ
QUIRE_BACKUP_ENCRYPTION_KEYጋር (ወይምQUIRE_BACKUP_ENCRYPTION_KEY_FILEበሚጠራው ፋይል)፦ 32 ባይት፣ በopenssl rand -hex 32የሚመነጭ። እያንዳንዱ ፋይል የራሱ nonceና authentication tag አለው፤ ስለዚህ ያለ ቁልፉ ቅጂው ሊነበብ አይችልም፣ ለውጥም ከተደረገበት ይገነዘባል። ቁልፉን ከQUIRE_MASTER_KEYጋር ከዚህ አገልጋይና ከምትኬ ማከማቻው ርቆ ያቆዩ፤ ያለ ቁልፉ መመለስ አይቻልም። - የት እንደሚቀመጥ።
QUIRE_BACKUP_STORAGE_DRIVERየs3፣azureወይምlocalእሴት ይይዛል (ከርቀት የተገናኘ ዲስክ በQUIRE_BACKUP_STORAGE_ROOT)። ቅንብሮቹ የፋይል ማከማቻ ቅንብሮች በQUIRE_BACKUP_ቅድመ ቅጥያ ናቸው፦QUIRE_BACKUP_S3_ENDPOINT፣QUIRE_BACKUP_S3_BUCKET፣QUIRE_BACKUP_S3_ACCESS_KEY_IDወዘተ። ከፋይሎቹ የተለየ bucket፣ ከተቻለም የተለየ account ይጠቀሙ፤ አቅራቢው ከፈቀደ መጻፍ የሚችሉ ግን መሰረዝ የማይችሉ ምስክርነቶችን ይምረጡ። - የማቆያ ጊዜ። አዲሶቹ
QUIRE_BACKUP_OFFSITE_KEEPመነሻ ምትኬዎች (ነባሪውQUIRE_BACKUP_KEEPከተቀመጠ፣ ካልሆነ 7) እና ከአሮጌው የሚያስፈልገው WAL ይቀመጣሉ፤ አሮጌ ስብስቦችና ክፍሎች ከማከማቻው ይሰረዛሉ። - መቼ እንደሚላክ። በየ
QUIRE_BACKUP_SHIP_INTERVAL_SECONDS(ነባሪ 300)። መላኩ idempotent ነው፤ ቀድሞ የተቀመጠው ይዘለላል፣ የመነሻ ምትኬም manifestው በመጨረሻ ከተጻፈ ብቻ እንደተቀመጠ ይቆጠራል።
ተመሳሳይ ትእዛዝ በእጅ ማስኬድ ይቻላል፦
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በአዲስ አገልጋይ ለመመለስ መጀመሪያ የምትኬ ስብስቡን ያመጡ። ከዚያ pgbackup ድምጽ ፋንታ ያመጡትን ማውጫ፣ እንዲሁም ያመጡትን wal-archive በpgwal ድምጽ ፋንታ በመጠቀም የሚከተሉትን ደረጃዎች ይከተሉ፦
bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restoreወደ ተወሰነ ጊዜ መመለስ
ይህን ከውሂብ መጥፋት በኋላ ይጠቀሙ፦ ችግር ያለበት import፣ የተሰረዘ ኮርስ ወይም መመለስ የሚያስፈልግ contract migration። ይህ በቀጥታ የሚሰራውን ውሂብ ጎታ ይተካል፤ ስለዚህ መጀመሪያ ከታች ባለው ልምምድ ይሞክሩት።
- የዒላማ ጊዜውን ጉዳቱ ከመከሰቱ ትንሽ በፊት በUTC ይምረጡ፦
2026-09-24 09:30:00+00። የaudit መዝገቡ (/admin/audit) ብዙውን ጊዜ ያንን ጊዜ ያሳያል። - መጻፍ የሚያደርጉትን ሁሉ ያቁሙ፦
docker compose -f docker/compose.yaml stop web content worker scheduler collab - የተጎዳውን ክላስተር ያቆዩ፣ መመለሱ እስኪረጋገጥ ድረስ፦
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/ - ከዒላማው በፊት የተወሰደውን አዲሱን የመነሻ ምትኬ ወደ ውሂብ ድምጹ ያውጡና የተወሰነ መመለስ ይጠይቁ፦
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' - መመለስ፦ መደበኛውን ፋይል እንዳይቀይሩ፣ ከCompose override የመመለሻ ቅንብሮች ጋር Postgresን አንድ ጊዜ ያስነሱ፦
Override ሙሉውን command ይተካል፤ ስለዚህ ለመመለስ የሚያስፈልጉትን ሁለት ቅንብሮች እንደገና ያካትቱ፦# 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_connectionsከዋናው አገልጋይ እሴት ያነሰ መሆን የለበትም (ካልሆነ መመለሱ “insufficient parameter settings” በሚል ስህተት ይቆማል)፣ የተገጠመውንም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) እና የጠፋው ውሂብ መመለሱን። - ወደ መደበኛ አሠራር ይመለሱ፦
docker compose -f docker/compose.yaml up -d። ይህ Postgresን WAL ማስቀመጥ እንደገና በማብራት ያስነሳል፣ አዲስ WAL timelineም ይጀምራል። ወዲያውኑ አዲስ የመነሻ ምትኬ ይውሰዱ።
የፕሮጀክቱ quire ስም በእያንዳንዱ ድምጽ ስም ቅድሚያ ይጨመራል፤ docker volume ls ትክክለኛውን ስም ያሳያል።
የታቀደ የማረጋገጫ ልምምድ
backup-offsite በየQUIRE_BACKUP_DRILL_INTERVAL_HOURS (በነባሪ 168፣ በየሳምንቱ) የማረጋገጫ ልምምድ ያካሂዳል፤ ካልተሳካ በሚቀጥለው ዙር እንደገና ይሞክራል። ከአገልጋዩ ውጭ ያለውን አዲስ የመነሻ ምትኬና ከእሱ በኋላ ያሉትን WAL ክፍሎች ሁሉ ያመጣልና ይፈታቸዋል (ቁልፉ መክፈት እንደሚችልና ምንም እንዳልተቀየረ ያረጋግጣል)፤ እያንዳንዱን ፋይል ከmanifest ጋር ያነጻጽራል፣ archiveው የPostgres ውሂብ ማውጫ መሆኑንና ከምትኬው በኋላ በWAL ውስጥ ክፍተት አለመኖሩን ይፈትሻል። ሪፖርቱን reports/drill-<time>.json ስም በማድረግ ማከማቻውና የአገልግሎቱ ሎግ ውስጥ ይጽፋል፤ ካልተሳካ ፋይሉን ወይም መጀመሪያ የጎደለውን ክፍል ይጠቅሳል።
የመመለስ ልምምድ
ፈጽሞ ተመልሶ ያልተሞከረ ምትኬ ምትኬ አይደለም። ልምምዱ ከዒላማው በፊት የተወሰደውን አዲሱን ሙሉ የመነሻ ምትኬና WAL ማህደሩን ከቀጥታው Postgres ምንም የማይጋራ ጊዜያዊ Postgres ውስጥ ይመልሳል፣ ውጤቱንም ያረጋግጣል፦
docker/scripts/restore-drill.sh # to ninety minutes ago
docker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"የዒላማው ጊዜ UTC ሆኖ በትክክል በዚህ ቅርጽ መጻፍ አለበት። ከዚያ በፊት የተወሰደ መነሻ ምትኬና ከዚያ በኋላ የተቀመጠ WAL ያስፈልጋሉ፦ አዲስ ጭነት ላይ መነሻ ምትኬ ውሰዱ፣ ቀጣዩ የተቀመጠ ክፍል እስኪመጣ ይጠብቁ (ውሂብ እየተጻፈ ከሆነ ቢበዛ አንድ ደቂቃ)፣ ከዚያም ከምትኬው በኋላ ያለ ጊዜ ይምረጡ። ልምምዱን ለማካሄድ በአገልጋዩ Dockerና bash ብቻ ያስፈልጋሉ።
ከዚህ በታች ያሉት ደረጃዎች ሁሉ መሳካት አለባቸው፦
- መመለስ መቻል፦ ጊዜያዊው cluster WALን እስከ ዒላማው ድረስ በድጋሚ ተጫውቶ ይከፈታል።
- ሙሉነት፦ የእያንዳንዱን ሰንጠረዥ ረድፍ ብዛት ከቀጥታው ውሂብ ጎታ ጋር ያነጻጽራል (
tooling/restore-drill)። ቀጥታው ውሂብ ጎታ ከዒላማው በኋላ ስለተቀየረ፣ በሁለቱም አቅጣጫ ከ500 ረድፎች ወይም ከሰንጠረዡ መጠን አንድ አስረኛ ከሚበልጠው መጠን ጋር የሚመጣ ልዩነት ሊኖር ይችላል (ጽሁፎች እየጨመሩ ከሆነ የተመለሰው ይዘገያል፣ ስረዛዎች ካሉ ግን የተመለሰው ተጨማሪ ረድፎች ሊይዝ ይችላል)፤ ከዒላማው በኋላ የተፈጠረ partition የጠፋ ሰንጠረዥ አይደለም። በበዛ ጭነትQUIRE_DRILL_MAX_BEHINDእናQUIRE_DRILL_MAX_DRIFT_RATIOበመጠቀም የሚፈቀደውን ልዩነት ያስፋፉ። የጎደለ ወይም ባዶ ሰንጠረዥ ስህተት ነው። - ታማኝነት፦ በተመለሰው ቅጂ ላይ የaudit hash chain ያልተነካ መሆኑ ይረጋገጣል።
- ጥቅም ላይ መዋል፦ application role በrow-level security በኩል ማንበብ ይችላል።
- ጊዜ፦ ከመጀመሪያ እስከ ስኬት ያለው ጊዜን ከ
QUIRE_DRILL_RTO_SECONDS(በነባሪ 3600) ጋር ያነጻጽሩ።
ይህ ልምምድ በቀጥታ የሚሰራው ውሂብ ጎታ ወይም ድምጾቹ ላይ ምንም አይጽፍም፦ የምትኬና WAL ድምጾቹ ለማንበብ ብቻ ይገጠማሉ፣ ጊዜያዊው clusterም በመጨረሻ ይሰረዛል (ስኬትም ሆነ ስህተት)።
JSON ሪፖርት ለማስጻፍ QUIRE_DRILL_REPORTን ወደ ፋይል መንገድ ያቀናብሩ፣ ከDocker አገልጋዩም በሰዓት መርሐግብር ያስኪዱ፦
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በየወሩና ከእያንዳንዱ ማሻሻያ በፊት ያስኪዱት። ልምምዱ ካልተሳካ ማሻሻያው ይቆማል። በየሩብ ዓመቱ ይህን የስራ መመሪያ ያልጻፈ ሰው በተጠባባቂ አገልጋይ ላይ ይህን ሰነድ ብቻ በመጠቀም እውነተኛ የpoint-in-time መመለስ እንዲያካሂድ ያድርጉ።
ፋይሎች
የአካባቢ ፋይሎች files ድምጽ ውስጥ ናቸው። ከውሂብ ጎታው ጋር አንድ ጊዜ ምትኬ ይውሰዱና ሁለቱንም አብረው ይመልሱ፦
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 ቀን ያቆዩ፤ ከዚያ የፋይሎች point-in-time መመለስን bucketው ያስተናግዳል።