Preskoči na sadržaj

Sigurnosne kopije, oporavak na određeni trenutak i proba vraćanja

Izradite sigurnosnu kopiju Quirea, vratite ga na određeni trenutak i dokažite ispravnost probom vraćanja.

Prikaži kao Markdown

Dizajn je opisan u odjeljku 8 dokumenta docs/architecture/23-ops.md. Ovo je operativni priručnik za proizvod Docker Compose. Napisana je tako da je može slijediti i osoba koja je nije sastavila; ako je neki korak nejasan, to je nedostatak ovog dokumenta.

Što je zaštićeno i kako

Sredstvo Način zaštite Mjesto
Baza podataka WAL se kontinuirano arhivira, najviše svakih 60 sekundi, od prvog pokretanja Volumen pgwal
Baza podataka Osnovne kopije pomoću pg_basebackup, zadano svakodnevno (backup-scheduler) Volumen pgbackup
Baza podataka Šifrirane kopije osnovnih sigurnosnih kopija i WAL-a svakih pet minuta (backup-offsite) Odvojeno spremište koje navedete
Datoteke Volumen files. Kopirajte ga alatom za sigurnosne kopije poslužitelja ili koristite pohranu objekata s verzijama Volumen files
Tajne docker/.env, a osobito QUIRE_MASTER_KEY (i sve povučene vrijednosti QUIRE_MASTER_KEY_RETIRED koje se još koriste), QUIRE_BACKUP_ENCRYPTION_KEY i docker/secrets/audit-signing-key.pem Sačuvajte kopiju izvan ovog poslužitelja
Indeksi pretraživanja, predmemorije, izvedene datoteke Ne izrađuju se sigurnosne kopije; ponovno se stvaraju

Ciljevi su točka oporavka unutar 60 sekundi prije kvara i vraćanje u roku od 60 minuta za bazu veličine 500 GB.

Dvije su pogreške česte. Vraćena baza bez datoteka prikazuje neispravne stranice. Vraćena baza bez QUIRE_MASTER_KEY ne može dešifrirati vjerodajnice SSO-a, web-dojavnika i integracija koje sadrži; sve dok se rotacija glavnog ključa ne dovrši bez nerazriješenih stavki (key-rotation.md), to uključuje i povučene ključeve. Obje stavke dio su sigurnosne kopije.

Izrada sigurnosnih kopija

Osnovna sigurnosna kopija cijelog skupa:

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

Zadržava najnovijih QUIRE_BACKUP_KEEP osnovnih kopija (zadano 5) i briše WAL koji najstarijoj više nije potreban, pa arhiva ne može neograničeno rasti. Zakažite svakodnevno pokretanje naredbom cron ili mjeračem systemd na poslužitelju:

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

Ili prepustite zakazivanje samom skupu usluga: profil backup pokreće backup-scheduler, koji izrađuje osnovnu kopiju svakih QUIRE_BACKUP_INTERVAL_HOURS sati (zadano 24), te backup-offsite, opisan u nastavku.

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

Šifrirane kopije izvan poslužitelja

Oba su volumena na istom poslužitelju kao baza, a sigurnosna kopija na stroju koji je otkazao nije sigurnosna kopija. backup-offsite kopira svaku osnovnu kopiju i svaki arhivirani segment WAL-a kroz priključak za pohranu u odvojeno, šifrirano spremište te ondje primjenjuje pravila zadržavanja:

  • Šifriranje. AES-256-GCM s ključem QUIRE_BACKUP_ENCRYPTION_KEY (ili datotekom navedenom u QUIRE_BACKUP_ENCRYPTION_KEY_FILE): 32 bajta, generirana naredbom openssl rand -hex 32. Svaka datoteka ima vlastiti nonce i oznaku provjere autentičnosti, pa se kopija ne može pročitati bez ključa i otkrivaju se sve njezine izmjene. Ključ čuvajte uz QUIRE_MASTER_KEY, podalje od ovog poslužitelja i spremišta sigurnosnih kopija. Bez ključa nema vraćanja.
  • Mjesto. QUIRE_BACKUP_STORAGE_DRIVER može biti s3, azure ili local (udaljeni disk priključen na QUIRE_BACKUP_STORAGE_ROOT). Postavke su jednake onima za pohranu datoteka uz prefiks QUIRE_BACKUP_: QUIRE_BACKUP_S3_ENDPOINT, QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID i druge. Koristite drugi spremnik i, po mogućnosti, drugi račun od onoga za datoteke, s vjerodajnicama koje mogu zapisivati, ali ne i brisati, ako pružatelj to podržava.
  • Zadržavanje. Zadržavaju se najnovijih QUIRE_BACKUP_OFFSITE_KEEP osnovnih kopija (zadano je QUIRE_BACKUP_KEEP, a ako ni ono nije postavljeno, vrijednost je 7) te WAL potreban najstarijoj od njih; stariji skupovi i segmenti brišu se iz spremišta.
  • Učestalost. Svakih QUIRE_BACKUP_SHIP_INTERVAL_SECONDS sekundi (zadano 300). Slanje je idempotentno: već pohranjene stavke preskaču se, a osnovna kopija smatra se pohranjenom tek nakon što se kao posljednji korak zapiše njezin manifest.

Ista se naredba može pokrenuti ručno:

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

Za vraćanje na novi poslužitelj najprije preuzmite skup, a zatim slijedite korake u nastavku tako da preuzeti direktorij zamijeni volumen pgbackup, a preuzeti wal-archive volumen pgwal:

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

Vraćanje na određeni trenutak

Primijenite postupak nakon gubitka podataka: neispravnog uvoza, izbrisanog kolegija ili migracije uklanjanja koju morate poništiti. Njime se zamjenjuje aktivna baza, pa ga najprije uvježbajte probom u nastavku.

  1. Odaberite ciljno vrijeme u UTC-u, neposredno prije oštećenja: 2026-09-24 09:30:00+00. Trenutak je obično vidljiv u zapisu nadzora (/admin/audit).
  2. Zaustavite sve procese koji zapisuju: docker compose -f docker/compose.yaml stop web content worker scheduler collab
  3. Zadržite oštećeni skup dok se ne provjeri vraćena baza:
    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. Raspakirajte najnoviju osnovnu sigurnosnu kopiju nastalu prije ciljnog vremena u volumen podataka i zatražite oporavak do odabrane točke:
    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. Provedite oporavak: pokrenite Postgres jednom s postavkama oporavka iz dodatne Compose datoteke kako biste ostavili uobičajenu datoteku nepromijenjenom:
    # 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]
    Dodatna datoteka zamjenjuje cijelu naredbu, pa ponavlja obje postavke potrebne za oporavak: max_connections mora biti barem jednak vrijednosti na primarnoj bazi (inače oporavak završava uz poruku „insufficient parameter settings”), a uključena mora biti i priključena datoteka 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"
  6. Provjerite bazu prije nego što ikoga pustite u nju: provjerite lanac nadzora naredbom docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts i potvrdite da su izgubljeni podaci vraćeni.
  7. Vratite uobičajeni rad: docker compose -f docker/compose.yaml up -d. Postgres će se ponovno pokrenuti s uključenim arhiviranjem i započet će nova vremenska linija WAL-a. Odmah izradite novu osnovnu sigurnosnu kopiju.

Naziv projekta quire prefiks je svakog volumena; točne nazive prikazuje docker volume ls.

Zakazana proba provjere

backup-offsite također provodi probu svakih QUIRE_BACKUP_DRILL_INTERVAL_HOURS sati (zadano 168, odnosno jednom tjedno), a neuspješnu ponavlja već u sljedećem ciklusu. Dohvaća najnoviju osnovnu sigurnosnu kopiju izvan poslužitelja i sve WAL segmente nakon nje, dešifrira ih (čime potvrđuje da ih ključ još može otvoriti i da nisu izmijenjeni), uspoređuje svaku datoteku s njezinim manifestom, provjerava da je arhiva direktorij podataka Postgresa te potvrđuje da u WAL-u nakon sigurnosne kopije nema prekida. Izvješće zapisuje u spremište kao reports/drill-<time>.json i u zapis usluge; neuspješna proba navodi datoteku ili prvi nedostajući segment.

Proba vraćanja

Sigurnosna kopija koja nikad nije vraćena nije provjerena sigurnosna kopija. Ova proba vraća najnoviju potpunu osnovnu sigurnosnu kopiju nastalu prije ciljnog vremena, zajedno s arhivom WAL-a, u pomoćnu bazu Postgresa koja ne dijeli ništa s aktivnom bazom te provjerava rezultat:

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

Ciljno vrijeme mora biti UTC i zapisano upravo u tom obliku. Potrebna je osnovna sigurnosna kopija starija od cilja i arhivirani WAL nakon njega: na novoj instalaciji izradite osnovnu kopiju i pričekajte sljedeći arhivirani segment (najviše minutu uz zapise) prije nego što odaberete kasnije ciljno vrijeme. Proba na poslužitelju zahtijeva samo Docker i bash, ništa drugo.

Proba završava neuspjehom u svakom od sljedećih slučajeva:

  1. Mogućnost oporavka: pomoćni se skup vrati do ciljnog trenutka i otvori.
  2. Cjelovitost: usporede se brojevi redaka svih tablica sa živom bazom (tooling/restore-drill). Aktivna baza odmaknula se od ciljnog vremena, pa se tablica može razlikovati u oba smjera za veću od vrijednosti 500 redaka i jedne desetine njezine veličine (zapisi mogu značiti da vraćena baza zaostaje, a brisanja da ih ima više); particija stvorena nakon ciljnog vremena ne smatra se izgubljenom tablicom. Na aktivnijoj instalaciji dopušteno odstupanje povećajte postavkama QUIRE_DRILL_MAX_BEHIND i QUIRE_DRILL_MAX_DRIFT_RATIO. Nedostajuća ili ispražnjena tablica uzrokuje neuspjeh.
  3. Cjelovitost podataka: provjerava se lanac sažetaka nadzora na vraćenoj kopiji.
  4. Upotrebljivost: uloga aplikacije može čitati podatke uz sigurnost na razini retka.
  5. Vrijeme: trajanje od početka do uspješnog završetka uspoređuje se s QUIRE_DRILL_RTO_SECONDS (zadano 3600).

Proba nikad ne zapisuje u aktivnu bazu ni njezine volumene: volumeni sigurnosnih kopija i WAL-a priključuju se samo za čitanje, a pomoćni se skup uklanja na kraju, bilo da je proba uspjela ili nije.

Postavite QUIRE_DRILL_REPORT na putanju za zapisivanje JSON izvješća i pri uspjehu i pri neuspjehu, pa pokrenite probu po rasporedu s domaćina Dockera:

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

Pokrećite je mjesečno i prije svake nadogradnje. Neuspjela proba zaustavlja nadogradnju. Jednom tromjesečno neka stvarni oporavak na određeni trenutak na pomoćnom poslužitelju provede osoba koja nije napisala ovaj priručnik, služeći se samo ovim dokumentom.

Datoteke

Lokalne se datoteke nalaze u volumenu files. Izradite njihovu sigurnosnu kopiju istodobno s kopijom baze i zajedno ih vratite:

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 .

Uz pohranu objekata uključite izradu verzija spremnika i zadržite zastarjele verzije 35 dana; vraćanje datoteka na određeni trenutak tada se obavlja izvornim mehanizmom spremnika.

Navigacija

Upišite za pretraživanje…

↑↓ kretanje↵ odabirEsc zatvaranje