Aia ka hoʻolālā ma ka māhele 8 o docs/architecture/23-ops.md. ʻO kēia ke alakaʻi hana no ka huahana Docker Compose. Ua kākau ʻia i hiki i kekahi kanaka ʻaʻole nāna i kākau ke hahai; inā pohihihi kekahi ʻanuʻu, he hewa ia o kēia palapala.
Nā mea i pale ʻia a me ke ʻano
Waiwai
Pehea
Kahi
Ka waihona ʻikepili
Waihona WAL mau, ʻaʻole i ʻoi aku ma mua o kēlā me kēia 60 kekona, mai ka hoʻomaka mua
Volume pgwal
Ka waihona ʻikepili
Nā papaʻa kumu me pg_basebackup, i kēlā me kēia lā ma ke ʻano paʻamau (backup-scheduler)
Volume pgbackup
Ka waihona ʻikepili
Nā kope hoʻopāʻālua o nā papaʻa kumu a me WAL, i kēlā me kēia ʻelima minuke (backup-offsite)
Waihona kaʻawale āu e kapa ai
Nā faila
Volume files. E kope me ka mea hana papaʻa o kāu host, a i ʻole hoʻohana i waihona mea i mana ʻia
Volume files
Nā ʻōlelo huna malu
docker/.env, ʻoi loa QUIRE_MASTER_KEY (a me kekahi QUIRE_MASTER_KEY_RETIRED e hoʻohana mau ʻia ana), QUIRE_BACKUP_ENCRYPTION_KEY, a me docker/secrets/audit-signing-key.pem
E mālama i kope ma waho o kēia host
Nā helu kuhikuhi huli, cache, a me nā ʻano i hana ʻia
ʻAʻole i hoʻokomo ʻia i loko o ka papaʻa; kūkulu hou ʻia
Nā pahuhopu: hoʻihoʻi i kahi kūlana ma loko o 60 kekona ma mua o ka pilikia, a hoʻopau i ka hoʻihoʻi ma loko o 60 minuke no ka waihona 500 GB.
ʻElua hewa maʻamau. Hōʻike ka waihona ʻikepili i hoʻihoʻi ʻia me ka ʻole o nā faila i nā ʻaoʻao haki. ʻAʻole hiki i ka waihona ʻikepili i hoʻihoʻi ʻia me ka ʻole o QUIRE_MASTER_KEY ke wehe i nā palapala hōʻoia SSO, webhook, a hoʻohui; a pau ka hoʻololi kī haku me ka ʻole o kekahi mea i koe (key-rotation.md), pili kēia i nā kī hoʻomaha pū. Māhele lāua o ka papaʻa.
Hana i nā papaʻa
Papaʻa kumu o ke kāʻei holoʻokoʻa:
docker compose -f docker/compose.yaml --profile backup run --rm backup
Mālama ia i nā papaʻa kumu hou loa e like me QUIRE_BACKUP_KEEP (5 ma ke ʻano paʻamau), a wehe i ka WAL i pono ʻole i ka papaʻa kahiko loa, i ulu palena ʻole ʻole ai ka waihona. Hoʻonohonoho i ia mea i kēlā me kēia lā me cron a i ʻole timer systemd ma ka host:
15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1
A i ʻole e ʻae i ka stack e hoʻonohonoho: holo ka profile backup iā backup-scheduler, nāna e hana i papaʻa kumu i kēlā me kēia QUIRE_BACKUP_INTERVAL_HOURS (24 ma ke ʻano paʻamau), a me backup-offsite e wehewehe ʻia aʻe.
docker compose -f docker/compose.yaml --profile backup up -d
Nā papaʻa hoʻopāʻālua ma waho o ka host
Noho nā volume ʻelua ma ka host like me ka waihona ʻikepili; ʻaʻole he papaʻa ka papaʻa ma ka mīkini i hāʻule. Kope ʻo backup-offsite i kēlā me kēia papaʻa kumu a me kēlā me kēia māhele WAL i waihona kaʻawale ma o ka puka waiho ʻikepili; hoʻopāʻālua, a mālama ma lalo o ka lula mālama:
Hoʻopāʻālua. AES-256-GCM me QUIRE_BACKUP_ENCRYPTION_KEY (a i ʻole ka faila i kapa ʻia e QUIRE_BACKUP_ENCRYPTION_KEY_FILE): 32 byte mai openssl rand -hex 32. Loaʻa i kēlā me kēia faila kona nonce a me ka hōʻailona hōʻoia ponoʻī, no laila ʻaʻole hiki ke heluhelu i kope me ka ʻole o ke kī a ʻike ʻia kekahi hoʻololi. E mālama i ke kī me QUIRE_MASTER_KEY, ma kahi mamao o kēia host a me ka waihona papaʻa. ʻAʻohe hoʻihoʻi me ka ʻole o ke kī.
Kahi. ʻO QUIRE_BACKUP_STORAGE_DRIVER kekahi o s3, azure, a i ʻole local (disk mamao i kau ʻia ma QUIRE_BACKUP_STORAGE_ROOT). ʻO nā hoʻonohonoho mālama faila me ka prefix QUIRE_BACKUP_: QUIRE_BACKUP_S3_ENDPOINT, QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID, a pēlā aku. E hoʻohana i bucket ʻokoʻa a, ʻoi aku ka maikaʻi, i moʻokāki ʻokoʻa mai nā faila, me nā palapala hōʻoia hiki ke kākau akā ʻaʻole holoi inā ʻae ka mea hoʻolako.
Mālama. Nā papaʻa kumu hou loa e like me QUIRE_BACKUP_OFFSITE_KEEP (paʻamau QUIRE_BACKUP_KEEP, a i ʻole 7) a me ka WAL e pono ai ka papaʻa kahiko loa; holoi ʻia nā pūʻulu a me nā māhele kahiko mai ka waihona.
Ka wā. I kēlā me kēia QUIRE_BACKUP_SHIP_INTERVAL_SECONDS (300 ma ke ʻano paʻamau). Hana hoʻokahi wale nō ka hoʻouna: kāpae ʻia nā mea i mālama ʻia, a helu ʻia kahi papaʻa kumu he mālama ʻia ma hope wale nō o ke kākau ʻia ʻana o kāna hōʻike hope.
Holo lima pū kēia kauoha:
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
No ka hoʻihoʻi ma host hou, e kiʻi mua i pūʻulu, a laila hahai i nā ʻanuʻu ma lalo me ka waihona i kiʻi ʻia ma kahi o ka volume pgbackup, a me ka wal-archive i kiʻi ʻia ma kahi o pgwal:
bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restore
Hoʻihoʻi i kekahi manawa kikoʻī
E hoʻohana ma hope o ka nalowale ʻikepili: hoʻokomo hewa, holoi papa, a i ʻole neʻe pani e pono ai ke kāpae. Hoʻololi kēia i ka waihona ʻikepili ola, no laila e hoʻāʻo mua me ka hana ma lalo.
Koho i ka manawa pahuhopu, ma UTC, ma mua koke o ka pōʻino:
2026-09-24 09:30:00+00. Hōʻike maʻamau ka moʻolelo hōʻoia (/admin/audit) i ia manawa.
Hoʻōki i nā mea a pau e kākau ana:
docker compose -f docker/compose.yaml stop web content worker scheduler collab
Mālama i ke kāʻei i pohō a hōʻoia ʻia ka hoʻihoʻi:
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/
Wehe i ka papaʻa kumu hou loa ma mua o ka pahuhopu i loko o ka volume ʻikepili, a noi i ka hoʻihoʻi kikoʻī:
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'
Hoʻihoʻi: hoʻomaka hoʻokahi manawa iā Postgres me nā hoʻonohonoho hoʻihoʻi, mai ka pani Compose i ʻole e hoʻopā i ka faila maʻamau:
Hoʻololi ka pani i ke kauoha holoʻokoʻa, no laila hana hou i nā hoʻonohonoho
ʻelua e pono ai ka hoʻihoʻi: ʻaʻole emi ʻo max_connections ma mua o ka
hoʻonohonoho nui (i ʻole pau ka hoʻihoʻi me ka memo «insufficient parameter
settings») a me ka pg_hba.conf i kau ʻia.
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"
Nānā iā ia ma mua o ka ʻae ʻana i kekahi: ke kaulahao hōʻoia
(docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts),
a hōʻoia ua hoʻi ka ʻikepili i nalowale.
Hoʻi i ka maʻamau: docker compose -f docker/compose.yaml up -d. Hoʻomaka hou
ʻo Postgres me ka waihona WAL i hoʻā ʻia, a hoʻomaka ka laina manawa WAL hou.
Hana koke i papaʻa kumu hou.
Hoʻokomo ka inoa papahana quire i prefix ma kēlā me kēia volume; hōʻike ʻo docker volume ls i nā inoa pololei.
Ka hoʻāʻo hōʻoia i hoʻonohonoho ʻia
Holo pū ʻo backup-offsite i hoʻāʻo i kēlā me kēia QUIRE_BACKUP_DRILL_INTERVAL_HOURS (168, i kēlā me kēia pule ma ke ʻano paʻamau), a i ka holo aʻe ma hope o kekahi hāʻule. Kiʻi ia i ka papaʻa kumu waho hou loa a me kēlā me kēia māhele WAL ma hope ona, wehe i kēlā me kēia hoʻopāʻālua (hōʻoia kēia e wehe mau ke kī a ʻaʻohe mea i hoʻololi), hoʻohālikelike i kēlā me kēia faila me kona hōʻike hope, nānā he papa kuhikuhi ʻikepili Postgres ka waihona, a hōʻoia ʻaʻohe hakahaka ma ka WAL mai ka papaʻa. Kākau ʻia ka hōʻike ma ka waihona ma ke ʻano he reports/drill-<time>.json a ma ka moʻolelo lawelawe; kapa ka hoʻāʻo hāʻule i ka faila a i ʻole ka māhele mua i nalowale.
Ka hoʻāʻo hoʻihoʻi
ʻAʻole he papaʻa ka papaʻa i hoʻihoʻi ʻole ʻia. Hoʻihoʻi ka hoʻāʻo i ka papaʻa kumu piha hou loa ma mua o ka pahuhopu, me ka waihona WAL, i Postgres hoʻāʻo kaʻawale loa mai ka mea ola, a hōʻoia i ka hopena:
docker/scripts/restore-drill.sh # to ninety minutes agodocker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"
Pono ka pahuhopu ma UTC a ma kēlā ʻano kikoʻī. Pono kekahi papaʻa kumu ma mua ona a me WAL i waiho ʻia ma hope: ma kahi hoʻouka hou, e hana i papaʻa kumu a kali i ka māhele waihona aʻe (ʻaʻole i ʻoi aku ma mua o hoʻokahi minuke ke kākau ʻia nā mea), ma mua o ke koho ʻana i pahuhopu ma hope o ka papaʻa. Pono ka hoʻāʻo i Docker a me bash ma ka host; ʻaʻohe mea ʻē aʻe.
Hāʻule ka hoʻāʻo ke hāʻule kekahi ʻanuʻu:
Hiki ke hoʻihoʻi: hoʻi ka cluster hoʻāʻo i ka pahuhopu a wehe ʻia.
Piha: helu lālani o kēlā me kēia papaʻaina e hoʻohālikelike ʻia me ka waihona ola (tooling/restore-drill). Ua neʻe ka waihona ola ma hope o ka pahuhopu, no laila hiki i kekahi papaʻaina ke ʻokoʻa ma ka waiwai nui aʻe o 500 lālani a i ʻole ka hapaʻumi o kona nui, ma kēlā me kēia ʻaoʻao (hoʻemi nā kākau i nā mea i hoʻihoʻi ʻia; hoʻonui nā holoi ʻana); ʻaʻole helu ʻia kahi māhele i hana ʻia ma hope o ka pahuhopu he papaʻaina nalowale. E hoʻonui i ka ʻae ma kahi hoʻouka hana nui me QUIRE_DRILL_MAX_BEHIND a me QUIRE_DRILL_MAX_DRIFT_RATIO. Hāʻule ka papaʻaina i nele a i hoʻokaʻawale ʻia.
Pono: hōʻoia ʻia ke kaulahao hash hōʻoia ma ka kope i hoʻihoʻi ʻia.
Hiki ke hoʻohana: heluhelu ke kuleana polokalamu ma lalo o ka palekana pae-lālani.
Manawa: mai ka hoʻomaka a hiki i ka holomua, hoʻohālikelike ʻia me QUIRE_DRILL_RTO_SECONDS (3600 ma ke ʻano paʻamau).
ʻAʻole loa ia e kākau i ka waihona ola a me kona mau volume: kau ʻia nā volume papaʻa a WAL ma ke ʻano heluhelu wale nō, a holoi ʻia ke cluster hoʻāʻo i ka hopena, hala a hāʻule paha.
E hoʻonoho iā QUIRE_DRILL_REPORT i helu wahi e kākau ai i hōʻike JSON, inā hala a hāʻule paha; a holo ma ka papa manawa mai ka host Docker:
E holo i kēlā me kēia mahina a ma mua o kēlā me kēia hōʻano hou. Kāohi ka hoʻāʻo hāʻule i ka hōʻano hou. Hoʻokahi manawa i ka hapahā makahiki, e noi i kekahi mea ʻaʻole i kākau i kēia alakaʻi e hana i hoʻihoʻi manawa kikoʻī ma host pani me kēia palapala wale nō.
Nā faila
Noho nā faila kūloko ma ka volume files. E hana pū i papaʻa me ka waihona ʻikepili i ka manawa like, a hoʻihoʻi pū iā lāua:
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 .
Me ka waihona mea, hoʻā i ka mālama mana bucket a mālama i nā mana kahiko ʻole no 35 lā; na ka bucket ponoʻī ka hoʻihoʻi manawa kikoʻī o nā faila ma ia manawa.