Ad contentum transilire

Custodia, recuperatio in tempus et exercitium restitutionis

Custodi Quire, restitue id ad tempus, et id exercitio restitutionis proba.

Ostendere textu Markdown

Consilium est docs/architecture/23-ops.md sectio 8. Hic est liber operum pro producti Docker Compose. Scriptus est ut ab eo sequatur qui eum non scripsit; si aliquis gradus obscurus est, id vitium in hoc documentum est.

Quid tueatur, et quomodo

Res Quomodo Ubi
Bases datae WAL continue archivata, omni 60 secunda saltem, ex prima incursione volumen pgwal
Bases datae Custodiae base cum pg_basebackup, cotidie per pristinum (backup-scheduler) volumen pgbackup
Bases datae Copiae encryptatae custodiarum base et WAL, omni quinque minuto (backup-offsite) Receptor separatus quem tu nominas
Filetuli Volumen files. Eum cum instrumento custodiae hospitis tui copia, aut repositionem obiectorum versionibus instructam utere volumen files
Arcana docker/.env, omnibus praecipue QUIRE_MASTER_KEY (et quodlibet QUIRE_MASTER_KEY_RETIRED adhuc in usu), QUIRE_BACKUP_ENCRYPTION_KEY, et docker/secrets/audit-signing-key.pem Copiam extra hunc hostem serva
Indices quaestionis, thesauri, renditiones Non custodiuntur; reficiuntur

Metae: punctum recuperationis intra 60 secundas ruinae, et restitutio intra 60 minuta pro basibus datae 500 GB.

Duo errorus communis sunt. Bases datae sine suis filetulis restitutae paginas fractas reddit. Bases datae sine QUIRE_MASTER_KEY restitutae arcana SSO, retextoris et integrationum quae tenet dechiffrare non possunt; usque ad id cum rota clavis magistralis absoluta est nihilque inresolverum (key-rotation.md), haec claves retiras includit. Utraque partes custodiae sunt.

Custodias capere

Custodia base totius agminis:

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

Ea novissimas QUIRE_BACKUP_KEEP custodias base servat (pristinum 5) et WAL quam vetustissima non iam desiderat putat, ita ut archivum sine fine crescere non possit. Eam cotidie cum cron aut timer systemd in hospite constitue:

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

Aut sine strue eam constituere sine: profilum backup currit backup-scheduler, qui custodiam base omni QUIRE_BACKUP_INTERVAL_HOURS (pristinum 24) accipit, et backup-offsite, qui proxime describitur.

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

Copiae extra hospitum encryptatae

Utraque volumina in eodem hospite cum basibus datae vivunt, et custodia in machina quae ruit non est custodia. backup-offsite quamque custodiam base et omne segmentum WAL archivatum per portum repositionis in receptorem separatum copiat, encryptatum, et eos ibi sub retentione servat:

  • Encryptio. AES-256-GCM cum QUIRE_BACKUP_ENCRYPTION_KEY (aut filetulo a QUIRE_BACKUP_ENCRYPTION_KEY_FILE nominato): 32 byta, ex openssl rand -hex 32. Quisque filetulus suum nonce et notam authenticationis habet, ideo copia sine clave legi nequit et quaelibet eius mutatio deprehenditur. Clavem cum QUIRE_MASTER_KEY serva, longe ab hoc hospite et longe a receptore custodiae. Sine clave nulla restitutio est.
  • Ubi. QUIRE_BACKUP_STORAGE_DRIVER est s3, azure aut local (discus remotus adfixus in QUIRE_BACKUP_STORAGE_ROOT). Constitutiones eae sunt filetulorum repositionis cum praefixo QUIRE_BACKUP_: QUIRE_BACKUP_S3_ENDPOINT, QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID, et ita porro. Bucket diversum et, optime, rationem diversam a filetulis utere, cum credentiis quae scribere possint non delere si praebitor permittit.
  • Retentio. Novissimae QUIRE_BACKUP_OFFSITE_KEEP custodiae base (pristinum QUIRE_BACKUP_KEEP, alioquin 7) et WAL quam vetustissima earum desiderat; antiquiores seti et segmenta e receptore delentur.
  • Quando. Omne QUIRE_BACKUP_SHIP_INTERVAL_SECONDS (pristinum 300). Navigatio idempotens est: quod iam servatum est omittitur, et custodia base solum semel cum suus index scriptus est, postremo, ut servata numeratur.

Eadem mandata manu curritur:

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

Ut in novo hospite restituas, primum setum reduce, deinde gradus infra sequere cum directory petito vice voluminis pgbackup et wal-archive petito vice pgwal:

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

Restituere ad tempus

Hoc post amissionem datarum utere: mala importatio, cursus deletus, migratio contractus quam solvere opus est. Vivas bases datae repraesentat, ideo eam primum cum exercitio infra exerce.

  1. Elige tempus metae, in UTC, paulo ante damnum: 2026-09-24 09:30:00+00. Liber custodiae (/admin/audit) plerumque momentum ostendit.
  2. Omne quod scribit compesce: docker compose -f docker/compose.yaml stop web content worker scheduler collab
  3. Agrum fractum serva usque ad id cum restitutio probata est:
    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. Novissimam custodiam base veterem quam tempus metae in volumen datae dispone, et recuperationem destinatam posce:
    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. Recupera: Postgres semel cum constitutionibus recuperationis incipe, ex superpositione Compose ita ut filetulum normale intactum maneat:
    # 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]
    Superpositio totum mandatum repraesentat, ideo ea duo constitutiones repetit quibus recuperatio pendet: max_connections non minus quam primarii (alioquin recuperatio cum “insufficient parameter settings” frangitur) et pg_hba.conf adfixum.
    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. Inspece eam antequam quemquam intromittas: catenam custodiae (docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts), et quod data amissa redierint.
  7. Ad normam redi: docker compose -f docker/compose.yaml up -d. Hic Postgres cum archivatione aperta iterum incipit, et novum tempus WAL incipit. Statim custodiam base novam cape.

Nomen projectus quire praefixum cuique volumini est; docker volume ls exacta nomina monstrat.

Exercitium explorationis constitutum

backup-offsite etiam exercitium omni QUIRE_BACKUP_DRILL_INTERVAL_HOURS (pristinum 168, hebdomadale) currit, et rursus in proxima currendo post unum fractum. Novissimam custodiam base extra hospitum et omne segmentum WAL post eam petit, quodque decryptat (quod probat clavem adhuc eos aperire et nihil mutatum esse), quodque filetulum cum suo indice comparat, inspicit archivum esse directory datae Postgres, et inspicit WAL a custodia in posterum nullum hiatus habere. Commentarium in receptorem ut reports/drill-<time>.json et in librum servitii scribitur; exercitium fractum filetulum aut primum segmentum deesse nominat.

Exercitium restitutionis

Custodia quae numquam restituta est non est custodia. Exercitium novissimam custodiam base completam ante tempus metae captam, plus archivum WAL, in Postgres ablutorium qui nihil cum vivo communicat restituit, et resultatum probat:

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

Tempus metae est UTC eo ipso forma. Custodiam base veterem quam id et WAL archivatum ultra id desiderat: in nova institutione, custodiam base cape et expecta proximum segmentum archivatum (cum scripturis saltem minutum) antequam tempus metae post custodiam eligas. Exercitium Docker et bash in hospite desiderat, nihil reliqui.

Quisque gradus exercitium frangit:

  1. Restitutibilitas: agmen ablutorium ad tempus metae reicit et aperitur.
  2. Completudo: numerus ordinum cuiusque tabulae contra vivas bases datae (tooling/restore-drill). Bases datae vivae post tempus metae processerunt, ideo tabula differre potest eo maiore quod inter 500 ordines et decimam partem magnitudinis eius est, utraque via (scripturae eam retardant, deletiones restitutio plura tenet); partitio post tempus metae creata non est tabula amissa. Latitudinem concessionis in institutione occupatiore cum QUIRE_DRILL_MAX_BEHIND et QUIRE_DRILL_MAX_DRIFT_RATIO fac. Tabula deesse aut evacuata frangit.
  3. Integritas: catena hausti custodiae in copia restituta probatur.
  4. Utilitas: rola applicationis per securitatem linea row legit.
  5. Tempus: ab initio ad viride, contra QUIRE_DRILL_RTO_SECONDS (pristinum 3600).

Numquam in vivas bases datae aut eorum volumina scribit: volumina custodiae et WAL solum legenti adfiguntur et agmen ablutorium in fine removetur, sive probatum sive fractum.

QUIRE_DRILL_REPORT in viam pone ut commentarium JSON scribatur, sive probatum sive fractum, et id in ordine ex hospite Docker curra:

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

Id monthly et ante quamque promotionem curra. Exercitium fractum promotionem prohibet. Semel per quadrimester, fac ut quis qui hunc librum non scripsit veram restitutionem in tempus in hospite vacuo perficiat, hoc solo documento usus.

Filetuli

Filetuli locales in volumine files vivunt. Eos cum basibus datae custodi, eodem tempore, et utrumque una restitue:

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 .

Cum repositio obiectorum, versionem bucket incipe et 35 dierum versionum non currentium serva; recuperatio in tempus pro filetulis tum ipsius bucket est.

Navigatio

Scribe ut quaeras…

↑↓ navigare↵ eligereEsc claudere