---
title: "Sigurnosne kopije, oporavak na određeni trenutak i proba vraćanja"
description: "Izradite sigurnosnu kopiju Quirea, vratite ga na određeni trenutak i dokažite ispravnost probom vraćanja."
image: "https://docs.quirelms.com/og.png"
---

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

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

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

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 <!--quire:what-is-protected-and-how-->

| 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](/hr/ops/key-rotation/)), to uključuje i povučene ključeve. Obje
stavke dio su sigurnosne kopije.

## Izrada sigurnosnih kopija <!--quire:taking-backups-->

Osnovna sigurnosna kopija cijelog skupa:

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

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

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

## Šifrirane kopije izvan poslužitelja <!--quire:encrypted-off-host-copies-->

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:

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

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

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

## Vraćanje na određeni trenutak <!--quire:restoring-to-a-point-in-time-->

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:
   ```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. **Raspakirajte najnoviju osnovnu sigurnosnu kopiju** nastalu prije ciljnog
   vremena u volumen podataka i zatražite oporavak do odabrane točke:
   ```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. **Provedite oporavak:** pokrenite Postgres jednom s postavkama oporavka iz
   dodatne Compose datoteke kako biste ostavili uobičajenu datoteku
   nepromijenjenom:
   ```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]
   ```
   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`.
   ```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. **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 <!--quire:the-scheduled-verification-drill-->

`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 <!--quire:the-restore-drill-->

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:

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

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

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 <!--quire:files-->

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

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

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.

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