---
title: "Պահուստավորում, ժամանակակետի վերականգնում և վերականգնման փորձ"
description: "Պահուստավորեք Quire-ը, վերականգնեք այն նշված պահի վիճակով և ապացուցեք վերականգնման փորձի հաջողությունը։"
image: "https://docs.quirelms.com/og.png"
---

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

# Պահուստավորում, ժամանակակետի վերականգնում և վերականգնման փորձ

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

Դիզայնը նկարագրված է `docs/architecture/23-ops.md` փաստաթղթի 8-րդ բաժնում։
Սա Docker Compose արտադրանքի գործառնական ուղեցույցն է։ Այն գրված է այնպես,
որ կարողանա հետևել նաև այն անձը, ով այն չի գրել․ եթե որևէ քայլ անհասկանալի է,
դա այս փաստաթղթի թերությունն է։

## Ինչն է պաշտպանված և ինչպես <!--quire:what-is-protected-and-how-->

| Տվյալ | Ինչպես | Որտեղ |
| --- | --- | --- |
| Տվյալների բազա | WAL-ն արխիվացվում է շարունակաբար՝ առավելագույնը յուրաքանչյուր 60 վայրկյանը մեկ՝ առաջին մեկնարկից ի վեր | `pgwal` ծավալ |
| Տվյալների բազա | `pg_basebackup`-ով հիմնական պահուստային պատճեններ, լռելյայն՝ ամեն օր (`backup-scheduler`) | `pgbackup` ծավալ |
| Տվյալների բազա | Հիմնական պատճենների և WAL-ի կոդավորված պատճեններ ամեն հինգ րոպեն մեկ (`backup-offsite`) | Ձեր նշած առանձին պահոց |
| Ֆայլեր | `files` ծավալը։ Պատճենեք այն հոսթի պահուստավորման գործիքով կամ օգտագործեք տարբերակվող օբյեկտների պահեստ | `files` ծավալ |
| Գաղտնի արժեքներ | `docker/.env`, հատկապես `QUIRE_MASTER_KEY`-ը (և դեռ օգտագործվող `QUIRE_MASTER_KEY_RETIRED` բանալիները), `QUIRE_BACKUP_ENCRYPTION_KEY`-ը և `docker/secrets/audit-signing-key.pem`-ը | Պատճենը պահեք այս հոսթից դուրս |
| Որոնման ինդեքսներ, քեշեր, տարբերակված ֆայլեր | Չեն պահուստավորվում․ վերակառուցվում են | |

Նպատակներն են՝ խափանումից հետո վերականգնման կետը լինի 60 վայրկյանի սահմանում,
իսկ 500 GB տվյալների բազայի վերականգնումը՝ 60 րոպեի ընթացքում։

Երկու սխալ հաճախ են պատահում։ Առանց **ֆայլերի** վերականգնված տվյալների բազան
ցուցադրում է խափանված էջեր։ Առանց **`QUIRE_MASTER_KEY`** վերականգնված բազան
չի կարող բացել իր SSO-ի, վեբհուքների ու ինտեգրումների հավատարմագրերը․ մինչև
գլխավոր բանալու պտտումն ավարտվի առանց չլուծված արժեքների
([key-rotation.md](/hy/ops/key-rotation/)), դրանք ներառում են նաև հին բանալիները։
Երկուսն էլ պահուստավորման մաս են։

## Պահուստային պատճենների ստեղծում <!--quire:taking-backups-->

Ամբողջ կլաստերի հիմնական պահուստային պատճենը․

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

Այն պահում է ամենանոր `QUIRE_BACKUP_KEEP` հիմնական պատճենները (լռելյայն՝ 5) և
մաքրում է ամենահինին այլևս անհրաժեշտություն չունեցող WAL-ը, որպեսզի արխիվը
անսահման չաճի։ Հոսթի cron-ով կամ systemd ժմչփով նախատեսեք ամենօրյա
գործարկում․

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

Կամ թողեք, որ կլաստերն ինքը պլանավորի․ `backup` պրոֆիլը գործարկում է
`backup-scheduler`-ը, որը հիմնական պատճեն է ստեղծում յուրաքանչյուր
`QUIRE_BACKUP_INTERVAL_HOURS` ժամում (լռելյայն՝ 24), և հաջորդ բաժնում
նկարագրված `backup-offsite`-ը։

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

## Հոսթից դուրս կոդավորված պատճեններ <!--quire:encrypted-off-host-copies-->

Երկու ծավալն էլ տվյալների բազայի հետ նույն հոսթում են, իսկ խափանված մեքենայի
վրա պահված պատճենը պահուստային պատճեն չէ։ `backup-offsite`-ը պահեստի դարպասով
կոդավորված պատճենում է յուրաքանչյուր հիմնական պահուստային պատճենն ու WAL-ի
յուրաքանչյուր արխիվացված հատվածը առանձին պահոցում և այնտեղ պահում ըստ
պահպանման կանոնների․

- **Կոդավորում։** AES-256-GCM՝ `QUIRE_BACKUP_ENCRYPTION_KEY`-ով (կամ
  `QUIRE_BACKUP_ENCRYPTION_KEY_FILE`-ում նշված ֆայլով)․ 32 բայթ՝ ստացված
  `openssl rand -hex 32` հրամանով։ Յուրաքանչյուր ֆայլ ունի իր nonce-ն ու
  վավերացման պիտակը, ուստի առանց բանալու պատճենն ընթեռնելի չէ, իսկ ցանկացած
  փոփոխություն հայտնաբերվում է։ Բանալին պահեք `QUIRE_MASTER_KEY`-ի հետ՝ այս
  հոսթից և պահուստային պատճենների պահոցից հեռու։ Առանց բանալու վերականգնում
  հնարավոր չէ։
- **Որտեղ։** `QUIRE_BACKUP_STORAGE_DRIVER`-ը `s3`, `azure` կամ `local` է
  (հեռակա սկավառակ, որը կցված է `QUIRE_BACKUP_STORAGE_ROOT` հասցեում)։
  Կարգավորումները ֆայլերի պահեստի կարգավորումներն են՝ `QUIRE_BACKUP_`
  նախածանցով․ `QUIRE_BACKUP_S3_ENDPOINT`, `QUIRE_BACKUP_S3_BUCKET`,
  `QUIRE_BACKUP_S3_ACCESS_KEY_ID` և այլն։ Օգտագործեք ֆայլերի պահեստից տարբեր
  bucket և ցանկալի է՝ նաև տարբեր հաշիվ, իսկ եթե մատակարարը թույլ է տալիս՝
  հավատարմագրեր, որոնք կարող են գրել, բայց ոչ ջնջել։
- **Պահպանում։** Ամենանոր `QUIRE_BACKUP_OFFSITE_KEEP` հիմնական պատճենները
  (լռելյայն՝ `QUIRE_BACKUP_KEEP`, հակառակ դեպքում՝ 7) և ամենահինին անհրաժեշտ
  WAL-ը․ ավելի հին հավաքածուներն ու հատվածները ջնջվում են պահոցից։
- **Երբ։** Ամեն `QUIRE_BACKUP_SHIP_INTERVAL_SECONDS` վայրկյանը մեկ
  (լռելյայն՝ 300)։ Փոխանցումն իդեմպոտենտ է․ պահվածը բաց է թողնվում, իսկ
  հիմնական պատճենը պահված է համարվում միայն այն բանից հետո, երբ որպես վերջին
  գործողություն գրվում է դրա մանիֆեստը։

Նույն հրամանը կարելի է ձեռքով գործարկել․

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

Նոր հոսթում վերականգնելու համար նախ հետ բերեք հավաքածուն, ապա հետևեք ստորև
քայլերին՝ `pgbackup` ծավալի փոխարեն օգտագործելով ներբեռնված թղթապանակը, իսկ
ներբեռնված `wal-archive`-ը՝ `pgwal`-ի փոխարեն․

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

## Վերականգնում նշված ժամանակակետին <!--quire:restoring-to-a-point-in-time-->

Օգտագործեք տվյալների կորստից հետո՝ սխալ ներմուծման, ջնջված դասընթացի կամ
հետարկելու անհրաժեշտություն ունեցող կրճատման միգրացիայի դեպքում։ Այն
փոխարինում է գործող տվյալների բազան, ուստի նախ փորձարկեք ստորև նշված եղանակով։

1. **Ընտրեք նպատակային պահը** UTC-ով՝ վնասից անմիջապես առաջ․
   `2026-09-24 09:30:00+00`։ Աուդիտի մատյանում (`/admin/audit`) սովորաբար
   երևում է այդ պահը։
2. **Կանգնեցրեք գրող բոլոր գործընթացները**․
   `docker compose -f docker/compose.yaml stop web content worker scheduler collab`
3. **Պահեք վնասված կլաստերը**, մինչև վերականգնման ստուգումը․
   ```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. **Նպատակային պահից հին նորագույն հիմնական պատճենը** բացեք տվյալների
   ծավալի մեջ և խնդրեք որոշակի ժամանակի վերականգնում․
   ```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. **Վերականգնում**․ Postgres-ը մեկ անգամ գործարկեք վերականգնման
   կարգավորումներով՝ Compose-ի լրացուցիչ ֆայլից, որպեսզի հիմնական ֆայլը
   անփոփոխ մնա․
   ```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]
   ```
   Լրացուցիչ ֆայլը փոխարինում է ամբողջ հրամանը, ուստի կրկնում է վերականգնման
   համար անհրաժեշտ երկու կարգավորումները․ `max_connections`-ը չպետք է ցածր լինի
   հիմնական սերվերի արժեքից (հակառակ դեպքում վերականգնումն ընդհատվում է
   «insufficient parameter settings» հաղորդագրությամբ), և պետք է նշվի նաև
   կցված `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. **Ստուգեք այն**՝ մինչև որևէ մեկին ներս թողնելը․ ստուգեք աուդիտի շղթան
   (`docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts`) և հաստատեք,
   որ կորցրած տվյալները վերադարձել են։
7. **Վերադարձեք սովորական ռեժիմին**․ `docker compose -f docker/compose.yaml up -d`։
   Սա վերագործարկում է Postgres-ը միացված արխիվացմամբ, և սկսվում է WAL-ի նոր
   ժամանակագիծ։ Անմիջապես ստեղծեք նոր հիմնական պահուստային պատճեն։

Նախագծի `quire` անունը յուրաքանչյուր ծավալի նախածանցն է․ ճշգրիտ անունները
ցուցադրում է `docker volume ls` հրամանը։

## Պլանավորված ստուգման փորձ <!--quire:the-scheduled-verification-drill-->

`backup-offsite`-ը նաև փորձ է անցկացնում յուրաքանչյուր
`QUIRE_BACKUP_DRILL_INTERVAL_HOURS` ժամում (լռելյայն՝ 168, շաբաթը մեկ), իսկ
ձախողումից հետո՝ հաջորդ անցման ժամանակ։ Այն վերցնում է հոսթից դուրս եղած
նորագույն հիմնական պատճենն ու դրանից հետո եղած բոլոր WAL հատվածները,
ապակոդավորում յուրաքանչյուրը (ապացուցելով, որ բանալին դեռ բացում է դրանք, և
ոչինչ չի փոփոխվել), յուրաքանչյուր ֆայլը համեմատում իր մանիֆեստի հետ,
ստուգում՝ արխիվը Postgres-ի տվյալների թղթապանակ է, և հաստատում, որ
պահուստավորումից սկսվող WAL-ում բաց չկա։ Հաշվետվությունը գրվում է պահոցում՝
`reports/drill-<time>.json` անունով և ծառայության մատյանում․ անհաջող փորձը
նշում է ֆայլը կամ առաջին բացակայող հատվածը։

## Վերականգնման փորձ <!--quire:the-restore-drill-->

Երբեք չվերականգնված պահուստային պատճենը ստուգված չէ։ Փորձը թիրախային պահից
առաջ արված ամենանոր ամբողջական հիմնական պատճենն ու WAL արխիվը վերականգնում է
ժամանակավոր Postgres-ում, որը ոչինչ չունի ընդհանուր գործող բազայի հետ, ապա
ապացուցում արդյունքը․

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

Նպատակային պահը պետք է լինի UTC-ով և հենց այդ ձևաչափով։ Պահը վերականգնելու
համար անհրաժեշտ է դրանից հին հիմնական պատճեն և դրանից հետո արխիվացված WAL։
Նոր տեղադրման դեպքում հիմնական պատճեն ստեղծեք և սպասեք հաջորդ արխիվացված
հատվածին (գրառումներ լինելու դեպքում՝ առավելագույնը մեկ րոպե), ապա ընտրեք
պահուստավորումից հետո ընկած նպատակային պահ։ Փորձը հոսթի վրա պահանջում է միայն
Docker և bash, ուրիշ ոչինչ։

Հետևյալ քայլերից յուրաքանչյուրի ձախողումը ձախողում է փորձը․

1. **Վերականգնելիություն**․ ժամանակավոր կլաստերը վերարտադրում է տվյալները մինչև
   նպատակային պահը և բացվում։
2. **Ամբողջականություն**․ յուրաքանչյուր աղյուսակի տողերի քանակի համեմատում
   գործող բազայի հետ (`tooling/restore-drill`)։ Գործող բազան նպատակային պահից
   առաջ է անցել, ուստի աղյուսակի տողերի քանակը կարող է երկու ուղղությամբ
   տարբերվել 500 տողից և իր չափի տասներորդից ավելի արժեքով (գրառումները
   վերականգնումը հետ են թողնում, ջնջումները՝ վերականգնված տարբերակում ավելի
   շատ տվյալ պահում)․ նպատակային պահից հետո ստեղծված բաժանմունքը կորած
   աղյուսակ չէ։ Ավելի ակտիվ տեղադրման դեպքում թույլատրելի շեղումը մեծացրեք
   `QUIRE_DRILL_MAX_BEHIND` և `QUIRE_DRILL_MAX_DRIFT_RATIO` կարգավորումներով։
   Բացակայող կամ դատարկված աղյուսակը ձախողում է առաջացնում։
3. **Ամբողջականություն**․ վերականգնված պատճենում ստուգվում է աուդիտի hash շղթան։
4. **Օգտագործելիություն**․ հավելվածի դերը տվյալները կարդում է տողի մակարդակով
   անվտանգության ներքո։
5. **Ժամանակ**․ մեկնարկից մինչև հաջող արդյունքը համեմատվում է
   `QUIRE_DRILL_RTO_SECONDS`-ի հետ (լռելյայն՝ 3600)։

Փորձը երբեք չի գրում գործող տվյալների բազայում կամ դրա ծավալներում․ պահուստային
պատճենի և WAL-ի ծավալները կցվում են միայն կարդալու իրավունքով, իսկ ժամանակավոր
կլաստերը հեռացվում է վերջում՝ հաջողության կամ ձախողման դեպքում։

Սահմանեք `QUIRE_DRILL_REPORT`-ը հաշվետվության ուղու վրա, որպեսզի JSON
հաշվետվությունը գրվի և՛ հաջողության, և՛ ձախողման դեպքում։ Այնուհետև
ժամանակացույցով գործարկեք հոսթի Docker միջավայրից․

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

Գործարկեք ամեն ամիս և յուրաքանչյուր արդիականացումից առաջ։ Անհաջող փորձը
արգելափակում է արդիականացումը։ Յուրաքանչյուր եռամսյակ թող որևէ մեկը, ով չի
գրել այս ուղեցույցը, պահուստային հոսթում կատարի իրական ժամանակակետի
վերականգնում՝ օգտագործելով միայն այս փաստաթուղթը։

## Ֆայլեր <!--quire:files-->

Տեղային ֆայլերը `files` ծավալում են։ Պահուստավորեք դրանք տվյալների բազայի հետ
միաժամանակ և միասին վերականգնեք․

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

Օբյեկտների պահեստ օգտագործելիս միացրեք bucket-ի տարբերակավորումը և 35 օր
պահեք չընթացիկ տարբերակները․ այդ դեպքում ֆայլերի ժամանակակետի վերականգնումը
կատարվում է հենց bucket-ի սեփական մեխանիզմով։

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