---
title: "Varundamine, ajahetke taastamine ja taastamiskatse"
description: "Varunda Quire, taasta see ajahetke seisundisse ja tõesta taastatavust katsega."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/et/llms.txt
> Use this file to discover all available pages before exploring further.

# Varundamine, ajahetke taastamine ja taastamiskatse

<span id="backup-point-in-time-recovery-and-the-restore-drill"></span>

Arhitektuur on kirjeldatud dokumendi `docs/architecture/23-ops.md` jaotises 8.
See on Docker Compose'i toote juhend. Juhend on kirjutatud inimesele, kes seda
ise ei koostanud; iga ebaselge samm on puudus dokumendis.

## Mis on kaitstud ja kuidas <!--quire:what-is-protected-and-how-->

| Vara | Kuidas | Kus |
| --- | --- | --- |
| Andmebaas | WAL arhiveeritakse pidevalt, kuni 60-sekundiliste vahedega, esimesest käivitusest alates | `pgwal` köide |
| Andmebaas | Põhi-varukoopiad `pg_basebackup`-iga, vaikimisi kord päevas (`backup-scheduler`) | `pgbackup` köide |
| Andmebaas | Põhi-varukoopiate ja WAL-i krüptitud koopiad iga viie minuti järel (`backup-offsite`) | Sinu määratud eraldi hoidla |
| Failid | `files`-köide. Kopeeri see hosti varundustööriistaga või kasuta versioonitud objektisalvestust | `files`-köide |
| Saladused | `docker/.env`, eriti `QUIRE_MASTER_KEY` (ja kasutusel olev `QUIRE_MASTER_KEY_RETIRED`), `QUIRE_BACKUP_ENCRYPTION_KEY` ning `docker/secrets/audit-signing-key.pem` | Hoia koopiat hostist eemal |
| Otsinguindeksid, vahemälud, teisendatud failid | Ei varundata; ehitatakse uuesti | |

Eesmärgid: rikke korral taastamispunkt kuni 60 sekundi kaugusel ning 500 GB
andmebaasi taastamine kuni 60 minutiga.

Kaks viga korduvad sageli. Andmebaasi taastamisel **ilma failideta** kuvatakse
katkiseid lehti. Andmebaas, mis taastati **ilma `QUIRE_MASTER_KEY`-ta**, ei saa
dekrüptida salvestatud SSO, veebikonksu ja integratsiooni mandaate; kuni peavõtme
vahetamine on lõpetatud nii, et midagi pole lahendamata
([key-rotation.md](/et/ops/key-rotation/)), kehtib see ka pensionile jäetud võtmete kohta.
Varunda mõlemad.

## Varundamine <!--quire:taking-backups-->

Tee kogu klastrist põhi-varukoopia:

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

Alles jäetakse uusimad `QUIRE_BACKUP_KEEP` varukoopiad (vaikimisi 5) ning
kustutatakse vanimale enam mittevajalik WAL, et arhiiv piiramatult ei kasvaks.
Ajasta hostis igapäevane käivitus croni või systemd taimeriga:

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

Või lase virnal ajastada: `backup`-profiil käivitab `backup-scheduler`i, mis teeb
põhi-varukoopia iga `QUIRE_BACKUP_INTERVAL_HOURS` järel (vaikimisi 24) ning
järgmises jaotises kirjeldatud `backup-offsite`i.

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

## Krüptitud koopiad väljaspool hosti <!--quire:encrypted-off-host-copies-->

Mõlemad köited asuvad andmebaasiga samas hostis, seega rikkis masina varukoopia
pole päris varukoopia. `backup-offsite` kopeerib iga põhi-varukoopia ja arhiveeritud
WAL-i segmendi üle salvestuspordi krüptitult eraldi hoidlasse ning rakendab
säilitusreeglit:

- **Krüptimine.** AES-256-GCM võtmega `QUIRE_BACKUP_ENCRYPTION_KEY` või faili
  `QUIRE_BACKUP_ENCRYPTION_KEY_FILE` abil: 32 baiti, loodud käsuga
  `openssl rand -hex 32`. Igal failil on oma nonce ja autentimismärgend, seega
  pole koopiat võtmeta võimalik lugeda ning muudatus tuvastatakse. Hoia võtit koos
  `QUIRE_MASTER_KEY`-ga sellest hostist ja varundushoidlast eraldi. Võtmeta ei saa
  taastada.
- **Asukoht.** `QUIRE_BACKUP_STORAGE_DRIVER` on `s3`, `azure` või `local`
  (ühendatud kaugketas aadressil `QUIRE_BACKUP_STORAGE_ROOT`). Seaded on samad mis
  failisalvestusel, kuid eesliitega `QUIRE_BACKUP_`: `QUIRE_BACKUP_S3_ENDPOINT`,
  `QUIRE_BACKUP_S3_BUCKET`, `QUIRE_BACKUP_S3_ACCESS_KEY_ID` jne. Kasuta failidest
  eraldi ämbrit ja võimalusel eraldi kontot; luba kirjutamine, kuid võimalusel
  keela pakkuja seadetes kustutamine.
- **Säilitamine.** Uusimad `QUIRE_BACKUP_OFFSITE_KEEP` põhi-varukoopiad (vaikimisi
  `QUIRE_BACKUP_KEEP`, muidu 7) ja vanimale neist vajalik WAL; vanemad kogumid
  ja segmendid kustutatakse hoidlast.
- **Millal.** Iga `QUIRE_BACKUP_SHIP_INTERVAL_SECONDS` järel (vaikimisi 300).
  Edastus on korduskindel: juba salvestatud failid jäetakse vahele ning
  põhi-varukoopia loetakse talletatuks alles siis, kui manifest on viimaks kirjutatud.

Käsitsi käitatakse sama käsku:

```sh
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
```

Uues hostis taastamiseks too varukoopiate komplekt esmalt tagasi ja järgi allpool
olevaid samme; kasuta toodud kataloogi `pgbackup`-köite ning toodud `wal-archive`
kausta `pgwal`-köite asemel:

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

## Taastamine ajahetke seisundisse <!--quire:restoring-to-a-point-in-time-->

Kasuta seda andmekao järel: vigane import, kustutatud kursus või tagasivõtmist
vajav andmebaasimuudatus. See asendab aktiivse andmebaasi, seega harjuta esmalt
allpool oleva taastamiskatsega.

1. **Vali sihtaeg** UTC-s, vahetult enne kahju:
   `2026-09-24 09:30:00+00`. Tavaliselt näitab hetke auditi logi
   (`/admin/audit`).
2. **Peata kõik kirjutavad teenused**:
   `docker compose -f docker/compose.yaml stop web content worker scheduler collab`
3. **Hoia kahjustatud klaster alles**, kuni taastamine on kontrollitud:
   ```sh
   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. **Paki sihtajast vanim uusim põhi-varukoopia** andmeköitesse lahti ja palu
   teha sihitud taastamine:
   ```sh
   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. **Taasta**: käivita Postgres üks kord taasteseadetega, kasutades
   ülekirjutusfaili, et tavapärane fail jääks muutmata:
   ```yaml
   # 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]
   ```
   Ülekirjutus asendab kogu käsu, nii et taasteks tuleb lisada kaks vajalikku
   seadet: `max_connections` peab olema vähemalt esmase väärtus (muidu katkeb
   taastamine veaga "insufficient parameter settings") ning määrata tuleb
   ühendatud `pg_hba.conf`.
   ```sh
   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. **Kontrolli** enne kellegi sisselaskmist auditi ahelat
   (`docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts`)
   ning veendu, et kadunud andmed on tagasi.
7. **Taastu tavakäiduks**: `docker compose -f docker/compose.yaml up -d`.
   Postgres käivitub arhiveerimisega uuesti ja algab uus WAL-i ajajoon. Tee kohe
   värske põhi-varukoopia.

Projektinimi `quire` lisatakse iga köite ette; täpseid nimesid näitab
`docker volume ls`.

## Ajastatud kontrollkatse <!--quire:the-scheduled-verification-drill-->

`backup-offsite` käivitab katse iga `QUIRE_BACKUP_DRILL_INTERVAL_HOURS` järel
(vaikimisi 168 tundi ehk kord nädalas) ning pärast nurjumist kohe järgmisel
käivitusel uuesti. See hangib uusima hostivälise põhi-varukoopia ja sellele
järgnevad WAL-i segmendid, dekrüptib need (kontrollides, et võti neid avab ja
neid pole muudetud), võrdleb faile manifestiga, kontrollib arhiivi kui Postgresi
andmekataloogi ning veendub, et varukoopiale järgnev WAL on terviklik. Aruanne
salvestatakse hoidlas nimega `reports/drill-<time>.json` ja teenuse logis; nurjunud
katse nimetab faili või esimest puuduvat segmenti.

## Taastamiskatse <!--quire:the-restore-drill-->

Varukoopia, mida pole kunagi taastatud, pole tõestatud varukoopia. Katse taastab
uusima täieliku sihtajale eelnenud põhi-varukoopia koos WAL-arhiiviga ajutisse
Postgresesse, mis ei jaga aktiivsega midagi, ning kontrollib tulemust:

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

Sihtaeg peab olema täpselt sellises UTC-vormingus. Vajalik on sellest varasem
põhi-varukoopia ja sellele järgnev arhiveeritud WAL: uuel paigaldusel tee
põhi-varukoopia ja oota enne hilisema sihtaja valimist järgmist arhiveeritud
segmenti (kirjutuste korral kõige rohkem minut). Katseks on hostis vaja üksnes
Dockerit ja bashi.

Iga samm võib katse nurjata:

1. **Taastatavus**: ajutine klaster taasesitab andmed sihtajani ja avaneb.
2. **Täielikkus**: iga tabeli ridade arvu võrreldakse aktiivse andmebaasiga
   (`tooling/restore-drill`). Aktiivne andmebaas on sihtajast edasi liikunud,
   seega võib tabelite ridade arv mõlemas suunas erineda suuremal väärtusel kahest:
   500 rida või kümnendik tabeli suurusest (kirjutused tekitavad mahajäämust,
   kustutused jätavad taastatud koopias rohkem ridu); pärast sihtaega loodud
   sektsioon pole kadunud tabel. Suurema liiklusega paigaldises suurenda lubatud
   vahet muutujatega `QUIRE_DRILL_MAX_BEHIND` ja `QUIRE_DRILL_MAX_DRIFT_RATIO`.
   Puuduv või tühjaks jäänud tabel tähendab nurjumist.
3. **Terviklus**: taastatud koopias kontrollitakse auditi räsiahelat.
4. **Kasutatavus**: rakenduseroll saab lugeda rea-taseme turbe kaudu.
5. **Aeg**: käivitamisest eduni kuluv aeg jääb `QUIRE_DRILL_RTO_SECONDS`
   piiridesse (vaikimisi 3600).

Katse ei kirjuta kunagi aktiivsesse andmebaasi ega selle köidetesse: varukoopia-
ja WAL-köited ühendatakse kirjutuskaitstult ning ajutine klaster eemaldatakse
lõpus nii edu kui ka nurjumise korral.

Määra `QUIRE_DRILL_REPORT` aruandefaili asukohaks, et JSON kirjutataks nii edu
kui ka nurjumise korral, ning ajasta hosti Dockeris:

```cron
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
```

Käivita seda iga kuu ja enne iga uuendust. Nurjunud katse takistab uuendamist.
Kord kvartalis palu inimesel, kes juhendit ei kirjutanud, teha päris ajahetke
taastamine varuhostis ainult selle dokumendi põhjal.

## Failid <!--quire:files-->

Kohalikud failid paiknevad `files`-köites. Varunda need andmebaasiga samal ajal
ning taasta mõlemad koos:

```sh
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 .
```

Objektisalvestuse korral lülita sisse ämbri versioonimine ja säilita vanu
versioone 35 päeva; siis haldab failide ajahetke taastamist ämber ise.

Source: https://docs.quirelms.com/et/ops/backup-restore/index.mdx
