Id-disinn jinsab f’docs/architecture/23-ops.md sezzjoni 8. Dan huwa r-runbook
għall-prodott Docker Compose. Jinkiteb biex jiġi segwit minn xi ħadd li
ma kitbux; jekk pass mhuwiex ċar, dak huwa difett f’dan id-dokument.
X’inhu protett, u kif
Asset
How
Where
Id-database
WAL arkivjat kontinwament, kull 60 sekonda l-aktar, mill-ewwel boot
Volum pgwal
Id-database
Backups bażi b’pg_basebackup, kuljum default (backup-scheduler)
Volum pgbackup
Id-database
Kopji encrypted tal-backups bażi u l-WAL, kull ħames minuti (backup-offsite)
Maħżen separat li ssemmi int
Files
Il-volum files. Ikkopjah bl-għodda tal-backup tal-host tiegħek, jew uża ħażna ta’ oġġetti verżjonata
Volum files
Secrets
docker/.env, fuq kollox QUIRE_MASTER_KEY (u kwalunkwe QUIRE_MASTER_KEY_RETIRED li għadu jintuża), QUIRE_BACKUP_ENCRYPTION_KEY, u docker/secrets/audit-signing-key.pem
Żomm kopja barra dan il-host
Search indexes, caches, renditions
Mhux backed up; mibnija mill-ġdid
Miri: punt ta’ rkupru fi żmien 60 sekonda mill-ħsara, u restore
fi żmien 60 minuta għal database ta’ 500 GB.
Żewġ żbalji huma komuni. Database rrestawrata mingħajr il-fajls tagħha tagħmel
paġni miksura. Database rrestawrata mingħajr QUIRE_MASTER_KEY ma tistax
tiddekripta l-kredenzjali SSO, webhook u integrazzjoni li żżomm; sakemm rotazzjoni ta’ ċavetta master
tintemm b’xejn mhux solvut (key-rotation.md),
dan jinkludi ċ-ċwievet irtirati. It-tnejn huma parti mill-backup.
Teħid ta’ backups
Backup bażi tal-cluster kollu:
docker compose -f docker/compose.yaml --profile backup run --rm backup
Iżomm l-aktar backups bażi ġodda ta’ QUIRE_BACKUP_KEEP (default 5) u jneħħi
WAL li l-eqdem waħda ma teħtieġx aktar, biex l-arkivju ma jistax jikber bla limitu.
Skedaha kuljum b’cron jew timer systemd fuq il-host:
15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1
Jew ħalli l-istack tiskedaha: il-profil backup imexxi backup-scheduler,
li jieħu backup bażi kull QUIRE_BACKUP_INTERVAL_HOURS (default 24),
u backup-offsite, deskritt wara.
docker compose -f docker/compose.yaml --profile backup up -d
Kopji encrypted barra l-host
Iż-żewġ volumi jgħixu fuq l-istess host mad-database, u backup fuq il-
magna li falliet mhuwiex backup. backup-offsite jikkopja kull backup bażi
u kull segment WAL arkivjat lil maħżen separat permezz tal-port tal-ħażna,
encrypted, u jżommhom hemmhekk taħt retention:
Encryption. AES-256-GCM b’QUIRE_BACKUP_ENCRYPTION_KEY (jew il-fajl
imsemmi minn QUIRE_BACKUP_ENCRYPTION_KEY_FILE): 32 bytes, minn
openssl rand -hex 32. Kull fajl għandu n-nonce tiegħu u tag tal-awtentikazzjoni,
biex kopja ma tinqarax mingħajr iċ-ċavetta u kwalunkwe bidla fiha tiġi
skoperta. Żomm iċ-ċavetta ma’ QUIRE_MASTER_KEY, ’il bogħod minn dan il-host u ’l bogħod
mill-maħżen tal-backup. Mingħajr iċ-ċavetta m’hemm l-ebda restore.
Fejn.QUIRE_BACKUP_STORAGE_DRIVER huwa s3, azure jew local (disk
remot mounted f’QUIRE_BACKUP_STORAGE_ROOT). Is-settings huma dawk tal-ħażna tal-fajls
b’prefiss QUIRE_BACKUP_: QUIRE_BACKUP_S3_ENDPOINT,
QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID, eċċ. Uża
bucket differenti u, idealment, kont differenti mill-fajls, b’
kredenzjali li jistgħu jiktbu iżda ma jħassrux jekk il-fornitur jippermetti.
Retention. L-aktar backups bażi ġodda ta’ QUIRE_BACKUP_OFFSITE_KEEP (default
QUIRE_BACKUP_KEEP, inkella 7) u l-WAL li l-eqdem minnhom teħtieġ; settijiet u segmenti eqdem
jitħassru mill-maħżen.
Meta. Kull QUIRE_BACKUP_SHIP_INTERVAL_SECONDS (default 300). Il-bagħt
huwa idempotenti: dak li diġà huwa maħżen jinqabeż, u backup bażi jgħodd
bħala maħżen biss ladarba l-manifest tiegħu jinkiteb, l-aħħar.
L-istess kmand jaħdem bl-idejn:
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
Biex tirrestawra fuq host ġdid, ġib sett lura l-ewwel, imbagħad segwi l-passi hawn taħt
bid-directory miġjuba minflok il-volum pgbackup u l-
wal-archive miġjub minflok pgwal:
bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restore
Restore għal punt fiż-żmien
Uża dan wara telf ta’ data: importazzjoni ħażina, kors imħassar, migrazzjoni
contract li għandek bżonn tħassar. Tissostitwixxi d-database live, għalhekk ipprattikaha
bid-drill hawn taħt l-ewwel.
Agħżel il-ħin fil-mira, f’UTC, ftit qabel il-ħsara:
2026-09-24 09:30:00+00. Il-log tal-verifika (/admin/audit) normalment juri l-
mument.
Waqqaf kull ma jikteb:
docker compose -f docker/compose.yaml stop web content worker scheduler collab
Żomm il-cluster imħassar sakemm ir-restore jiġi vverifikat:
docker compose -f docker/compose.yaml stop postgresdocker run --rm -v quire_postgres18-data:/from -v quire_postgres-damaged:/to alpine cp -a /from/. /to/
Iftaħ l-aktar backup bażi ġdid eqdem mill-mira fil-volum tad-data,
u itlob irkupru mmirat:
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'
Irkupra: ibda Postgres darba bis-settings tal-irkupru, minn
override ta’ Compose biex il-fajl normali ma jintmessx:
L-override tissostitwixxi l-kmand kollu, għalhekk tirrepeti ż-żewġ settings
li l-irkupru jiddependi fuqhom: max_connections mhux inqas mill-primarja
(inkella l-irkupru jabbanduna b’“insufficient parameter settings”) u
il-pg_hba.conf mounted.
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"
Iċċekkjaha qabel ma tħalli lil ħadd jidħol: il-katina tal-verifika
(docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts),
u li d-data mitlufa reġgħet lura.
Erġa’ għan-normal: docker compose -f docker/compose.yaml up -d. Dan
jerġa’ jibda Postgres bl-arkivjar mixgħul, u timeline WAL ġdida tibda. Ħu
backup bażi frisk minnufih.
L-isem tal-proġett quire jipprefigġi kull volum; docker volume ls juri l-
ismijiet eżatti.
Id-drill tal-verifika skedata
backup-offsite imexxi wkoll drill kull QUIRE_BACKUP_DRILL_INTERVAL_HOURS
(default 168, kull ġimgħa), u mill-ġdid fil-pass li jmiss wara li wieħed ifalli. Huwa jġib
l-aktar backup bażi ġdid barra l-host u kull segment WAL warajh, jiddekripta kull wieħed
(li jipprova li ċ-ċavetta xorta tiftaħhom u xejn ma ġie mibdul), iqabbel kull
fajl mal-manifest tiegħu, jiċċekkja li l-arkivju huwa directory tad-data ta’ Postgres, u
jiċċekkja li l-WAL mill-backup ’il quddiem m’għandu l-ebda vojt. Ir-rapport jinkiteb fil-
maħżen bħala reports/drill-<time>.json u fil-log tas-servizz; drill fallut isemmi
il-fajl jew l-ewwel segment nieqes.
Id-drill tar-restore
Backup li qatt ma ġie rrestawrat mhuwiex backup. Id-drill jirrestawra l-
aktar backup bażi komplut ġdid meħud qabel il-mira, flimkien mal-arkivju WAL,
f’Postgres scratch li ma jaqsam xejn mal-live, u jipprova r-
riżultat:
docker/scripts/restore-drill.sh # to ninety minutes agodocker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"
Il-mira hija UTC f’dik il-forma eżatta. Jeħtieġ backup bażi eqdem minnha
u WAL arkivjat lil hinn minnha: fuq installazzjoni ġdida, ħu backup bażi u stenna għas-
segment arkivjat li jmiss (l-aktar minuta bi kitbiet) qabel ma tagħżel
mira wara l-backup. Id-drill jeħtieġ Docker u bash fuq il-host, xejn
ieħor.
Kull pass ifalli d-drill:
Irkuprabbiltà: il-cluster scratch jerġa’ jdoqq sal-mira u jiftaħ.
Kompletezza: l-għadd tar-ringieli ta’ kull tabella kontra d-database live
(tooling/restore-drill). Id-database live mexgħet ‘il quddiem mill-mira,
għalhekk tabella tista’ tvarja bl-akbar ta’ 500 ringiela u għaxra tad-daqs tagħha, fi
kull direzzjoni (kitbiet jagħmluha lura, tħassir jagħmel ir-restore jżomm aktar);
partizzjoni maħluqa wara l-mira mhijiex tabella mitlufa. Wessa’ l-
allowance fuq installazzjoni aktar traffikuża b’QUIRE_DRILL_MAX_BEHIND u
QUIRE_DRILL_MAX_DRIFT_RATIO. Tabella nieqsa jew vojta tfalli.
Integrità: il-katina hash tal-verifika tivverifika fuq il-kopja rrestawrata.
Użabbiltà: ir-rwol tal-applikazzjoni jaqra permezz ta’ sigurtà fil-livell tar-ringieli.
Ħin: mill-bidu għal aħdar, kontra QUIRE_DRILL_RTO_SECONDS
(default 3600).
Qatt ma jikteb fid-database live jew fil-volumi tagħha: il-backup u l-WAL
volumi huma mounted qari biss u l-cluster scratch jitneħħa fl-aħħar,
jgħaddi jew ifalli.
Issettja QUIRE_DRILL_REPORT għal mogħdija biex rapport JSON jinkiteb, jgħaddi jew
ifalli, u ħaddmu fuq skeda mill-host Docker:
Ħaddmu kull xahar u qabel kull aġġornament. Drill fallut jimblokka l-aġġornament.
Darba kull tliet xhur, ħalli lil xi ħadd li ma kitebx dan ir-runbook iwettaq restore
puntwal reali fuq host żejjed, bl-użu ta’ dan id-dokument biss.
Fajls
Fajls lokali jgħixu fil-volum files. Agħmel backup tagħhom mad-database, fl-
istess ħin, u rrestawra t-tnejn flimkien:
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 .
B’ħażna ta’ oġġetti, ixgħel il-verżjonar tal-bucket u żomm 35 jum ta’
verżjonijiet mhux attwali; irkupru puntwal għall-fajls imbagħad huwa dak tal-bucket
stess.