---
title: "ब्याकअप, निश्चित समय पुनःप्राप्ति र पुनर्स्थापना अभ्यास"
description: "Quire ब्याकअप गर्नुहोस्, निश्चित समयमा पुनर्स्थापना गर्नुहोस्, र पुनर्स्थापना अभ्यासबाट प्रमाणित गर्नुहोस्।"
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/ne/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, webhook र एकीकरण प्रमाण डिक्रिप्ट गर्न सक्दैन;
केही अनसुलझे नभई मास्टर कुञ्जी घुमाउने सकिएसम्म ([key-rotation.md](/ne/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 खण्ड भण्डारण पोर्टमार्फत छुट्टै भण्डारमा प्रतिलिपि गर्छ,
इन्क्रिप्टेड, र अवधारणअन्तर्गत त्यहाँ राख्छ:

- **इन्क्रिप्सन।** `QUIRE_BACKUP_ENCRYPTION_KEY` (वा `QUIRE_BACKUP_ENCRYPTION_KEY_FILE` ले नाम दिएको फाइल) सहित AES-256-GCM:
  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`, आदि। फाइलबाट फरक बकेट र,
  आदर्श, फरक खाता प्रयोग गर्नुहोस्, प्रदायकले दिएमा लेख्न सक्ने तर मेट्न नसक्ने प्रमाणसहित।
- **अवधारण।** नवीनतम `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. **अखण्डता**: पुनर्स्थापित प्रतिलिपिमा अडिट ह्यास शृङ्खला प्रमाणित हुन्छ।
4. **प्रयोगयोग्यता**: अनुप्रयोग भूमिकाले पङ्क्ति-स्तर सुरक्षामार्फत पढ्छ।
5. **समय**: सुरुदेखि हरियोसम्म, `QUIRE_DRILL_RTO_SECONDS` विरुद्ध
   (पूर्वनिर्धारित 3600)।

यसले प्रत्यक्ष डेटाबेस वा यसका भोल्युममा कहिल्यै लेख्दैन: ब्याकअप र WAL भोल्युम पठन-मात्र माउन्ट हुन्छन्
र स्क्र्याच क्लस्टर अन्त्यमा हटाइन्छ, पास वा असफल।

JSON प्रतिवेदन लेख्न `QUIRE_DRILL_REPORT` लाई पथमा सेट गर्नुहोस्, पास वा
असफल, र 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 .
```

वस्तु भण्डारणसँग, बकेट संस्करण खोल्नुहोस् र 35 दिन गैरहालका संस्करण राख्नुहोस्;
फाइलका लागि निश्चित समय पुनःप्राप्ति त्यसपछि बकेटकै हुन्छ।

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