Ugrás a tartalomhoz

Biztonsági mentés, időpontra történő helyreállítás és visszaállítási próba

A Quire mentése, visszaállítása egy adott időpontra, és ennek igazolása visszaállítási próbával.

A kialakítást a docs/architecture/23-ops.md 8. szakasza írja le. Ez a Docker Compose-termék eljárásrendje. Úgy készült, hogy a műveletet olyan ember is végrehajthassa, aki nem írta; ha egy lépés nem világos, az a dokumentum hibája.

Mit védünk, és hogyan

Eszköz Módszer Hely
Adatbázis Folyamatos WAL-archiválás, legfeljebb 60 másodpercenként, az első indítástól pgwal kötet
Adatbázis Alapmentések pg_basebackup használatával, alapértelmezés szerint naponta (backup-scheduler) pgbackup kötet
Adatbázis Az alapmentések és WAL titkosított másolata ötpercenként (backup-offsite) Külön, Ön által megadott tároló
Fájlok A files kötet. Másolja a host mentőeszközével, vagy használjon verziózott objektumtárolót files kötet
Titkok docker/.env, különösen az esetleg használt QUIRE_MASTER_KEY és QUIRE_MASTER_KEY_RETIRED, a QUIRE_BACKUP_ENCRYPTION_KEY és a docker/secrets/audit-signing-key.pem A hoston kívül őrizzen meg másolatot
Keresési indexek, gyorsítótárak, átalakított változatok Nincs mentés; újraépülnek

Cél: a hiba előtti 60 másodpercen belüli helyreállítási pont, valamint 500 GB-os adatbázis visszaállítása 60 percen belül.

Két hiba gyakori. A fájljai nélkül visszaállított adatbázis hibás oldalakat eredményez. A QUIRE_MASTER_KEY nélkül visszaállított adatbázis nem tudja visszafejteni a benne lévő SSO-, webhook- és integrációs hitelesítő adatokat; amíg a kulcscsere minden megoldatlan elemtől mentesen be nem fejeződik (key-rotation.md), a visszavont kulcsokra is szükség van. Mindegyik a mentés részét képezi.

Biztonsági mentések készítése

Teljes fürt alapmentése:

docker compose -f docker/compose.yaml --profile backup run --rm backup

A legújabb QUIRE_BACKUP_KEEP számú alapmentést őrzi meg (alapértelmezés szerint 5), és törli azt a régi WAL-t, amelyre már nincs szükség, így az archívum nem nő korlátlanul. A hoston állítson be napi cron-feladatot vagy systemd időzítőt:

15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1

Vagy bízza az ütemezést a stackre: a backup profil elindítja a backup-scheduler szolgáltatást, amely minden QUIRE_BACKUP_INTERVAL_HOURS időközönként készít alapmentést (alapérték 24), valamint a következőként ismertetett backup-offsite szolgáltatást.

docker compose -f docker/compose.yaml --profile backup up -d

Titkosított másolatok külső hoston

Mindkét kötet ugyanazon a hoston található, mint az adatbázis; a meghibásodott gépen lévő mentés nem mentés. A backup-offsite minden alapmentést és archivált WAL-szegmenst titkosít, a storage-rétegen át külön tárolóba másol, majd megőrzési szabály szerint ott tárolja:

  • Titkosítás. AES-256-GCM a QUIRE_BACKUP_ENCRYPTION_KEY beállítással vagy a QUIRE_BACKUP_ENCRYPTION_KEY_FILE által megadott fájllal: 32 bájt, előállítása openssl rand -hex 32 paranccsal. Minden fájlnak külön nonce-a és hitelesítési címkéje van, ezért kulcs nélkül nem olvasható, módosítása pedig észlelhető. A kulcsot a QUIRE_MASTER_KEY mellett, a hosttól és mentéstárolótól külön őrizze. Kulcs nélkül nincs visszaállítás.
  • Hely. A QUIRE_BACKUP_STORAGE_DRIVER értéke s3, azure vagy local (csatolt távoli lemez a QUIRE_BACKUP_STORAGE_ROOT alatt). Használja a fájltárolás beállításait QUIRE_BACKUP_ előtaggal: QUIRE_BACKUP_S3_ENDPOINT, QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID stb. Másik bucketet, lehetőleg másik fiókot használjon, és ha a szolgáltató engedi, olyan hitelesítő adatokat, amelyek írhatnak, de törölni nem tudnak.
  • Megőrzés. A legújabb QUIRE_BACKUP_OFFSITE_KEEP számú alapmentés (alapértelmezés a QUIRE_BACKUP_KEEP, ennek hiányában 7) és a legrégebbi mentéshez szükséges WAL marad meg; a régebbi készleteket és szegmenseket törli a tárolóból.
  • Ütemezés. Minden QUIRE_BACKUP_SHIP_INTERVAL_SECONDS másodpercben (alapérték 300). A küldés idempotens: a már tárolt elemek kimaradnak, az alapmentés pedig csak a jegyzék utolsóként történő megírása után számít tároltnak.

Ugyanez a parancs kézzel is futtatható:

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

Új hostra történő visszaállításhoz előbb töltsön vissza egy készletet, majd az alábbi lépéseknél a letöltött könyvtárat használja a pgbackup kötet, a letöltött wal-archive könyvtárat pedig a pgwal helyett:

bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restore

Visszaállítás egy adott időpontra

Adatvesztés után használja, például hibás import, törölt kurzus vagy visszavonandó szerződésmigráció esetén. Lecseréli az éles adatbázist, ezért előbb gyakorolja a lenti próbával.

  1. Válassza ki a célidőpontot UTC-ben, közvetlenül a káresemény előtt: 2026-09-24 09:30:00+00. Az auditnapló (/admin/audit) rendszerint mutatja az időpontot.
  2. Állítson le mindent, ami ír: docker compose -f docker/compose.yaml stop web content worker scheduler collab
  3. Tartsa meg a sérült fürtöt a visszaállítás ellenőrzéséig:
    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/
  4. Csomagolja ki a célidőpontnál korábbi legújabb alapmentést az adatkönyvtárba, és kérjen célzott helyreállítást:
    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'
  5. Helyreállítás: indítsa el egyszer a Postgrest a helyreállítási beállításokkal, Compose felülíró fájlból, így a normál fájl érintetlen marad:
    # 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]
    A felülírás lecseréli a teljes parancsot, ezért ismét tartalmaznia kell a helyreállításhoz szükséges két beállítást: a max_connections értéke ne legyen kisebb az elsődlegesénél (különben a helyreállítás „insufficient parameter settings” hibával leáll), és adja meg a csatolt pg_hba.conf fájlt is.
    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"
  6. Ellenőrizze, mielőtt bárkit visszaenged: auditlánc (docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts) és hogy az elveszett adat visszatért-e.
  7. Térjen vissza a normál működéshez: docker compose -f docker/compose.yaml up -d. Ez archiválással indítja újra a Postgrest, új WAL-idővonal kezdődik. Azonnal készítsen új alapmentést.

A quire projektnevet minden kötet előtagként használja; a docker volume ls megmutatja a pontos neveket.

Ütemezett ellenőrzési próba

A backup-offsite minden QUIRE_BACKUP_DRILL_INTERVAL_HOURS időközönként (alapérték 168, hetente) próbát is futtat, sikertelenség után pedig a következő futásnál újrapróbálja. Letölti a legújabb külső alapmentést és az összes utána következő WAL-szegmenst, mindegyiket visszafejti (ezzel igazolja, hogy a kulcs működik, és semmi sem módosult), összeveti a fájlokat a jegyzékükkel, ellenőrzi, hogy az archívum Postgres-adatkönyvtár, és hogy az alapmentéstől nincs hiány a WAL-ban. A jelentés reports/drill-<time>.json néven kerül a tárolóba és a szolgáltatás naplójába; hiba esetén megnevezi a fájlt vagy első hiányzó szegmenst.

Visszaállítási próba

A még soha vissza nem állított mentés nem valódi mentés. A próba az éles adatbázistól teljesen különálló, ideiglenes Postgresbe állítja vissza a célidőpont előtti legújabb teljes alapmentést és a WAL-archívumot, majd igazolja az eredményt:

docker/scripts/restore-drill.sh                                  # to ninety minutes ago
docker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"

A célidőpont UTC, pontosan ebben a formában. Kell hozzá korábbi alapmentés és az utána archivált WAL: új telepítésnél készítsen alapmentést, és várja meg a következő archivált szegmenst (írások mellett legfeljebb egy perc), mielőtt a mentés utáni időpontot választja. A próbához csak Docker és bash kell a hoston.

Bármelyik lépés sikertelensége megbuktatja a próbát:

  1. Helyreállíthatóság: az ideiglenes fürt visszajátszik a célidőpontig, és megnyílik.
  2. Teljesség: minden tábla sorszáma a jelenlegi adatbázishoz képest (tooling/restore-drill). Az élő adatbázis a cél óta változott, ezért egy tábla mindkét irányban eltérhet 500 sor vagy méretének egytizede közül a nagyobb értékkel (az írások miatt a visszaállítás lemarad, törlésnél több sora lehet); a cél után létrejött partíció nem számít hiányzó táblának. Forgalmasabb telepítésen bővítse az engedményt a QUIRE_DRILL_MAX_BEHIND és QUIRE_DRILL_MAX_DRIFT_RATIO értékeivel. Hiányzó vagy kiürült tábla esetén a próba megbukik.
  3. Sértetlenség: az audit hash-lánc ellenőrzése sikerül a visszaállított példányon.
  4. Használhatóság: az alkalmazásszerepkör row-level security mellett olvas.
  5. Idő: az indulástól a sikerig eltelt idő a QUIRE_DRILL_RTO_SECONDS értékén belül van (alapérték 3600).

Soha nem ír az éles adatbázisba vagy köteteibe: a mentési és WAL-kötetek csak olvashatóan csatolódnak, az ideiglenes fürt pedig a végén törlődik, akár sikerült, akár nem.

Állítsa a QUIRE_DRILL_REPORT értékét egy útvonalra, ha siker vagy hiba esetén is JSON-jelentést szeretne, majd ütemezze a futtatást a Docker-hoston:

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

Futtassa havonta és minden frissítés előtt. Sikertelen próba esetén ne frissítsen. Negyedévente kérjen meg valakit, aki nem írta ezt az eljárást, hogy kizárólag e dokumentum alapján végezzen valódi, időpontra történő visszaállítást egy tartalék hoston.

Fájlok

A helyi fájlok a files kötetben találhatók. Ugyanakkor készítsen róluk mentést az adatbázissal, és állítsa vissza őket együtt:

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 .

Objektumtárolás esetén kapcsolja be a bucket verziózását, és 35 napig őrizze meg a nem aktuális verziókat; így a fájlok időpontra történő visszaállítását maga a bucket biztosítja.

Navigáció

Írjon a kereséshez…

↑↓ navigálás↵ kiválasztásEsc bezárás