---
title: "Nruab Quire nrog Docker Compose"
description: "Nruab Quire rau koj tus kheej infrastructure siv Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

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

# Nruab Quire nrog Docker Compose

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

Nov yog product puv khiav ntawm ib host: LMS, haujlwm tom qab, realtime thiab kev pab kho ntawv ua ke, thiab txhua optional service uas qhib ntawm profile. Tus qauv nyob ntu 2 hauv `docs/architecture/23-ops.md`.

Target ntxiv: [Vercel](/hmn/ops/vercel/) thiab [Cloudflare Workers](/hmn/ops/cloudflare/) khiav web tier xwb. Cov kev upgrade nyob hauv [upgrade.md](/hmn/ops/upgrade/), thiab thaub qab nrog restore drill nyob hauv [backup-restore.md](/hmn/ops/backup-restore/).

## Yam koj xav tau <!--quire:what-you-need-->

- Docker Engine 27 lossis tshiab dua nrog Compose plugin 2.30 lossis tshiab dua.
- 4 CPU core thiab 8 GB memory rau stack qub; 8 core thiab 16 GB nrog `--profile full` (ClamAV ib leeg tuav kwv yees 1.5 GB signatures).
- DNS npe rau web tier thiab npe thib ob rau ntsiab lus tsis ntseeg siab. Yuav tsum yog host txawv: SCORM package thiab HTML upload khiav ntawm content origin kom yeej nyeem tsis tau LMS cookies.
- Rau sim hauv zos, `lvh.me` thiab `*.localhost` taw rau 127.0.0.1, raws li `docker/.env.example` siv. Stack tus `proxy` service muab ob qho ntawm https nrog local certificate authority, ces tsis tas nruab lwm yam (saib “TLS”).
- Port 80 thiab 443 yuav tsum tsis siv ntawm host (`QUIRE_PROXY_HTTP_PORT` thiab `QUIRE_PROXY_HTTPS_PORT` hloov tau lawv).

## Khiav thawj zaug <!--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
```

`docker/scripts/init-env.sh` tsim `docker/.env` ntawm `docker/.env.example` thiab tsim txhua secret (database password, signing/master key, content launch key pair), nrog audit checkpoint signing key hauv `docker/secrets/audit-signing-key.pem`, uas Compose mount rau worker ua secret. Xav tau `sh`, `awk` thiab `openssl` xwb; tsis sau dhau `docker/.env` uas twb muaj. Luam ob ntaub ntawv tawm ntawm host: tsis muaj `QUIRE_MASTER_KEY`, database restore decrypt tsis tau credential khaws cia. Yog sau ntaub ntawv tes ua, siv `cp docker/.env.example docker/.env`; ntaub ntawv ntawd qhia yuav tsim secret twg.

Ob origin yuav tsum yog `https`: production content service tsis txais http dawb, thiab ob lub origin yuav tsum tsis koom registrable domain tib yam. `proxy` service xaus TLS rau ob qho (saib “TLS”); `init-env.sh` tsis txais origin `http://`.

Stack pib raws kev txiav txim ruaj, thiab txhua kauj ruam tos kauj ruam ua ntej:

1. `postgres` pib noj qab haus huv. Thawj zaug, init script (`docker/postgres/init/90-passwords.sh`) teeb plaub role password.
2. `migrate` siv txhua migration thiab nruab job queue hauv control database thiab txhua tenant database tshwj xeeb, xyuas kom lawv sib luag, ces tawm (saib docs/ops/upgrade.md). Migration khiav txhua zaus pib thiab idempotent, ces upgrade tsuas yog image tshiab thiab restart xwb.
3. `init` (`apps/web/src/first-run.ts`) teev application database hauv `QUIRE_DATABASE_ID`; yog teeb `QUIRE_SETUP_ADMIN_EMAIL`, kuj tsim thawj koom haum thiab nws tus thawj coj. Chaw nkag thiab password tsim cia luam ib zaug xwb hauv `docker compose logs init`.
4. Pib `web`, `content`, `worker`, `scheduler`, `collab` thiab `centrifugo`.
5. Pib `proxy` thaum `web` thiab `content` qhia noj qab haus huv.

Qhib `https://demo.` ntxiv rau domain app (daim log `init` qhia chaw nkag tiag) thiab nkag. Rau nruab local, tso siab rau proxy certificate authority ua ntej (saib “TLS”). Hloov password tsim cia ntawm `/account/security`.

Process uas pib tsis muaj secret yuav tsum tau tsis kam pib thiab qhia setting uas ploj hauv log. Tsis muaj yam pib ib nrab teeb xwb.

## Services thiab profiles <!--quire:services-and-profiles-->

| Service | Profile | Nws ua dab tsi |
| --- | --- | --- |
| postgres | ib txwm | Database (PostgreSQL 18 nrog pgvector, tsim ntawm `docker/postgres.Dockerfile`), archive WAL txij boot xub thawj |
| migrate, init | ib txwm | Khiav ib zaug: migration ces thawj zaug |
| web | ib txwm | LMS, ntawm `QUIRE_HTTP_PORT` (8080) |
| content | ib txwm | Content origin tsis ntseeg siab, ntawm `QUIRE_CONTENT_PORT` (8081) |
| worker | ib txwm | Background job: email, ntaub ntawv qhia, ua ntaub ntawv, webhook |
| scheduler | ib txwm | Job rov tshwm: sau npe 64 runtime schedule thiab xa rau worker; ib zaug muaj ib tug thawj coj xwb |
| collab | ib txwm | Collaborative editing websocket, ntawm `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | ib txwm | Realtime fan-out, ntawm `QUIRE_REALTIME_PORT` (8000) |
| proxy | ib txwm | Caddy, qhov rooj TLS ntawm port 80 thiab 443 (saib “TLS”) |
| valkey | `cache` | Cache thiab rate limit |
| clamav | `scan` | Kuaj malware hauv upload |
| gotenberg | `preview` | Office ua PDF saib ua ntej, tsim daim ntawv pov thawj |
| imgproxy | `images` | Hloov loj thiab format duab |
| transcoder | `video` | Worker image nrog ffmpeg siv LGPL xwb, ua video rendition |
| seaweedfs | `storage` | Object storage haum S3 ntawm host no |
| otelcol | `observability` | OpenTelemetry collector |
| mailpit | `devmail` | Txais txhua email xa tawm kom sim Quire |
| backup | `backup` | Base backup khiav ib zaug; saib backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | Base backup txhua `QUIRE_BACKUP_INTERVAL_HOURS` thiab luam foob tawm host nrog drill xyuas txhua lim tiam |
| h5p | `h5p` | H5P LTI 1.3 tool image uas koj muab hauv `QUIRE_H5P_IMAGE`, ntawm `QUIRE_H5P_PORT` (8090); saib “Txuas H5P provider” |

`--profile full` pib txhua optional service tsuas tsis suav `backup` thiab `h5p`. Pib ib qho nrog `docker compose -f docker/compose.yaml --profile scan up -d`. Yog tsis muaj optional service Quire tseem ua haujlwm thiab qhia yam ploj: tsis muaj scanner ces upload khaws tsis tau scan thiab ceeb toom thawj coj; tsis muaj Gotenberg ces muaj download xwb, tsis muaj preview; tsis muaj transcoder ces video ua si ua ntaub ntawv qub.

Muaj npe txhua third-party image thiab cov cai licence hauv `docker/third-party-containers.yaml`.

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

Quire tsis embed lossis xa H5P runtime/sidecar (ADR 0019). Yog siv H5P, muab koj tus hosted subscription lossis khiav koj tus H5P instance nyias ntawm Quire. Tso npe provider ua LTI 1.3 external tool thiab ntxiv nws cov ntsiab lus rau chav kawm ua tool activity. Quire pauv qhab nia thiab kev kawm tiav yam haujlwm/qhab nia ntawm LTI Assignment and Grade Services (AGS). Yog provider xa xAPI statements thiab, teeb nyias rau Quire xAPI statement store; AGS pauv qhab nia/nce qib tsis xa xAPI statements. Moodle import qhia H5P activity tias xav tau LTI tool connection. Provider tseem lav rau nws H5P runtime, authoring, content bank thiab keeb kwm sim.

Yog khiav koj tus H5P instance self-hosted ntawm host no, teeb `QUIRE_H5P_IMAGE` ua nws image thiab pib `h5p` profile. Compose publish ntawm `QUIRE_H5P_PORT` (8090) thiab khaws ntaub ntawv hauv `h5p-data` volume; image thiab nws cov luag num licence yog koj lub luag num.

## Chaw teeb tsa <!--quire:settings-->

Txhua process nyeem `docker/.env`. Template `docker/.env.example` teev txhua setting nrog nws tus nqi qub. Pawg muaj:

### Chaw nyob <!--quire:addresses-->

| Setting | Lub ntsiab lus |
| --- | --- |
| `QUIRE_APP_ORIGIN` | Chaw pej xeem ntawm LMS, xws li `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Content origin, yuav tsum yog host txawv |
| `QUIRE_PLATFORM_DOMAINS` | Domain uas koom haum nyob hauv, cais nrog comma |
| `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` | Ntawm no yog `compose`. Saib lwm phau ntawv rau `vercel` thiab `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Proxy uas ntseeg nws `X-Forwarded-For` |

### Secrets <!--quire:secrets-->

| Setting | Lub ntsiab lus |
| --- | --- |
| `QUIRE_SECRET_KEY` | Kos npe session thiab token. 64 cim hex |
| `QUIRE_MASTER_KEY` | Qhwv credential khaws cia xws li SSO thiab webhook secret. 32 byte, base64. Web tier thiab worker siv tus nqi tib yam. Hloov: [key-rotation.md](/hmn/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Cim version ntawm master key, yog tsis teeb ces `v1`. Nce thaum hloov key |
| `QUIRE_MASTER_KEY_RETIRED` | Master key qub tseem xav tau los nyeem yam nws qhwv, xws li `v1=<base64>`. Rho tom qab hloov tiav thiab tsis muaj yam daws tsis tau |
| `QUIRE_COLLAB_SIGNING_KEY` | Web thiab collab sib koom kos npe editing token |
| `QUIRE_BACKUP_SIGNING_KEY` | Kos npe course backup (xaiv tau) |

Khaws daim luam `QUIRE_MASTER_KEY` lwm qhov tsis yog host no. Database restore uas tsis muaj nws decrypt tsis tau credential khaws cia.

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

| Setting | Lub ntsiab lus |
| --- | --- |
| `POSTGRES_PASSWORD` | Superuser, siv los ntawm container thiab backup |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Role password, teeb thawj zaug pib |
| `DATABASE_URL` | Application role. Row-level security siv rau txhua query nws ua |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | Migrator role rau `migrate` thiab `init` |
| `QUIRE_SUPERUSER_URL` | Siv thawj zaug xwb |
| `QUIRE_REPORT_DATABASE_URL` | Report role nyeem xwb rau report thiab report builder |
| `QUIRE_AUDIT_DATABASE_URL` | Audit role rau audit console thiab SIEM export |
| `QUIRE_DATABASE_ID` | UUID twg los tau, nyob ruaj thaum install tseem siv |

Role password siv thaum tsim database volume thawj zaug xwb. Yuav hloov tom qab, siv `ALTER ROLE` ces hloov URL uas phim.

`QUIRE_REPORT_DATABASE_URL` siv rau physical database uas `DATABASE_URL` teeb. Rau physical database tso npe ntxiv, teeb nws tus kheej `quire_report` connection URL hauv web thiab worker environment, ces sau npe variable hauv teb **Reporting environment variable** ntawm database ua `env:NAME`. Reference yuav tsum taw rau database tib yam li app connection, zoo tshaj yog read replica. Txhua report surface raws tenant mus rau report connection ntawm nws database: report builder thiab report khaws, kev xa teem caij, report export, analytics, audit log, REST audit resource thiab audit search ntawm assistant. Tsis muaj ib qho siv report URL ntawm database txawv. Yog database tsis muaj report connection, report ib txwm khiav ntawm application connection ntawm database ntawd; analytics thiab audit nyeem tsis kam thiab qhia laj thawj, vim application role nyeem tsis tau audit trail.

### Drivers <!--quire:drivers-->

| Setting | Release no muaj | Lus qhia |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (qub), `s3` lossis `azure` | `local` khaws ntaub ntawv hauv `files` volume. `s3` siv tau AWS S3, R2, GCS interoperability thiab lwm store haum S3, txhawb multipart upload rov txuas tau |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (qub), `sse`, `centrifugo` lossis `durable_objects` | `inprocess` phim ib web container; siv `centrifugo` lossis `sse` thaum muaj ntau container |
| `QUIRE_CACHE_DRIVER` | `memory` (qub), `postgres` lossis `valkey` | `memory` cais raws process; siv `valkey` lossis `postgres` kom rate limit sib koom ntawm container |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (qub) lossis `progressive_mp4` | Lossis provider hosted: Cloudflare Stream, Mux lossis Bunny, siv lawv cov key |
| `QUIRE_IMAGE_DRIVER` | `noop` (qub), `imgproxy` lossis `cloudflare` | `noop` xa duab loj qub. `imgproxy` xav `images` profile thiab chaw hauv qab; `cloudflare` siv Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` lossis `in_process` | Provider qub rau kev sib ntsib nyob. Yog tsis teeb, kev sib ntsib qhia tias tseem tsis tau teeb txog thaum koom haum txuas nws tus as khauj hauv Integrations, Live session provider. Tus as khauj ntawm koom haum yeej qhov chaw no. Chaw ntawm provider (`BBB_URL` thiab `BBB_SECRET`, variable `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*` thiab `JITSI_*`) nyeem rau provider uas teev ntawm no xwb |
| `QUIRE_MEETING_REGIONS` | Daim npe comma ntawm `eu`, `uk`, `us` | Cheeb tsam uas provider qub ua kev sib ntsib. Yog tsis teeb, tsis kuaj piv rau koom haum pinned cheeb tsam li yav dhau los. As khauj ntawm koom haum teev nws cheeb tsam ntawm nws nplooj |

Tus nqi driver uas release no tsis muaj yuav raug tsis kam thaum web tier pib nrog npe setting ntawd, tsis txhob hloov ntsiag to mus tus qub.

### Duab <!--quire:images-->

Nplooj thov duab ntawm plaub qhov loj ruaj ntawm `/api/files/{id}/image/{size}`; qhov no kuaj cai nkag ib yam li ntaub ntawv thiab mam redirect rau image service. Ib lub koom haum thov tau `QUIRE_IMAGE_SPECS_PER_HOUR` duab thiab size khub tshiab ib teev (qhov qub 2000); yam uas twb tsim teev ntawd tsis suav. Thaum muaj web container ntau dua ib, siv `valkey` lossis `postgres` rau `QUIRE_CACHE_DRIVER` kom ciam sib koom.

| Setting | Driver | Lus qhia |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Chaw nyob browser nkag imgproxy, xws li `https://images.example.org`. `images` profile publish ntawm `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Hex string tib yam li thaum pib imgproxy. Tsim txhua tus nrog `openssl rand -hex 32`. Quire kos npe txhua image address siv lawv, ces imgproxy tsis tsim duab uas Quire tsis thov |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` nrog local storage | Chaw uas imgproxy rub duab qub. Compose teeb `http://web:3000`. Siv `s3` lossis `azure`, imgproxy rub ntawm bucket thiab tsis siv setting no |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | API token muaj Images edit permission, thiab account hash ntawm Images, Developer resources. Qhib flexible variants rau account |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Xaiv tau. Yog teeb, duab ntiag tug, txhua address kos npe thiab tas sijhawm. Yog tsis muaj, duab pej xeem ntawm address tsim los ntawm `QUIRE_SECRET_KEY` uas twv tsis tau |

Cloudflare Images khaws daim luam ntawm txhua duab qub uas nws xa. Thaum rho ntaub ntawv, worker rho daim luam ntawd ua ntej daim qub.

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

Background job siv pg-boss hauv Postgres database tib yam, ces tsis tas khiav queue service thiab tsis muaj dab tsi teeb. Tso job rau tib transaction nrog kev hloov uas ua rau nws tshwm, kom crash poob tsis tau job thiab xa tsis tau ob zaug. `QUIRE_QUEUE_DRIVER` yog `pgboss` ntawm no, tus qub; `vercel` thiab `cloudflare` tsuas txav light notification thiab webhook xa mus queue platform tus kheej xwb; phau Vercel thiab Cloudflare piav lawv thiab txoj kev web tier tso job.

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

Teem ib qho ntawm:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: JSON object qhia HTTP provider thiab credential, xws li `{"provider":"postmark","token":"..."}`. Txhawb Postmark, Amazon SES, Mailgun, SendGrid thiab Resend.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Target no xwb; serverless target thaiv SMTP.

`QUIRE_MAIL_FROM` yog tus xa. Yuav sim Quire, pib `devmail` profile, teem `QUIRE_SMTP_URL=smtp://mailpit:1025`, thiab nyeem email ntawm `http://localhost:8025`.

### Optional service <!--quire:optional-services-->

| Setting | Profile uas xav tau |
| --- | --- |
| `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` lossis `QUIRE_MEILISEARCH_URL` | Search sab nraud; tsis li siv Postgres full text |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Kuaj password xau. Raws qhov qub qhib ntawm `api.pwnedpasswords.com` (xa hash prefix tsib tus cim xwb); `off` tua, URL taw rau range API uas koj tswj |

### Kev saib xyuas <!--quire:observability-->

`OTEL_EXPORTER_OTLP_ENDPOINT` teev collector uas txhua process xa trace thiab metric; nrog `observability` profile yog `http://otelcol:4318`, thiab ntxiv exporter rau backend hauv `docker/otel-collector.yaml`. Web tier, worker, scheduler, content thiab collab xa span ntawm OTLP/HTTP (web request, tenant database transaction, worker job thiab hu tawm) thaum teeb; txhua feeb xa metric rau endpoint tib yam (`OTEL_METRICS_EXPORTER=none` tua lawv). `OTEL_TRACES_SAMPLER_ARG` teeb feem trace khaws. Log xa standard output ntawm `LOG_LEVEL`, Compose hloov log cia li. Trace yeej tsis muaj ntaub ntawv tus kheej.

### Kev xa tawm cheeb tsam (EU data residency) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` qhia tias stack pab European Union koom haum. Ces worker txwv txhua request tawm uas ua rau koom haum pinned EU rau allowlist (21-compliance.md ntu 8.1). Allowlist muaj host ntawm service teeb rau cheeb tsam (storage endpoint, email provider, video hosted, storage target ntawm koom haum, AI provider thiab email account), host ntawm service uas muaj derogation siv thiab cov host hauv `QUIRE_EGRESS_ALLOW_HOSTS`. Request mus public host twg ntxiv raug tsis kam ua ntej xa; teev qhov tsis kam hauv audit trail koom haum ua `privacy/egress_refused` thiab qhia hauv Compliance, Data residency.

| Setting | Tus nqi | Qhov tshwm |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Hostname cais comma lossis `*.example.org` rau subdomain txhua yam | Host ntxiv uas EU koom haum ncav tau. Webhook, xAPI, SIEM endpoint, blog feed thiab Amazon SES host yuav tsum nyob ntawm no vim koom haum xaiv lawv tus kheej thiab tsis muaj service twg teev. Loopback, private address thiab npe ib lo lus xws li `web` lossis `clamav` yog network koj tus kheej thiab yeej tsis kuaj |

UK thiab US koom haum tsis txwv raws host list; lawv tseem kuaj service cheeb tsam. Teeb list hauv worker; nplooj admin nyeem ntawm web tier los qhia allowlist, yog li tso hauv `docker/.env` uas txhua service nyeem.

Kev kuaj hauv application qhia error meej thiab audit entry, tiam sis qhov ntawd tsis yog kev lav: code yuam kev tau. Kev lav tiag yog network. Compose tsis yuam txoj cai no rau koj. Rau regional stack, tso `worker` thiab `web` services rau network `internal: true` uas tsuas muaj kev tawm ntawm egress proxy (xws li Squid lossis tinyproxy container) uas tso cai tib host li `QUIRE_EGRESS_ALLOW_HOSTS` ntxiv host ntawm service uas teeb, thiab teem `HTTPS_PROXY` rau cov service. Nplooj residency teev host meej uas application tso cai kom piv tau ob daim npe.

## Kev noj qab haus huv <!--quire:health-->

| Endpoint | Lub ntsiab lus |
| --- | --- |
| `/healthz` | Liveness: process teb. Compose health check siv qhov no |
| `/readyz` | Readiness: ncav dependency tau thiab qhia seb optional service twg teeb lawm. Taw load balancer rau ntawm no |

`docker compose -f docker/compose.yaml ps` qhia kev noj qab haus huv ntawm txhua service.

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

`proxy` service (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) yog ib feem ntawm stack qub. Nws teb ntawm port 80 thiab 443 thiab taw kev:

| Host lossis path | Taw rau |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, txhua tenant subdomain thiab custom domain | `web` |
| `/_collab/` ntawm cov host ntawd | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` ntawm cov host ntawd | client websocket ntawm `centrifugo`; server API yeej tsis qhib rau sab nraud |
| `/_images/` ntawm cov host ntawd | `imgproxy`, nrog `images` profile (`IMGPROXY_URL`) |

`init-env.sh` tsim `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`, `QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` thiab `IMGPROXY_URL` raws ob origin, kom tsis txhob sib txawv. Yog hloov origin tes ua, hloov txhua qhov ua ke.

Certificate xaiv raws `QUIRE_PROXY_TLS`:

- `internal` (qhov qub): Caddy tus certificate authority rau `localhost`, `*.localhost` thiab `lvh.me`. Tso siab rau root ib zaug, ces luam:

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

  Ntxiv `quire-local-ca.crt` rau system lossis browser trust store. `curl` txais nws nrog `--cacert`.
- Chaw email: ACME certificate cia li (Let's Encrypt, ces ZeroSSL) rau hostname tiag. DNS rau ob origin thiab txhua tenant host yuav tsum taw ntawm no; internet yuav tsum ncav port 80 thiab 443.

Tenant host tau certificate thaum xub qhib xwb, thiab tsuas thaum web lees tias npe yog ntawm qhov kev nruab no (`/tls-allowed`, nug ntawm Compose network). Tsis xav wildcard certificate lossis DNS provider plugin; tus neeg txawv uas taw npe rau host tsis yuam tau daim certificate. Certificate thiab authority local nyob hauv `caddy-data` volume; yog siv `internal`, thaub qab nrog lwm yam.

Web ntseeg `X-Forwarded-For` ntawm proxy xwb: proxy muaj chaw nyob ruaj (`QUIRE_PROXY_ADDRESS`, qhov qub `172.29.64.10`) hauv subnet ruaj (`QUIRE_COMPOSE_SUBNET`), thiab `QUIRE_TRUSTED_PROXY_CIDRS` teev chaw ntawd. Yog subnet sib tsoo network ntawm host, hloov ob qho thiab khiav `docker compose down` ua ntej `up`.

## Qab reverse proxy koj tus kheej <!--quire:behind-your-own-reverse-proxy-->

Yuav siv load balancer lossis proxy uas koj twb muaj, tsis txhob pib `proxy` (`docker compose up -d --scale proxy=0`) thiab xaus TLS ua ntej mus rau `web` (8080), `content` (8081), `collab` (1234, websocket) thiab `centrifugo` (8000, websocket). Teeb chaw pej xeem hauv `QUIRE_APP_ORIGIN`, `QUIRE_CONTENT_ORIGIN` thiab `QUIRE_COLLAB_URL` (`wss://`), thiab ntau chaw nyob proxy hauv `QUIRE_TRUSTED_PROXY_CIDRS`.

## Kho teeb meem <!--quire:troubleshooting-->

- `init` tawm nrog “QUIRE_DATABASE_ID is not a UUID”: teem nws siv `uuidgen`.
- `web` rov pib nrog “did not start on compose”: log teev setting uas nws siv tsis tau thiab yam yuav hloov.
- Hloov role password hauv `.env` tom qab thawj zaug tsis ua dab tsi: init script khiav ib zaug xwb. Siv `ALTER ROLE`.
- Upload tsis dhau vim scan yuam kev thaum teeb `CLAMAV_URL`: ClamAV rub signature thawj zaug pib, siv sijhawm ob peb feeb.

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