---
title: "Pag-install ng Quire gamit ang Docker Compose"
description: "I-install ang Quire sa sarili mong imprastraktura gamit ang Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/fil/llms.txt
> Use this file to discover all available pages before exploring further.

# Pag-install ng Quire gamit ang Docker Compose

<span id="installing-quire-with-docker-compose"></span>

Ito ang buong produkto sa iisang host: ang LMS, mga trabahong pang-background nito,
mga serbisyo para sa realtime at collaborative editing, at bawat opsyonal na serbisyong
nasa ilalim ng profile. Nasa seksiyon 2 ng `docs/architecture/23-ops.md` ang disenyo.

Iba pang target: web tier lamang ang pinapatakbo ng [Vercel](/fil/ops/vercel/) at
[Cloudflare Workers](/fil/ops/cloudflare/). Nasa [upgrade.md](/fil/ops/upgrade/) ang mga upgrade,
at nasa [backup-restore.md](/fil/ops/backup-restore/) ang mga backup at restore drill.

## Mga kailangan <!--quire:what-you-need-->

- Docker Engine 27 o mas bago, kasama ang Compose plugin 2.30 o mas bago.
- 4 na CPU core at 8 GB memory para sa default na stack; 8 core at 16 GB
  kapag ginamit ang `--profile full` (may hawak na humigit-kumulang 1.5 GB ng mga signature ang ClamAV lamang).
- Isang DNS name para sa web tier at isa pa para sa hindi pinagkakatiwalaang content.
  Dapat magkaibang host ang mga ito: tumatakbo sa content origin ang SCORM package at
  na-upload na HTML upang hindi nila mabasa kailanman ang cookies ng LMS.
- Para sa lokal na pagsubok, tumuturo ang `lvh.me` at `*.localhost` sa 127.0.0.1,
  gaya ng ginagamit ng `docker/.env.example`. Naghahain ang sariling `proxy` service
  ng stack sa dalawa gamit ang https at lokal na certificate authority, kaya walang
  ibang kailangang i-install (tingnan ang "TLS").
- Dapat bakante sa host ang mga port 80 at 443 (maililipat ng `QUIRE_PROXY_HTTP_PORT`
  at `QUIRE_PROXY_HTTPS_PORT` ang mga ito).

## Unang pagpapatakbo <!--quire:first-run-->

```sh
QUIRE_APP_ORIGIN=https://learn.example.org \
QUIRE_CONTENT_ORIGIN=https://content.example-content.org \
QUIRE_SETUP_ADMIN_EMAIL=you@example.org \
  docker/scripts/init-env.sh
docker compose -f docker/compose.yaml up -d --build
docker compose -f docker/compose.yaml logs init
```

Gumagawa ang `docker/scripts/init-env.sh` ng `docker/.env` mula sa `docker/.env.example`
at bumubuo ng bawat secret (mga password ng database, signing at master key,
at key pair para sa content launch), pati ang audit checkpoint signing key sa
`docker/secrets/audit-signing-key.pem`, na mina-mount ng Compose sa mga worker bilang secret.
`sh`, `awk` at `openssl` lamang ang kailangan nito, at tumatanggi itong patungan
ang umiiral nang `docker/.env`. Kopyahin sa labas ng host ang dalawang file: kung wala
ang `QUIRE_MASTER_KEY`, hindi maide-decrypt ng na-restore na database ang mga kredensiyal
na nakaimbak dito. Para punan ang file nang mano-mano, gamitin ang
`cp docker/.env.example docker/.env`; nakasaad sa file kung paano buuin ang bawat secret.

Dapat `https` ang dalawang origin: tumatanggi ang content service sa plain http sa
production, at hindi dapat magkapareho ang registrable domain ng mga ito. Tinatapos ng
`proxy` service ang TLS para sa dalawa (tingnan ang "TLS"); tumatanggi ang `init-env.sh`
sa `http://` origin.

Nagsisimula ang stack sa nakapirming pagkakasunod-sunod, at hinihintay ng bawat hakbang
ang nauna rito:

1. Nagiging healthy ang `postgres`. Sa pinakaunang pagsisimula, itinatakda ng init script nito
   (`docker/postgres/init/90-passwords.sh`) ang apat na password ng role.
2. Inilalapat ng `migrate` ang lahat ng migration at sinisimulan ang job queue sa control
   database at sa bawat nakalaang tenant database, tinitiyak na magkakatugma ang lahat,
   saka humihinto (docs/ops/upgrade.md). Tumatakbo ang mga migration sa bawat pagsisimula
   at idempotent ang mga ito, kaya bagong image at restart ang upgrade.
3. Itinatala ng `init` (`apps/web/src/first-run.ts`) ang application database sa ilalim
   ng `QUIRE_DATABASE_ID` at, kapag nakatakda ang `QUIRE_SETUP_ADMIN_EMAIL`, ginagawa ang
   unang organisasyon at administrator nito. Minsan lang inilalabas ang address sa pag-sign in
   at nabuong password sa `docker compose logs init`.
4. Nagsisimula ang `web`, `content`, `worker`, `scheduler`, `collab` at `centrifugo`.
5. Nagsisimula ang `proxy` kapag healthy na ang `web` at `content`.

Buksan ang `https://demo.` na sinusundan ng domain ng application mo (ipinapakita ng
`init` log ang eksaktong address sa pag-sign in), at mag-sign in. Sa lokal na install,
pagkatiwalaan muna ang certificate authority ng proxy (tingnan ang "TLS"). Palitan
ang nabuong password sa `/account/security`.

Tumatangging magsimula ang prosesong walang kinakailangang secret at ipinapangalan sa log
ang nawawalang setting. Walang bahaging nagsisimula nang kulang ang configuration.

## Mga serbisyo at profile <!--quire:services-and-profiles-->

| Serbisyo | Profile | Gawain |
| --- | --- | --- |
| postgres | always | Database (PostgreSQL 18 na may pgvector, binubuo mula sa `docker/postgres.Dockerfile`), naka-archive ang WAL mula sa unang boot |
| migrate, init | always | Isahang pagpapatakbo: mga migration, saka unang pagsisimula |
| web | always | Ang LMS, sa `QUIRE_HTTP_PORT` (8080) |
| content | always | Origin ng hindi pinagkakatiwalaang content, sa `QUIRE_CONTENT_PORT` (8081) |
| worker | always | Mga trabahong pang-background: email, report, pagproseso ng file, webhook |
| scheduler | always | Mga paulit-ulit na trabaho: nirerehistro ang 64 runtime schedule at ipinapasa sa worker; iisa lang ang leader sa bawat pagkakataon |
| collab | always | Websocket para sa collaborative editing, sa `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | always | Realtime fan-out, sa `QUIRE_REALTIME_PORT` (8000) |
| proxy | always | Caddy, TLS front door sa mga port 80 at 443 (tingnan ang "TLS") |
| valkey | `cache` | Cache at mga limitasyon sa rate |
| clamav | `scan` | Pagsusuri ng malware sa mga upload |
| gotenberg | `preview` | Mga preview ng Office sa PDF, pag-render ng certificate |
| imgproxy | `images` | Mga larawang binago ang laki at format |
| transcoder | `video` | Worker image na may ffmpeg na LGPL-only, para sa rendition ng video |
| seaweedfs | `storage` | S3-compatible na object storage sa host na ito |
| otelcol | `observability` | OpenTelemetry collector |
| mailpit | `devmail` | Sumasalo sa lahat ng papalabas na mail para masubukan ang Quire |
| backup | `backup` | Isahang base backup; tingnan ang backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | Base backup bawat `QUIRE_BACKUP_INTERVAL_HOURS`, at mga naka-encrypt na kopyang nasa labas ng host na may lingguhang verification drill |
| h5p | `h5p` | H5P LTI 1.3 tool image na ibibigay mo sa `QUIRE_H5P_IMAGE`, sa `QUIRE_H5P_PORT` (8090); tingnan ang "Pagkonekta ng H5P provider" |

Sinisimulan ng `--profile full` ang lahat ng opsyonal na serbisyo maliban sa `backup`
at `h5p`. Simulan ang isa gamit ang `docker compose -f docker/compose.yaml --profile scan up -d`.
Gumagana pa rin ang Quire nang walang opsyonal na serbisyo at ipinapaalam nito kung ano ang wala:
kapag walang scanner, hindi sinusuri ang mga nakaimbak na upload at ipinapaalam ito sa
administrator; kapag walang Gotenberg, download sa halip na preview ang iniaalok para sa mga file;
kapag walang transcoder, orihinal na file ang pinapatugtog na video.

Nakalista sa `docker/third-party-containers.yaml` ang bawat third-party image at mga obligasyon
sa lisensiya nito.

### Pagkonekta ng H5P provider <!--quire:connecting-an-h5p-provider-->

Hindi nag-e-embed o nagsasama ang Quire ng H5P runtime o sidecar (ADR 0019). Kung gagamit ka
ng H5P, magbigay ng sarili mong hosted subscription o magpatakbo ng sarili mong self-hosted
na H5P instance nang hiwalay sa Quire. Irehistro ang provider bilang LTI 1.3 external tool
at idagdag ang content nito sa mga kurso bilang tool activity. Nagpapalitan ang Quire ng mga
marka at progreso ng activity/pagmamarka sa pamamagitan ng LTI Assignment and Grade Services
(AGS). Kung nagpapadala rin ng xAPI statement ang provider, isaayos iyon nang hiwalay para sa
xAPI statement store ng Quire; hindi nagpapadala ng xAPI statement ang pagpapalitan ng grado
at progreso sa AGS. Iniuulat ng Moodle import na kailangan ng H5P activity ng koneksiyon sa
LTI tool. Nananatiling pananagutan ng provider ang H5P runtime, pag-akda, content bank at
kasaysayan ng pagsubok nito.

Para magpatakbo ng sarili mong self-hosted instance sa host na ito, itakda ang `QUIRE_H5P_IMAGE`
sa image nito at simulan ang `h5p` profile. Inilalathala ito ng Compose sa `QUIRE_H5P_PORT`
(8090) at iniimbak ang data nito sa `h5p-data` volume; sa iyo pa rin ang image at mga obligasyon nito.

## Mga setting <!--quire:settings-->

Binabasa ng bawat proseso ang `docker/.env`. Inililista sa template na `docker/.env.example`
ang bawat setting at default nito. Narito ang mga pangkat:

### Mga address <!--quire:addresses-->

| Setting | Kahulugan |
| --- | --- |
| `QUIRE_APP_ORIGIN` | Pampublikong address ng LMS, gaya ng `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Origin ng content, sa ibang host |
| `QUIRE_PLATFORM_DOMAINS` | Mga domain kung saan nakatira ang mga organisasyon, pinaghiwalay ng kuwit |
| `QUIRE_MARKETING_ORIGIN` | Optional. The marketing site, default `https://quirelms.com`. The only origin the waitlist form (`POST /api/waitlist`, `POST /waitlist`) accepts and redirects to. Comma separated; a `www.` variant is allowed only if listed |
| `QUIRE_DEPLOY_TARGET` | `compose` dito. Tingnan ang ibang gabay para sa `vercel` at `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Mga proxy na pinagkakatiwalaan ang `X-Forwarded-For` nila |

### Mga lihim <!--quire:secrets-->

| Setting | Kahulugan |
| --- | --- |
| `QUIRE_SECRET_KEY` | Lumalagda sa mga session at token. 64 na hex character |
| `QUIRE_MASTER_KEY` | Binabalot ang nakaimbak na kredensiyal gaya ng SSO at webhook secret. 32 byte, base64. Dapat iisa ang value sa web tier at worker. Rotation: [key-rotation.md](/fil/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Label ng bersiyon ng master key, `v1` kung hindi nakatakda. Itaas ito kapag nag-rotate ka |
| `QUIRE_MASTER_KEY_RETIRED` | Mga naunang master key na kailangan pa para mabasa ang mga nilagdaan ng mga ito, bilang `v1=<base64>`. Alisin kapag kumpleto na ang rotation at wala nang hindi nalulutas |
| `QUIRE_COLLAB_SIGNING_KEY` | Ibinabahagi ng web at collab para lumagda sa mga editing token |
| `QUIRE_BACKUP_SIGNING_KEY` | Lumalagda sa mga backup ng kurso (opsyonal) |

Magtabi ng kopya ng `QUIRE_MASTER_KEY` sa ibang lugar maliban sa host na ito. Hindi
maide-decrypt ng database na na-restore nang wala ito ang mga kredensiyal na laman nito.

### Database <!--quire:database-->

| Setting | Kahulugan |
| --- | --- |
| `POSTGRES_PASSWORD` | Superuser, ginagamit ng container at mga backup |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Mga password ng role, itinatakda sa unang pagsisimula |
| `DATABASE_URL` | Application role. Ipinapatupad ang row-level security sa bawat query nito |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | Migrator role, para sa `migrate` at `init` |
| `QUIRE_SUPERUSER_URL` | Ginagamit lamang sa unang pagsisimula |
| `QUIRE_REPORT_DATABASE_URL` | Read-only report role, para sa mga report at report builder |
| `QUIRE_AUDIT_DATABASE_URL` | Audit role, para sa audit console at SIEM export |
| `QUIRE_DATABASE_ID` | Anumang UUID, hindi nagbabago habang ginagamit ang install |

Sa unang paglikha lang ng database volume inilalapat ang mga password ng role.
Para palitan ang isa sa mga ito sa susunod, gamitin ang `ALTER ROLE`, saka i-update
ang katugmang URL.

Ginagamit ang `QUIRE_REPORT_DATABASE_URL` para sa pisikal na database na itinakda ng
`DATABASE_URL`. Para sa iba pang nakarehistrong pisikal na database, itakda ang sarili nitong
`quire_report` connection URL sa environment ng web at worker, saka ilagay ang pangalan ng
variable sa field na **Reporting environment variable** ng database bilang `env:NAME`.
Dapat tumukoy ang sanggunian sa kaparehong database ng app connection nito, pinakamainam kung
read replica. Sinusundan ng bawat report surface ang tenant papunta sa report connection ng
sarili nitong database: report builder at mga naka-save na report, naka-iskedyul na delivery,
report export, analytics, audit log, REST audit resource at paghahanap ng assistant sa audit.
Hindi kailanman ginagamit ng mga ito ang report URL ng ibang database. Kapag walang report
connection ang database, tumatakbo ang karaniwang report gamit ang sarili nitong application
connection; tumatanggi naman ang analytics at bawat audit read at sinasabi ang dahilan,
dahil hindi mabasa ng application role ang audit trail.

### Mga driver <!--quire:drivers-->

| Setting | Kasama sa release na ito | Mga tala |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (default), `s3` o `azure` | Iniimbak ng `local` ang mga file sa `files` volume. Saklaw ng `s3` ang AWS S3, R2, GCS interoperability at iba pang S3-compatible na store, kasama ang resumable multipart upload |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (default), `sse`, `centrifugo` o `durable_objects` | Tama ang `inprocess` para sa iisang web container; gamitin ang `centrifugo` o `sse` kapag marami ang mga ito |
| `QUIRE_CACHE_DRIVER` | `memory` (default), `postgres` o `valkey` | Para sa bawat proseso ang `memory`; gamitin ang `valkey` o `postgres` upang umiral sa lahat ng container ang mga limitasyon sa rate |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (default) o `progressive_mp4` | O gumamit ng hosted provider: Cloudflare Stream, Mux o Bunny, gamit ang mga key nito |
| `QUIRE_IMAGE_DRIVER` | `noop` (default), `imgproxy` o `cloudflare` | Inihahain ng `noop` ang bawat larawan sa orihinal nitong laki. Kailangan ng `imgproxy` ang `images` profile at mga setting sa ibaba; gumagamit naman ang `cloudflare` ng Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` o `in_process` | Default na provider ng platform para sa mga live session. Kapag hindi nakatakda, sinasabing hindi naka-configure ang mga live session hanggang ikonekta ng organisasyon ang sarili nitong account sa Integrations, Live session provider. Laging nangingibabaw ang sariling account ng organisasyon sa value na ito. Binabasa lang ang setting ng bawat provider (`BBB_URL` at `BBB_SECRET`, mga variable na `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*` at `JITSI_*`) para sa provider na pinangalanan dito |
| `QUIRE_MEETING_REGIONS` | Listahan ng `eu`, `uk`, `us` na pinaghiwalay ng kuwit | Mga rehiyon kung saan pinoproseso ng default na provider ng platform ang mga meeting. Kapag hindi nakatakda, hindi ito sinusuri laban sa organisasyong nakatalaga sa isang rehiyon, gaya ng dati. Nakasaad sa pahina ng organisasyon ang mga rehiyon ng sarili nitong account |

Tumatanggi ang web tier sa pagsisimula kapag wala sa release na ito ang value ng driver,
at ipinapangalan ang setting sa halip na tahimik itong palitan ng default.

### Mga larawan <!--quire:images-->

Humihingi ang mga pahina ng larawan sa apat na nakapirming laki sa pamamagitan ng
`/api/files/{id}/image/{size}`, na sumusuri sa parehong access gaya ng mismong file
at saka nagre-redirect sa serbisyo ng larawan. Bawat organisasyon ay maaaring humiling ng
`QUIRE_IMAGE_SPECS_PER_HOUR` (default 2000) na bagong pares ng larawan at laki bawat oras;
hindi binibilang ang mga laki na nagawa na sa oras na iyon. Gamitin ang `valkey` o
`postgres` para sa `QUIRE_CACHE_DRIVER` kapag higit sa isa ang web container upang gumana
ang limitasyon sa lahat ng ito.

| Setting | Driver | Mga tala |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Address na maaabot ng browser sa imgproxy, halimbawa `https://images.example.org`. Inilalathala ito ng `images` profile sa `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Mga hex string, kapareho ng mga value na sinisimulan ng imgproxy. Buuin ang bawat isa gamit ang `openssl rand -hex 32`. Nilalagdaan ng Quire ang bawat address ng larawan gamit ang mga ito kaya walang nire-render ang imgproxy na hindi hiniling ng Quire |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` na may lokal na storage | Pinagkukunan ng imgproxy ng mga orihinal. Itinatakda ng Compose ang `http://web:3000`. Sa `s3` o `azure` na storage, kumukuha ang imgproxy mula sa bucket at hindi ito ginagamit |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | API token na may pahintulot na mag-edit ng Images at account hash mula sa Images, Developer resources. I-on ang flexible variant para sa account |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Opsyonal. Kapag nakatakda, pribado ang mga larawan at nilalagdaan at pinapaso ang bawat address. Kung wala ito, pampubliko ang mga larawan sa mga address na hinango sa `QUIRE_SECRET_KEY` na walang makahuhula |

Iniingatan ng Cloudflare Images ang sarili nitong kopya ng bawat orihinal na inihahain nito.
Kapag binura ang file, binubura muna ng worker ang kopyang iyon bago ang orihinal.

### Queue <!--quire:queue-->

Gumagamit ng pg-boss ang mga trabahong pang-background sa kaparehong Postgres database,
kaya walang queue service na kailangang patakbuhin o i-configure. Isinasabay sa transaction
ng pagbabagong nagdulot sa mga ito ang paglalagay sa queue, kaya hindi mawawala o madodoble
ang trabaho dahil sa pag-crash. `QUIRE_QUEUE_DRIVER` ay `pgboss` bilang default dito; inililipat
ng `vercel` at `cloudflare` ang magagaang notification at webhook delivery lamang sa sariling
queue ng platform. Inilalarawan ng mga gabay sa Vercel at Cloudflare ang mga ito at kung paano
naglalagay sa queue ang kanilang web tier.

### Email <!--quire:email-->

Itakda ang isa sa mga ito:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: JSON object na nagpapangalan ng HTTP provider at mga kredensiyal
  nito, gaya ng `{"provider":"postmark","token":"..."}`. Sinusuportahan ang Postmark,
  Amazon SES, Mailgun, SendGrid at Resend.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Para lamang sa target na ito; hinaharang ng
  mga serverless target ang SMTP.

Ang `QUIRE_MAIL_FROM` ang address ng nagpadala. Para subukan ang Quire, simulan ang `devmail`
profile, itakda ang `QUIRE_SMTP_URL=smtp://mailpit:1025`, at tingnan ang mail sa
`http://localhost:8025`.

### Mga opsyonal na serbisyo <!--quire:optional-services-->

| Setting | Gamit ang profile |
| --- | --- |
| `CLAMAV_URL=tcp://clamav:3310` | `scan` |
| `GOTENBERG_URL=http://gotenberg:3000` | `preview` |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `images` |
| `VALKEY_URL=redis://valkey:6379` | `cache` |
| `QUIRE_OPENSEARCH_URL` o `QUIRE_MEILISEARCH_URL` | Panlabas na search; full text sa Postgres kung wala |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Pagsusuri kung nalantad sa paglabag ang password. Naka-on bilang default laban sa `api.pwnedpasswords.com` (limang character lang ng hash prefix ang ipinapadala); isinasara ito ng `off`, at tumuturo ang URL sa range API na ikaw ang nagho-host |

### Pagmamasid <!--quire:observability-->

Tinutukoy ng `OTEL_EXPORTER_OTLP_ENDPOINT` ang collector na pinagdadalhan ng bawat proseso
ng trace at metric; kapag ginagamit ang `observability` profile, ito ay `http://otelcol:4318`,
at sa `docker/otel-collector.yaml` idinadagdag ang exporter para sa backend mo. Nag-e-export
ng span sa OTLP/HTTP ang mga proseso ng web tier, worker, scheduler, content at collab kapag
nakatakda ito (mga web request, tenant database transaction, worker job at papalabas na tawag),
pati metric sa parehong endpoint bawat minuto (`OTEL_METRICS_EXPORTER=none` ang nagsasara sa
mga ito). Itinatakda ng `OTEL_TRACES_SAMPLER_ARG` ang bahagdan ng mga trace na itinatago.
Pumupunta sa standard output ang log sa `LOG_LEVEL`, at iniikot ito ng Compose. Walang
personal na data sa mga trace.

### Panrehiyong egress (residensiya ng data sa EU) <!--quire:regional-egress-eu-data-residency-->

Ipinapahiwatig ng `QUIRE_REGION=eu` na nagsisilbi ang stack sa mga organisasyon sa European Union.
Nililimitahan ng worker sa allowlist ang bawat papalabas na request para sa organisasyong nakatalaga
sa EU (21-compliance.md seksiyon 8.1). Kabilang sa allowlist ang mga host na idineklara para sa
rehiyon ng mga naka-configure na serbisyo (storage endpoint, email provider, hosted video provider,+sariling storage target ng organisasyon, AI provider at email account), mga host ng anumang serbisyong
nasa ilalim ng aktibong derogation, at mga host na inilista mo sa `QUIRE_EGRESS_ALLOW_HOSTS`.
Bago ipadala, tinatanggihan ang request sa iba pang pampublikong host; itinatala ang pagtanggi
sa audit trail ng organisasyon bilang `privacy/egress_refused` at inililista sa Compliance,
Data residency.

| Setting | Mga value | Epekto |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Listahan ng hostname na pinaghiwalay ng kuwit, o `*.example.org` para sa lahat ng subdomain | Mga karagdagang host na maaaring puntahan ng organisasyon sa EU. Dito dapat ilagay ang webhook, xAPI at SIEM endpoint, blog feed at Amazon SES host dahil sariling pinili ito ng organisasyon at walang serbisyong nagdedeklara sa mga ito. Sarili mong network ang loopback, pribadong address at iisang-label na pangalan gaya ng `web` o `clamav`, at hindi kailanman sinusuri ang mga ito |

Hindi nililimitahan sa listahan ng host ang mga organisasyon sa UK at US; nananatili ang pagsusuri
sa rehiyon ng serbisyo. Itakda ang listahan sa worker; binabasa ito ng admin page sa web tier
upang ipakita ang allowlist, kaya ilagay ito sa `docker/.env` na binabasa ng bawat serbisyo.

Nagbibigay ng malinaw na error at audit entry ang pagsusuri ng application, pero hindi ito ang
garantiya: maaaring mali ang code. Network ang garantiya. Hindi ito ipinapatupad ng Compose
para sa iyo. Para sa panrehiyong stack, ilagay ang mga serbisyong `worker` at `web` sa network
na `internal: true` na ang tanging labasan ay egress proxy (halimbawa, Squid o tinyproxy container)
na nagpapahintulot sa parehong host gaya ng `QUIRE_EGRESS_ALLOW_HOSTS` pati sa mga host ng
naka-configure mong serbisyo, at itakda ang `HTTPS_PROXY` para sa mga serbisyong iyon. Inililista
ng residency page ang eksaktong mga host na pinapayagan ng application upang maikumpara ang dalawang
listahan.

## Kalusugan <!--quire:health-->

| Endpoint | Kahulugan |
| --- | --- |
| `/healthz` | Liveness: sumasagot ang proseso. Ito ang ginagamit sa health check ng Compose |
| `/readyz` | Readiness: naaabot ang mga dependency at iniulat kung naka-configure o hindi ang bawat opsyonal na serbisyo. Ituro rito ang load balancer mo |

Ipinapakita ng `docker compose -f docker/compose.yaml ps` ang kalusugan ng bawat serbisyo.

## TLS <!--quire:tls-->

Bahagi ng default na stack ang `proxy` service (Caddy, Apache-2.0,
`docker/caddy/Caddyfile`). Sumasagot ito sa mga port 80 at 443 at niruruta ang:

| Host o path | Papunta sa |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, bawat tenant subdomain at custom domain | `web` |
| `/_collab/` sa mga host na iyon | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` sa mga host na iyon | client websocket ng `centrifugo`; hindi inilalantad kailanman ang server API nito |
| `/_images/` sa mga host na iyon | `imgproxy`, gamit ang `images` profile (`IMGPROXY_URL`) |

Hinango ng `init-env.sh` ang `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`,
`QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` at `IMGPROXY_URL` mula sa dalawang
origin upang hindi magkahiwalay ang mga value ng mga ito. Sabay-sabay na i-edit ang mga ito
kung mano-mano mong babaguhin ang isang origin.

Sumusunod ang mga certificate sa `QUIRE_PROXY_TLS`:

- `internal` (ang default): sariling certificate authority ng Caddy, para sa
  `localhost`, `*.localhost` at `lvh.me`. Pagkatiwalaan nang isang beses ang root nito,
  saka mag-browse:

  ```sh
  docker compose -f docker/compose.yaml cp \
    proxy:/data/caddy/pki/authorities/local/root.crt ./quire-local-ca.crt
  ```

  Idagdag ang `quire-local-ca.crt` sa trust store ng system o browser. Tumatanggap ang `curl`
  nito sa pamamagitan ng `--cacert`.
- Email address: awtomatikong ACME certificate (Let's Encrypt, saka ZeroSSL) para sa
  totoong hostname. Dapat nakaturo rito ang DNS ng dalawang origin at bawat tenant host,
  at dapat maabot mula sa internet ang mga port 80 at 443.

Inilalabas ang mga certificate para sa tenant host kapag unang binisita ito at kapag kinumpirma
lamang ng web na kabilang ang pangalan sa install na ito (`/tls-allowed`, hinihiling sa Compose
network). Hindi kailangan ang wildcard certificate o DNS provider plugin, at hindi makakapagpahiling
ng certificate ang estrangherong nagtuturo ng pangalan sa host. Nakatira sa `caddy-data` volume
ang mga certificate at lokal na authority; i-backup ito kasama ng iba kung gumagamit ka ng `internal`.

Ang proxy lamang ang pinaniniwalaan ng web para sa `X-Forwarded-For`: nakapirmi ang address ng
proxy (`QUIRE_PROXY_ADDRESS`, default `172.29.64.10`) sa nakapirming subnet (`QUIRE_COMPOSE_SUBNET`),
at pinapangalanan ng `QUIRE_TRUSTED_PROXY_CIDRS` ang address na iyon. Kung sumasalungat ang subnet
sa isang network sa host, palitan ang dalawa at patakbuhin ang `docker compose down` bago ang `up`.

## Sa likod ng sarili mong reverse proxy <!--quire:behind-your-own-reverse-proxy-->

Para gumamit sa halip ng load balancer o proxy na pinapatakbo mo na, huwag isama ang `proxy`
(`docker compose up -d --scale proxy=0`) at tapusin ang TLS sa harap ng `web` (8080),
`content` (8081), `collab` (1234, websocket) at `centrifugo` (8000, websocket). Itakda ang
mga pampublikong address sa `QUIRE_APP_ORIGIN`, `QUIRE_CONTENT_ORIGIN` at `QUIRE_COLLAB_URL`
(`wss://`), at hanay ng address ng proxy sa `QUIRE_TRUSTED_PROXY_CIDRS`.

## Pag-troubleshoot <!--quire:troubleshooting-->

- Hihinto ang `init` na may "QUIRE_DATABASE_ID is not a UUID": itakda ito gamit ang `uuidgen`.
- Paulit-ulit na nagre-restart ang `web` na may "did not start on compose": inililista ng log
  ang bawat setting na hindi nito matutupad at kung ano ang dapat gamitin sa halip.
- Walang epekto ang pagpapalit ng password ng role sa `.env` pagkatapos ng unang pagsisimula:
  minsan lang tumatakbo ang init script. Gamitin ang `ALTER ROLE`.
- Nabibigo ang mga upload sa error sa scan habang nakatakda ang `CLAMAV_URL`: dina-download
  ng ClamAV ang mga signature sa unang pagsisimula at tumatagal ito nang ilang minuto.

Source: https://docs.quirelms.com/fil/ops/install/index.mdx
