---
title: "બેકઅપ, ચોક્કસ સમયની પુનઃપ્રાપ્તિ અને પુનઃસ્થાપન અભ્યાસ"
description: "Quire નો બેકઅપ લો, ચોક્કસ સમય સુધી પુનઃસ્થાપિત કરો અને પુનઃસ્થાપન અભ્યાસથી તેની ખાતરી કરો."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/gu/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
પ્રોડક્ટ માટેની runbook છે. જે વ્યક્તિએ આ લખ્યું નથી તે અનુસરી શકે એ રીતે લખી છે;
કોઈ પગલું અસ્પષ્ટ હોય તો આ દસ્તાવેજમાં ખામી છે.

## શું સુરક્ષિત છે અને કેવી રીતે <!--quire:what-is-protected-and-how-->

| સંપત્તિ | રીત | સ્થાન |
| --- | --- | --- |
| ડેટાબેઝ | પ્રથમ boot થી સતત WAL archive, વધુમાં વધુ દર 60 સેકન્ડે | `pgwal` volume |
| ડેટાબેઝ | `pg_basebackup` વડે આધાર બેકઅપ, મૂળભૂત રીતે દરરોજ (`backup-scheduler`) | `pgbackup` volume |
| ડેટાબેઝ | આધાર બેકઅપ અને WAL ની એન્ક્રિપ્ટ કરેલી નકલો દર પાંચ મિનિટે (`backup-offsite`) | તમે પસંદ કરેલો અલગ store |
| Files | `files` volume. તમારા host ના backup tool થી નકલ કરો અથવા versioned object storage વાપરો | `files` volume |
| Secrets | `docker/.env`, ખાસ કરીને `QUIRE_MASTER_KEY` (અને વપરાશમાં હોય તેવી `QUIRE_MASTER_KEY_RETIRED`), `QUIRE_BACKUP_ENCRYPTION_KEY` અને `docker/secrets/audit-signing-key.pem` | આ host ની બહાર નકલ રાખો |
| Search indexes, caches, renditions | બેકઅપ લેવાતાં નથી; ફરી બનાવાય છે | |

લક્ષ્યો: નિષ્ફળતા પછી 60 સેકન્ડની અંદરનો recovery point, અને 500 GB ડેટાબેઝ માટે
60 મિનિટની અંદર પુનઃસ્થાપન.

બે ભૂલો વારંવાર થાય છે. **Files વિના** પુનઃસ્થાપિત ડેટાબેઝ તૂટેલા પાનાં આપે છે.
**`QUIRE_MASTER_KEY` વિના** પુનઃસ્થાપિત ડેટાબેઝ તેમાં રહેલા SSO, webhook અને
integration ઓળખપત્રો decrypt કરી શકતું નથી; unresolved કંઈ બાકી ન રહે ત્યાં સુધી
master key rotation પૂર્ણ ન થાય ([key-rotation.md](/gu/ops/key-rotation/)), ત્યાં સુધી તેમાં
retired keys પણ આવે છે. બંને બેકઅપનો ભાગ છે.

## બેકઅપ લેવું <!--quire:taking-backups-->

આખા cluster નો આધાર બેકઅપ:

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

તે તાજેતરના `QUIRE_BACKUP_KEEP` આધાર બેકઅપ રાખે છે (મૂળભૂત 5) અને સૌથી જૂનાને હવે
જરૂર ન હોય તે WAL કાઢી નાખે છે, જેથી archive અપરિમિત ન વધે. Host પર cron અથવા
systemd timer વડે દરરોજ સમય નક્કી કરો:

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

અથવા stack ને સમય નક્કી કરવા દો: `backup` profile `backup-scheduler` ચલાવે છે, જે
દર `QUIRE_BACKUP_INTERVAL_HOURS` (મૂળભૂત 24) કલાકે આધાર બેકઅપ લે છે, અને આગળ
વર્ણવેલું `backup-offsite` પણ ચલાવે છે.

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

## Host ની બહાર એન્ક્રિપ્ટ કરેલી નકલો <!--quire:encrypted-off-host-copies-->

બંને volumes ડેટાબેઝવાળા એ જ host પર છે; નિષ્ફળ થયેલા મશીન પરનો બેકઅપ બેકઅપ નથી.
`backup-offsite` દરેક આધાર બેકઅપ અને દરેક archived WAL segment ને storage port મારફતે
અલગ store માં એન્ક્રિપ્ટ કરીને નકલ કરે છે અને retention નીતિ અનુસાર ત્યાં રાખે છે:

- **એન્ક્રિપ્શન.** `QUIRE_BACKUP_ENCRYPTION_KEY` વડે AES-256-GCM (અથવા
  `QUIRE_BACKUP_ENCRYPTION_KEY_FILE` દ્વારા દર્શાવેલી file): 32 bytes,
  `openssl rand -hex 32` માંથી. દરેક file નો પોતાનો nonce અને authentication
  tag હોય છે; તેથી key વિના નકલ વાંચી શકાતી નથી અને તેમાં કોઈ ફેરફાર થયો હોય તો
  પકડાય છે. Key ને `QUIRE_MASTER_KEY` સાથે આ host અને backup store થી દૂર રાખો.
  Key વિના પુનઃસ્થાપન શક્ય નથી.
- **સ્થાન.** `QUIRE_BACKUP_STORAGE_DRIVER` નું મૂલ્ય `s3`, `azure` અથવા `local`
  ( `QUIRE_BACKUP_STORAGE_ROOT` પર mount કરેલી remote disk) છે. સેટિંગ્સ file storage
  વાળી જ છે, ફક્ત આગળ `QUIRE_BACKUP_` prefix છે: `QUIRE_BACKUP_S3_ENDPOINT`,
  `QUIRE_BACKUP_S3_BUCKET`, `QUIRE_BACKUP_S3_ACCESS_KEY_ID` વગેરે. Files માટેના
  bucket થી જુદો અને શક્ય હોય તો જુદો account વાપરો; provider મંજૂરી આપે તો લખી શકે
  પણ કાઢી ન શકે એવા credentials રાખો.
- **Retention.** નવા `QUIRE_BACKUP_OFFSITE_KEEP` આધાર બેકઅપ (મૂળભૂત રીતે
  `QUIRE_BACKUP_KEEP`, નહિતર 7) અને સૌથી જૂનાને જરૂરી WAL રાખાય છે; જૂના sets અને
  segments store માંથી કાઢી નાખાય છે.
- **ક્યારે.** દરેક `QUIRE_BACKUP_SHIP_INTERVAL_SECONDS` (મૂળભૂત 300 સેકન્ડે).
  Shipping idempotent છે: પહેલેથી સંગ્રહેલી વસ્તુઓ છોડાય છે, અને આધાર બેકઅપનો
  manifest છેલ્લે લખાય ત્યારે જ તેને સંગ્રહાયેલો ગણાય છે.

આ જ આદેશ હાથેથી પણ ચલાવી શકાય છે:

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

નવા host પર પુનઃસ્થાપન માટે પહેલાં એક set પાછો લાવો, પછી નીચેના પગલાંમાં મેળવેલી
directory ને `pgbackup` volume ના બદલે અને મેળવેલા `wal-archive` ને `pgwal` ના બદલે વાપરો:

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

## ચોક્કસ સમય સુધી પુનઃસ્થાપિત કરવું <!--quire:restoring-to-a-point-in-time-->

ડેટા ગુમાય ત્યારે વાપરો: ખોટો import, કાઢી નાખેલો course, અથવા પાછી ફેરવવાની
જરૂરિયાતવાળી contract migration. આ live ડેટાબેઝ બદલે છે, તેથી પહેલાં નીચેના અભ્યાસથી
રીહર્સલ કરો.

1. **લક્ષ્ય સમય પસંદ કરો**, UTC માં, નુકસાન થવાની ક્ષણથી તરત પહેલાંનો:
   `2026-09-24 09:30:00+00`. Audit log (`/admin/audit`) સામાન્ય રીતે સમય બતાવે છે.
2. **લખતી દરેક વસ્તુ રોકો**:
   `docker compose -f docker/compose.yaml stop web content worker scheduler collab`
3. **પુનઃસ્થાપન ચકાસાય ત્યાં સુધી નુકસાન પામેલું cluster રાખો**:
   ```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. **લક્ષ્ય સમય પહેલાંનો સૌથી નવો આધાર બેકઅપ** data volume માં ખોલો અને નિશાનિત
   recovery માગો:
   ```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. **પુનઃપ્રાપ્તિ કરો**: સામાન્ય file અસ્પર્શિત રહે તે માટે Compose override માંથી
   recovery સેટિંગ સાથે Postgres એક વાર શરૂ કરો:
   ```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]
   ```
   Override આખો command બદલે છે, તેથી recovery ને જરૂરી બંને સેટિંગ ફરી આપે છે:
   `max_connections` primary કરતાં ઓછું નહીં (નહિતર recovery
   "insufficient parameter settings" સાથે અટકે છે) અને mount કરેલું `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. **કોઈને પ્રવેશ આપવા પહેલાં તપાસો**: audit chain
   (`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 ને archiving ચાલુ રાખીને ફરી શરૂ કરે છે અને નવી WAL timeline શરૂ થાય છે.
   તરત જ નવો આધાર બેકઅપ લો.

Project નું નામ `quire` દરેક volume પહેલાં લાગે છે; ચોક્કસ નામો `docker volume ls`
બતાવે છે.

## નક્કી કરેલો ચકાસણી અભ્યાસ <!--quire:the-scheduled-verification-drill-->

`backup-offsite` દર `QUIRE_BACKUP_DRILL_INTERVAL_HOURS` (મૂળભૂત 168, સાપ્તાહિક)
કલાકે અભ્યાસ પણ ચલાવે છે અને નિષ્ફળતા પછીના આગામી ચક્રમાં ફરી ચલાવે છે. તે સૌથી
નવો host બહારનો આધાર બેકઅપ અને ત્યાર પછીના બધા WAL segments મેળવે છે, દરેકને decrypt
કરે છે (આથી key તેમને ખોલે છે અને તેમાં ફેરફાર થયો નથી તેની ખાતરી થાય છે), દરેક file
ને તેના manifest સાથે સરખાવે છે, archive Postgres data directory છે તે તપાસે છે અને
બેકઅપ પછીથી WAL માં કોઈ ખાલી જગ્યા નથી તેની ખાતરી કરે છે. અહેવાલ store માં
`reports/drill-<time>.json` તરીકે અને service log માં લખાય છે; નિષ્ફળ અભ્યાસ file અથવા
પહેલો ગુમ થયેલો segment જણાવે છે.

## પુનઃસ્થાપન અભ્યાસ <!--quire:the-restore-drill-->

ક્યારેય પુનઃસ્થાપિત ન કરેલો બેકઅપ બેકઅપ નથી. અભ્યાસ સૌથી નવા સંપૂર્ણ આધાર બેકઅપને,
લક્ષ્ય પહેલાંના સમયનો, અને WAL archive ને live ડેટાબેઝથી સંપૂર્ણ અલગ scratch 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 હોવું જોઈએ. તેના પહેલાંનો આધાર બેકઅપ અને તેના પછીનો
archived WAL જરૂરી છે: નવા install પર આધાર બેકઅપ લો અને લક્ષ્ય પસંદ કરતાં પહેલાં
આગળનો archived segment આવે ત્યાં સુધી રાહ જુઓ (લખાણ હોય તો વધુમાં વધુ એક મિનિટ).
અભ્યાસ માટે host પર Docker અને bash જોઈએ, બીજું કશું નહીં.

દરેક પગલું અભ્યાસ નિષ્ફળ કરી શકે છે:

1. **પુનઃપ્રાપ્યતા**: scratch cluster લક્ષ્ય સમય સુધી replay થઈને ખુલે છે.
2. **સંપૂર્ણતા**: live database સામે દરેક table ની row ગણતરી (`tooling/restore-drill`).
   Live database લક્ષ્ય સમય પછી આગળ વધી ગયો હોય છે, એટલે કોઈ table માં બંને દિશામાં
   500 rows અથવા તેના કદના દસમા ભાગમાંથી જે મોટું હોય તેટલો તફાવત માન્ય છે (લખાણો
   તેને પાછળ રાખે, deletions પુનઃસ્થાપિત નકલમાં વધારે રાખે); લક્ષ્ય પછી બનેલો partition
   ગુમાયેલો table નથી. વધુ વ્યસ્ત install માં `QUIRE_DRILL_MAX_BEHIND` અને
   `QUIRE_DRILL_MAX_DRIFT_RATIO` વડે મર્યાદા વધારો. ગુમ થયેલો અથવા ખાલી કરેલો table
   નિષ્ફળ જાય છે.
3. **અખંડિતતા**: પુનઃસ્થાપિત નકલ પર audit hash chain ચકાસાય છે.
4. **ઉપયોગિતા**: application role row-level security મારફતે વાંચી શકે છે.
5. **સમય**: શરૂઆતથી સફળતા સુધી `QUIRE_DRILL_RTO_SECONDS` સામે તપાસાય છે
   (મૂળભૂત 3600).

તે live database અથવા તેના volumes માં ક્યારેય લખતું નથી: backup અને WAL volumes
માત્ર વાંચવા માટે mount થાય છે અને પરિણામ સફળ હોય કે નિષ્ફળ, અંતે scratch cluster
કાઢી નાખાય છે.

`QUIRE_DRILL_REPORT` ને કોઈ path પર સેટ કરો તો સફળતા કે નિષ્ફળતા બંને સ્થિતિમાં JSON
અહેવાલ લખાય છે; Docker host પરથી schedule કરો:

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

તે દર મહિને અને દરેક upgrade પહેલાં ચલાવો. નિષ્ફળ અભ્યાસ upgrade અટકાવે છે. દર
ત્રિમાસિક કોઈ એવી વ્યક્તિને, જેણે આ runbook લખી નથી, ફક્ત આ દસ્તાવેજ વાપરીને spare
host પર ખરેખર ચોક્કસ-સમય પુનઃસ્થાપન કરવા કહો.

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

સ્થાનિક files `files` volume માં રહે છે. ડેટાબેઝ સાથે એ જ સમયે તેનો બેકઅપ લો અને
બંનેને સાથે પુનઃસ્થાપિત કરો:

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

Object storage હોય તો bucket versioning ચાલુ કરો અને 35 દિવસ સુધી જૂની versions
રાખો; પછી files માટે ચોક્કસ-સમય પુનઃપ્રાપ્તિ bucket પોતે સંભાળે છે.

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