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
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),
tio inkluzivas retiriĝintajn ŝlosilojn. Ambaŭ estas parto de sekurkopio.
Fari sekurkopiojn
Baza sekurkopio de tuta grapolo:
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:
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.
docker compose -f docker/compose.yaml --profile backup up -d
Ĉifritaj kopioj ekster gastiganto
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:
docker compose -f docker/compose.yaml run --rm backup-offsite bun apps/worker/src/backups/main.ts shipdocker 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:
bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restore
Restarigi al specifa momento
Uzu post datumperdo: malbona importo, forigita kurso, kuntira
migrado malfarebla. Tio anstataŭigas aktualan datumbazon, do unue ekzercu
per provo sube.
Elektu celtempon en UTC, ĵus antaŭ damaĝo:
2026-09-24 09:30:00+00. Kontrolprotokolo (/admin/audit) kutime montras
momenton.
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.
docker compose -f docker/compose.yaml -f docker/compose.recover.yaml up -d postgresdocker compose -f docker/compose.yaml logs -f postgres # wait for "database system is ready"
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.
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
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
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:
docker/scripts/restore-drill.sh # to ninety minutes agodocker/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:
Reakireblo: prova grapolo reludas ĝis celo kaj malfermiĝas.
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.
Integreco: kontrola haketĉeno validas ĉe restarigita kopio.
Uzeblo: aplikaĵa rolo legas laŭ row-level security.
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:
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
Lokaj dosieroj troviĝas en volumeno files. Sekurkopiu ĝin samtempe kun datumbazo
kaj restarigu ambaŭ kune:
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.