---
title: "Sekurkopioj, restarigo al momento kaj restariga provo"
description: "Sekurkopii Quire, restarigi al momento kaj pruvi tion per restariga provo."
image: "https://docs.quirelms.com/og.png"
---

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

# Sekurkopioj, restarigo al momento kaj restariga provo

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

La dezajno estas en sekcio 8 de `docs/architecture/23-ops.md`. Jen la
runbook por la produkto Docker Compose. Ĝi estas verkita por sekvado de iu
neverkinta ĝin; se paŝo estas neklara, tio estas difekto de ĉi tiu dokumento.

## Kio estas protektata kaj kiel <!--quire:what-is-protected-and-how-->

| Aktivo | Kiel | Kie |
| --- | --- | --- |
| Datumbazo | WAL arkivata senĉese, maksimume po 60 sekundoj, ekde unua ekfunkciigo | Volumeno `pgwal` |
| Datumbazo | Bazaj sekurkopioj per `pg_basebackup`, defaŭlte ĉiutage (`backup-scheduler`) | Volumeno `pgbackup` |
| Datumbazo | Ĉifritaj kopioj de bazaj sekurkopioj kaj WAL ĉiun kvinan minuton (`backup-offsite`) | Aparta konservejo nomita de vi |
| Dosieroj | Volumeno `files`. Kopiu per gastiganta sekurkopiilo aŭ uzu versionitan objektostokadon | Volumeno `files` |
| Sekretoj | `docker/.env`, precipe `QUIRE_MASTER_KEY` (kaj ĉiu ankoraŭ uzata `QUIRE_MASTER_KEY_RETIRED`), `QUIRE_BACKUP_ENCRYPTION_KEY` kaj `docker/secrets/audit-signing-key.pem` | Konservu kopion ekster ĉi tiu gastiganto |
| Serĉindeksoj, kaŝmemoroj, derivaĵoj | Ne sekurkopiataj; rekonstrueblaj | |

Celoj: reakira punkto ene de 60 sekundoj antaŭ paneo kaj restarigo
ene de 60 minutoj por 500 GB-datumbazo.

Du eraroj oftas. Datumbazo restarigita **sen siaj dosieroj** montras
rompitajn paĝojn. Datumbazo restarigita **sen `QUIRE_MASTER_KEY`** ne povas
malĉifri SSO-, webhook- kaj integrigajn legitimilojn; ĝis rotacio de ĉefa
ŝlosilo finiĝas sen nesolvitaj valoroj ([key-rotation.md](/eo/ops/key-rotation/)),
tio inkluzivas retiriĝintajn ŝlosilojn. Ambaŭ estas parto de sekurkopio.

## Fari sekurkopiojn <!--quire:taking-backups-->

Baza sekurkopio de tuta grapolo:

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

Ĝi konservas plej novajn `QUIRE_BACKUP_KEEP` bazajn sekurkopiojn (defaŭlte 5) kaj fortranĉas
WAL, kiun la plej malnova ne plu bezonas, por ke arkivo kresku senlime.
Planigu ĉiutage per cron aŭ systemd-tempigilo ĉe gastiganto:

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

Aŭ lasu stakon planigi ĝin: profilo `backup` rulas `backup-scheduler`,
kiu faras bazan sekurkopion ĉiun `QUIRE_BACKUP_INTERVAL_HOURS` (defaŭlte 24),
kaj `backup-offsite`, priskribitan poste.

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

## Ĉifritaj kopioj ekster gastiganto <!--quire:encrypted-off-host-copies-->

Ambaŭ volumoj troviĝas ĉe sama gastiganto kiel datumbazo, kaj sekurkopio en
paneinta maŝino ne estas sekurkopio. `backup-offsite` kopias ĉiun bazan sekurkopion
kaj ĉiun arkivitan WAL-segmenton al aparta konservejo per stokada pordo,
ĉifras ilin kaj konservas laŭ reteno:

- **Ĉifrado.** AES-256-GCM per `QUIRE_BACKUP_ENCRYPTION_KEY` (aŭ dosiero
  nomita de `QUIRE_BACKUP_ENCRYPTION_KEY_FILE`): 32 bajtoj el
  `openssl rand -hex 32`. Ĉiu dosiero havas propran nonce-on kaj aŭtentikigan
  etikedon, do kopio estas nelegebla sen ŝlosilo kaj ĉiu ŝanĝo estas
  detektata. Konservu ŝlosilon kun `QUIRE_MASTER_KEY`, for de ĉi tiu gastiganto kaj sekurkopiejo. Sen ŝlosilo, restarigo ne eblas.
- **Loko.** `QUIRE_BACKUP_STORAGE_DRIVER` estas `s3`, `azure` aŭ `local` (muntita ekstera disko ĉe `QUIRE_BACKUP_STORAGE_ROOT`). Agordoj estas la samaj kiel por dosierstokado kun prefikso `QUIRE_BACKUP_`: `QUIRE_BACKUP_S3_ENDPOINT`,
  `QUIRE_BACKUP_S3_BUCKET`, `QUIRE_BACKUP_S3_ACCESS_KEY_ID` kaj tiel plu. Uzu alian bucketon kaj ideale alian konton ol por dosieroj; legitimiloj rajtu skribi sed ne forigi, se provizanto tion permesas.
- **Reteno.** Plej novaj `QUIRE_BACKUP_OFFSITE_KEEP` bazaj sekurkopioj (defaŭlte
  `QUIRE_BACKUP_KEEP`, alie 7) kaj WAL bezonata de plej malnova; pli malnovaj
  aroj kaj segmentoj estas forigitaj el konservejo.
- **Kiam.** Ĉiun `QUIRE_BACKUP_SHIP_INTERVAL_SECONDS` (defaŭlte 300). Sendo
  estas idempotenta: jam stokitaj elementoj estas preterlasataj, kaj baza sekurkopio kalkuliĝas stokita nur
  post la lasta skribo de ĝia manifesto.

La sama komando ruliĝas permane:

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

Por restarigi ĉe nova gastiganto, unue revenigu aron, poste sekvu paŝojn sube
kun elŝutita dosierujo anstataŭ volumeno `pgbackup` kaj elŝutita
`wal-archive` anstataŭ `pgwal`:

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

## Restarigi al specifa momento <!--quire:restoring-to-a-point-in-time-->

Uzu post datumperdo: malbona importo, forigita kurso, kuntira
migrado malfarebla. Tio anstataŭigas aktualan datumbazon, do unue ekzercu
per provo sube.

1. **Elektu celtempon** en UTC, ĵus antaŭ damaĝo:
   `2026-09-24 09:30:00+00`. Kontrolprotokolo (`/admin/audit`) kutime montras
   momenton.
2. **Haltigu ĉion skribantan**:
   `docker compose -f docker/compose.yaml stop web content worker scheduler collab`
3. **Konservu difektitan grapolon** ĝis restarigo estas kontrolita:
   ```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. **Malfaldu plej novan bazan sekurkopion pli fruan ol celo** en datumvolumon,
   kaj petu celitan reakiron:
   ```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. **Reakiru**: startigu Postgres unufoje kun reakiro-agordoj, per Compose-
   superregilo por ne tuŝi normalan dosieron:
   ```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]
   ```
   Superregilo anstataŭigas tutan komandon, do ĝi ripetas du agordojn
   bezonatajn de reakiro: `max_connections` ne malpli ol ĉe ĉefa datumbazo
   (alie reakiro ĉesas kun "insufficient parameter settings") kaj muntita
   `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. **Kontrolu** antaŭ ol enlasi iun: kontrolĉenon
   (`docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts`)
   kaj revenon de perdita datumo.
7. **Reiru al normala stato**: `docker compose -f docker/compose.yaml up -d`. Tio
   restartigas Postgres kun arkivado aktiva, kaj nova WAL-linio komenciĝas. Tuj faru freŝan bazan sekurkopion.

Projekt nomo `quire` estas prefiksata al volumoj; `docker volume ls` montras
precizajn nomojn.

## Planita kontrolprovo <!--quire:the-scheduled-verification-drill-->

`backup-offsite` ankaŭ rulas provon ĉiun `QUIRE_BACKUP_DRILL_INTERVAL_HOURS`
(defaŭlte 168, ĉiusemajne), kaj denove ĉe sekva kuro post malsukceso. Ĝi prenas
plej novan ekstergastigantan bazan sekurkopion kaj ĉiun WAL-segmenton post ĝi, malĉifras ĉiun
(pruvante ke ŝlosilo plu malfermas ilin kaj nenio ŝanĝiĝis), komparas ĉiun
dosieron kun manifesto, kontrolas ke arkivo estas Postgres-datumdosierujo kaj
kontrolas ke WAL ekde sekurkopio havas neniun truon. Raporto skribiĝas
en konservejo kiel `reports/drill-<time>.json` kaj en servoprotokolo; malsukcesa
provo nomas dosieron aŭ unuan mankantan segmenton.

## Restariga provo <!--quire:the-restore-drill-->

Sekurkopio neniam restarigita ne estas sekurkopio. Provo restarigas
plej novan kompletan bazan sekurkopion faritan antaŭ celo, plus WAL-arkivon,
en apartan provan Postgres-on sen kunhavaĵoj kun viva instanco, kaj pruvas
rezulton:

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

Celo estas UTC en precize tiu formo. Bezonata estas baza sekurkopio pli frua
ol ĝi kaj arkivita WAL posta al ĝi: ĉe nova instalado, faru bazan sekurkopion kaj atendu
proksiman arkivitan segmenton (maksimume minuton kun skriboj) antaŭ ol elekti
celon post sekurkopio. Provo bezonas Docker kaj bash ĉe gastiganto, nenion alian.

Ĉiu paŝo povas malsukcesigi provon:

1. **Reakireblo**: prova grapolo reludas ĝis celo kaj malfermiĝas.
2. **Kompleteco**: kalkulo de vicoj de ĉiu tabelo kompare kun viva datumbazo
   (`tooling/restore-drill`). Viva datumbazo progresis post celo,
   do diferenco ĉe tablo povas esti la pli granda el 500 vicoj kaj dekono de ĝia grando,
   ambaŭdirekte (skriboj igas ĝin malantaŭa; forigoj lasas pli en restarigo);
   subdisko kreita post celo ne estas perdita tabelo. Plilarĝigu
   permeson ĉe pli aktiva instalo per `QUIRE_DRILL_MAX_BEHIND` kaj
   `QUIRE_DRILL_MAX_DRIFT_RATIO`. Mankanta aŭ malplenigita tabelo malsukcesas.
3. **Integreco**: kontrola haketĉeno validas ĉe restarigita kopio.
4. **Uzeblo**: aplikaĵa rolo legas laŭ row-level security.
5. **Tempo**: de starto ĝis sukceso, kompare kun `QUIRE_DRILL_RTO_SECONDS`
   (defaŭlte 3600).

Ĝi neniam skribas al viva datumbazo aŭ ĝiaj volumoj: sekurkopiaj kaj WAL-
volumoj estas muntitaj nurlegeble kaj prova grapolo estas forigita je fino,
ĉu sukcese ĉu ne.

Agordu `QUIRE_DRILL_REPORT` al vojo por skribi JSON-raporton, sukcesan aŭ
malsukcesan, kaj rulu laŭ horaro el Docker-gastiganto:

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

Rulu ĉiumonate kaj antaŭ ĉiu ĝisdatigo. Malsukcesa provo blokas ĝisdatigon.
Ĉiukvaronjare, petu al iu neverkinta ĉi tiun runbook fari realan
restarigon al specifa momento ĉe rezerva gastiganto uzante nur ĉi tiun dokumenton.

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

Lokaj dosieroj troviĝas en volumeno `files`. Sekurkopiu ĝin samtempe kun datumbazo
kaj restarigu ambaŭ kune:

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

Kun objektostokado, ŝaltu bucketan versionigon kaj konservu 35 tagojn da
neaktualaj versioj; tiam la bucketo mem provizas tempopunktan reakiron de dosieroj.

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