---
title: "Instal·lar Quire amb Docker Compose"
description: "Instal·leu Quire a la vostra infraestructura amb Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

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

# Instal·lar Quire amb Docker Compose

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

Aquest és el producte complet en un sol host: l’LMS, les tasques en segon
pla, els serveis de temps real i d’edició col·laborativa i tots els serveis
opcionals darrere d’un perfil. El disseny es descriu a la secció 2 de
`docs/architecture/23-ops.md`.

Altres opcions: [Vercel](/ca/ops/vercel/) i [Cloudflare Workers](/ca/ops/cloudflare/)
executen només la capa web. Les actualitzacions es descriuen a
[upgrade.md](/ca/ops/upgrade/), i les còpies de seguretat i el simulacre de restauració
a [backup-restore.md](/ca/ops/backup-restore/).

## Requisits <!--quire:what-you-need-->

- Docker Engine 27 o posterior, amb el connector Compose 2.30 o posterior.
- 4 nuclis de CPU i 8 GB de memòria per al stack predeterminat; 8 nuclis i
  16 GB amb `--profile full` (ClamAV ocupa tot sol aproximadament 1,5 GB de
  signatures).
- Un nom DNS per a la capa web i un altre per al contingut no fiable. Han de
  ser hosts diferents: els paquets SCORM i l’HTML carregat s’executen des de
  l’origen de contingut i no poden llegir mai les galetes de l’LMS.
- Per a una prova local, `lvh.me` i `*.localhost` es resolen a 127.0.0.1,
  com preveu `docker/.env.example`. El servei `proxy` del stack serveix tots
  dos per HTTPS amb una autoritat de certificació local, així que no cal
  instal·lar res més (vegeu «TLS»).
- Allibereu els ports 80 i 443 de l’host (`QUIRE_PROXY_HTTP_PORT` i
  `QUIRE_PROXY_HTTPS_PORT` els canvien).

## Primera execució <!--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` crea `docker/.env` a partir de
`docker/.env.example` i genera tots els secrets (contrasenyes de la base de
dades, claus de signatura i mestra, i parell de claus d’inici del contingut).
També crea la clau de signatura dels checkpoints d’auditoria a
`docker/secrets/audit-signing-key.pem`, que Compose munta als workers com a
secret. Només necessita `sh`, `awk` i `openssl` i es nega a sobreescriure un
`docker/.env` existent. Copieu tots dos fitxers fora de l’host: sense
`QUIRE_MASTER_KEY`, una base de dades restaurada no pot desxifrar les
credencials que conté. Si preferiu omplir el fitxer manualment, executeu
`cp docker/.env.example docker/.env`; dins del fitxer s’explica com generar
cada secret.

Tots dos orígens han de ser `https`: el servei de contingut rebutja l’http
sense xifrar en producció i no poden compartir un mateix domini registrable.
El servei `proxy` acaba TLS per a tots dos (vegeu «TLS»); `init-env.sh`
rebutja els orígens que comencen per `http://`.

El stack s’inicia en un ordre fix i cada pas espera que acabi l’anterior:

1. `postgres` arriba a un estat saludable. A la primera arrencada, l’script
   d’inicialització (`docker/postgres/init/90-passwords.sh`) estableix les
   contrasenyes dels quatre rols.
2. `migrate` aplica totes les migracions i inicialitza la cua de tasques tant
   a la base de dades de control com a cada base de dades de tenant dedicada;
   comprova que totes coincideixin i, després, surt (docs/ops/upgrade.md).
   Les migracions s’executen cada vegada que s’inicia el stack i són
   idempotents, així que actualitzar-lo consisteix a fer servir una imatge nova
   i reiniciar.
3. `init` (`apps/web/src/first-run.ts`) registra la base de dades de
   l’aplicació sota `QUIRE_DATABASE_ID` i, si s’ha definit
   `QUIRE_SETUP_ADMIN_EMAIL`, crea la primera organització i el seu
   administrador. L’adreça d’inici de sessió i una contrasenya generada es
   mostren una sola vegada al registre de `docker compose logs init`.
4. S’inicien `web`, `content`, `worker`, `scheduler`, `collab` i `centrifugo`.
5. `proxy` s’inicia quan `web` i `content` estan saludables.

Obriu `https://demo.` seguit del domini de l’aplicació (el registre de `init`
mostra l’adreça d’inici de sessió exacta) i inicieu sessió. En una instal·lació
local, primer establiu com a fiable l’autoritat de certificació del proxy
(vegeu «TLS»). Canvieu la contrasenya generada a `/account/security`.

Un procés que s’inicia sense un secret obligatori es nega a arrencar i n’indica
el nom al registre. No s’inicia res amb una configuració incompleta.

## Serveis i perfils <!--quire:services-and-profiles-->

| Servei | Perfil | Funció |
| --- | --- | --- |
| postgres | sempre | Base de dades (PostgreSQL 18 amb pgvector, compilat des de `docker/postgres.Dockerfile`), amb l’arxivament de WAL des de la primera arrencada |
| migrate, init | sempre | Tasca puntual: primer migracions, després configuració inicial |
| web | sempre | L’LMS, al port `QUIRE_HTTP_PORT` (8080) |
| content | sempre | Origen per al contingut no fiable, al port `QUIRE_CONTENT_PORT` (8081) |
| worker | sempre | Tasques en segon pla: correu, informes, processament de fitxers i webhooks |
| scheduler | sempre | Tasques recurrents: registra les 64 programacions de temps d’execució i les lliura al worker; només hi ha un líder alhora |
| collab | sempre | Websocket d’edició col·laborativa, al port `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | sempre | Distribució de temps real, al port `QUIRE_REALTIME_PORT` (8000) |
| proxy | sempre | Caddy, el punt d’entrada TLS als ports 80 i 443 (vegeu «TLS») |
| valkey | `cache` | Memòria cau i límits de freqüència |
| clamav | `scan` | Anàlisi de programari maliciós de les pujades |
| gotenberg | `preview` | Previsualització de documents Office en PDF i generació de certificats |
| imgproxy | `images` | Redimensionament i conversió d’imatges |
| transcoder | `video` | Imatge del worker amb ffmpeg només sota llicència LGPL, per generar versions de vídeo |
| seaweedfs | `storage` | Emmagatzematge d’objectes compatible amb S3 en aquest host |
| otelcol | `observability` | Recol·lector d’OpenTelemetry |
| mailpit | `devmail` | Captura tot el correu sortint per provar Quire |
| backup | `backup` | Còpia base puntual; vegeu backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | Còpia base cada `QUIRE_BACKUP_INTERVAL_HOURS` i còpies xifrades fora de l’host amb un simulacre de verificació setmanal |
| h5p | `h5p` | Imatge d’eina H5P LTI 1.3 que proporcioneu amb `QUIRE_H5P_IMAGE`, al port `QUIRE_H5P_PORT` (8090); vegeu «Connectar un proveïdor H5P» |

`--profile full` inicia tots els serveis opcionals excepte `backup` i `h5p`.
Per iniciar-ne un, executeu `docker compose -f docker/compose.yaml --profile scan up -d`.
Quire continua funcionant sense un servei opcional i indica què manca: sense
scanner, les pujades es desen sense analitzar i s’avisa l’administrador; sense
Gotenberg, els fitxers es poden descarregar però no previsualitzar; sense
transcoder, el vídeo es reprodueix com el fitxer original.

Les imatges de tercers i les obligacions de llicència corresponents figuren a
`docker/third-party-containers.yaml`.

### Connectar un proveïdor H5P <!--quire:connecting-an-h5p-provider-->

Quire no incorpora ni distribueix un runtime o sidecar H5P (ADR 0019). Si
utilitzeu H5P, contracteu una subscripció allotjada pròpia o gestioneu una
instància H5P autoallotjada separada de Quire. Registreu aquest proveïdor com
a eina externa LTI 1.3 i afegiu-ne el contingut als cursos com a activitats
d’eina. Quire intercanvia qualificacions i progrés de l’activitat i
l’avaluació mitjançant LTI Assignment and Grade Services (AGS). Si el proveïdor
també envia declaracions xAPI, configureu-ho per separat amb el magatzem de
declaracions xAPI de Quire; l’intercanvi de qualificacions i progrés per AGS no
envia declaracions xAPI. Les importacions de Moodle indiquen que les activitats
H5P necessiten una connexió a una eina LTI. El proveïdor continua sent
responsable del seu runtime H5P, les eines de creació, el banc de continguts i
l’historial d’intents.

Per executar una instància pròpia en aquest host, establiu `QUIRE_H5P_IMAGE`
amb la imatge i inicieu el perfil `h5p`. Compose la publica al port
`QUIRE_H5P_PORT` (8090) i en desa les dades al volum `h5p-data`; tant la
imatge com les obligacions que comporta són responsabilitat vostra.

## Configuració <!--quire:settings-->

Cada procés llegeix `docker/.env`. El fitxer de plantilla,
`docker/.env.example`, enumera cada opció amb el seu valor predeterminat. Els
grups són:

### Adreces <!--quire:addresses-->

| Configuració | Significat |
| --- | --- |
| `QUIRE_APP_ORIGIN` | Adreça pública de l’LMS, per exemple `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Origen del contingut, en un host diferent |
| `QUIRE_PLATFORM_DOMAINS` | Dominis de les organitzacions, separats per comes |
| `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` | Aquí és `compose`. Consulteu les altres guies per a `vercel` i `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Proxies de qui es considera fiable la capçalera `X-Forwarded-For` |

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

| Configuració | Significat |
| --- | --- |
| `QUIRE_SECRET_KEY` | Signa sessions i tokens. 64 caràcters hexadecimals |
| `QUIRE_MASTER_KEY` | Embolica credencials desades com ara secrets SSO i webhook. 32 bytes, base64. La capa web i el worker necessiten el mateix valor. Rotació: [key-rotation.md](/ca/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Etiqueta de versió de la clau mestra; si no s’estableix, `v1`. Augmenteu-la en rotar la clau |
| `QUIRE_MASTER_KEY_RETIRED` | Claus mestres anteriors que encara calen per llegir els valors que protegeixen; format `v1=<base64>`. Elimineu-les després d’acabar la rotació sense cap valor pendent |
| `QUIRE_COLLAB_SIGNING_KEY` | La comparteixen web i collab per signar tokens d’edició |
| `QUIRE_BACKUP_SIGNING_KEY` | Signa còpies de seguretat de cursos (opcional) |

Guardeu una còpia de `QUIRE_MASTER_KEY` fora d’aquest host. Sense aquesta
clau, una base de dades restaurada no pot desxifrar les credencials que conté.

### Base de dades <!--quire:database-->

| Configuració | Significat |
| --- | --- |
| `POSTGRES_PASSWORD` | Superusuari, utilitzat pel contenidor i les còpies de seguretat |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Contrasenyes de rol que s’estableixen a la primera arrencada |
| `DATABASE_URL` | Rol de l’aplicació. La seguretat a nivell de fila s’aplica a totes les seves consultes |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | Rol de migració per a `migrate` i `init` |
| `QUIRE_SUPERUSER_URL` | Només s’utilitza a la primera arrencada |
| `QUIRE_REPORT_DATABASE_URL` | Rol de només lectura per als informes i el creador d’informes |
| `QUIRE_AUDIT_DATABASE_URL` | Rol d’auditoria per a la consola d’auditoria i l’exportació SIEM |
| `QUIRE_DATABASE_ID` | Qualsevol UUID, fix durant tota la vida de la instal·lació |

Les contrasenyes dels rols només s’apliquen quan es crea per primera vegada
el volum de la base de dades. Per canviar-ne una més endavant, executeu
`ALTER ROLE` i, després, actualitzeu l’URL corresponent.

`QUIRE_REPORT_DATABASE_URL` s’utilitza per a la base de dades física
configurada a `DATABASE_URL`. Per a qualsevol altra base de dades física
registrada, establiu el seu propi URL de connexió `quire_report` als entorns
web i worker; després, al camp **Reporting environment variable** de la base,
indiqueu el nom de la variable amb el format `env:NAME`. La referència ha
d’apuntar a la mateixa base de dades que la connexió de l’aplicació, idealment
a la seva rèplica de lectura. Cada superfície d’informes segueix el tenant i
utilitza la connexió d’informes de la seva base de dades: el creador i els
informes desats, els lliuraments programats, les exportacions d’informes,
l’analítica, el registre d’auditoria, els recursos d’auditoria REST i la cerca
d’auditoria de l’assistent. Cap d’ells no utilitza la URL d’informes d’una altra
base de dades. Si una base de dades no té connexió d’informes, els informes
habituals utilitzen la connexió de l’aplicació de la mateixa base; en canvi,
l’analítica i qualsevol lectura d’auditoria es rebutgen i n’indiquen el motiu,
perquè el rol de l’aplicació no pot llegir el registre d’auditoria.

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

| Configuració | Valors d’aquesta versió | Notes |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (predeterminat), `s3` o `azure` | `local` desa els fitxers al volum `files`. `s3` és compatible amb AWS S3, R2, la interoperabilitat GCS i altres magatzems compatibles amb S3; permet càrregues multipart reprenibles |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (predeterminat), `sse`, `centrifugo` o `durable_objects` | `inprocess` és adequat per a un sol contenidor web; si n’hi ha més, utilitzeu `centrifugo` o `sse` |
| `QUIRE_CACHE_DRIVER` | `memory` (predeterminat), `postgres` o `valkey` | `memory` és independent per a cada procés; feu servir `valkey` o `postgres` perquè els límits de freqüència s’apliquin entre contenidors |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (predeterminat) o `progressive_mp4` | També podeu fer servir un proveïdor allotjat: Cloudflare Stream, Mux o Bunny, amb les claus corresponents |
| `QUIRE_IMAGE_DRIVER` | `noop` (predeterminat), `imgproxy` o `cloudflare` | `noop` serveix totes les imatges a la mida original. `imgproxy` necessita el perfil `images` i les opcions que s’indiquen més avall; `cloudflare` utilitza Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` o `in_process` | Proveïdor predeterminat de la plataforma per a les sessions en directe. Si no està definit, les sessions s’indiquen com a no configurades fins que l’organització connecta el seu compte a Integrations, Live session provider. El compte propi de l’organització sempre té prioritat. Només es llegeixen les opcions del proveïdor seleccionat (`BBB_URL` i `BBB_SECRET`, i les variables `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*` i `JITSI_*`) |
| `QUIRE_MEETING_REGIONS` | Llista separada per comes de `eu`, `uk` i `us` | Regions on el proveïdor predeterminat de la plataforma processa les reunions. Si no es defineix, no es comprova si coincideix amb la regió assignada a l’organització, com fins ara. El compte propi de l’organització n’indica les regions a la seva pàgina |

Quan s’inicia la capa web, es rebutja un valor de driver que no inclogui
aquesta versió i se n’indica el nom; no se substitueix silenciosament pel valor
predeterminat.

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

Les pàgines demanen imatges en quatre mides fixes mitjançant
`/api/files/{id}/image/{size}`. Es comprova el mateix accés que al fitxer i,
després, es redirigeix al servei d’imatges. Cada organització pot demanar fins
a `QUIRE_IMAGE_SPECS_PER_HOUR` (2000 per defecte) parelles noves d’imatge i
mida per hora; les mides ja generades durant aquella hora no compten. Si hi ha
més d’un contenidor web, utilitzeu `valkey` o `postgres` per a
`QUIRE_CACHE_DRIVER`, de manera que el límit s’apliqui a tots.

| Configuració | Driver | Notes |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Adreça on els navegadors accedeixen a imgproxy, com ara `https://images.example.org`. El perfil `images` el publica al port `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Cadenes hexadecimals; han de ser els mateixos valors que rep imgproxy en iniciar-se. Genereu-los amb `openssl rand -hex 32`. Quire signa totes les adreces d’imatge amb aquests valors, de manera que imgproxy no renderitza cap imatge que Quire no hagi demanat |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` amb emmagatzematge local | Adreça d’on imgproxy obté les imatges originals. Compose estableix `http://web:3000`. Amb l’emmagatzematge `s3` o `azure`, imgproxy les obté del bucket i no es fa servir aquesta opció |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Token d’API amb permís d’edició d’Imatges i hash del compte de Images, Developer resources. Activeu les variants flexibles al compte |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Opcional. Si s’estableix, les imatges són privades i totes les adreces se signen i caduquen. Si no, són públiques a adreces derivades de `QUIRE_SECRET_KEY` que ningú no pot endevinar |

Cloudflare Images conserva una còpia de cada original que serveix. Quan se
suprimeix un fitxer, el worker elimina primer aquella còpia i després
l’original.

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

Les tasques en segon pla utilitzen pg-boss a la mateixa base de dades Postgres;
per tant, no cal executar ni configurar un servei de cua. Les tasques
s’encuen dins de la mateixa transacció que el canvi que les ha provocat: una
fallada no en pot perdre cap ni enviar-la dues vegades. Aquí
`QUIRE_QUEUE_DRIVER` és `pgboss`, el valor predeterminat; `vercel` i
`cloudflare` només traslladen les notificacions lleugeres i els lliuraments de
webhooks a la cua de la plataforma. Les guies de Vercel i Cloudflare n’expliquen
el funcionament i com les seves capes web hi encuen tasques.

### Correu electrònic <!--quire:email-->

Establiu una d’aquestes opcions:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: objecte JSON que indica un proveïdor HTTP i
  les seves credencials, com ara `{"provider":"postmark","token":"..."}`.
  S’admeten Postmark, Amazon SES, Mailgun, SendGrid i Resend.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Només funciona en aquest
  entorn; els entorns serverless bloquegen SMTP.

`QUIRE_MAIL_FROM` és l’adreça del remitent. Per provar Quire, inicieu el perfil
`devmail`, establiu `QUIRE_SMTP_URL=smtp://mailpit:1025` i llegiu el correu a
`http://localhost:8025`.

### Serveis opcionals <!--quire:optional-services-->

| Configuració | Perfil necessari |
| --- | --- |
| `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` | Cerca externa; si no, cerca de text complet de Postgres |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Comprovació de contrasenyes filtrades. S’activa per defecte amb `api.pwnedpasswords.com` (només s’envia el prefix de cinc caràcters del hash); `off` la desactiva, i l’URL indica una range API que allotgeu vosaltres |

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

`OTEL_EXPORTER_OTLP_ENDPOINT` indica el recol·lector al qual cada procés
envia traçes i mètriques. Amb el perfil `observability`, és
`http://otelcol:4318`; a `docker/otel-collector.yaml` s’hi afegeix
l’exportador per al vostre backend. Si s’estableix aquesta opció, els
processos de la capa web, el worker, l’scheduler, content i collab envien
spans per OTLP/HTTP (peticions web, transaccions de bases de dades tenant,
tasques de workers i crides sortints) i mètriques al mateix endpoint cada
minut (`OTEL_METRICS_EXPORTER=none` les desactiva). `OTEL_TRACES_SAMPLER_ARG`
determina la proporció de traces conservades. Els registres s’envien a la
sortida estàndard segons `LOG_LEVEL` i Compose els rota. Les traces no
contenen mai dades personals.

### Trànsit de sortida regional (residència de dades a la UE) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` indica que el stack serveix organitzacions de la Unió
Europea. En aquest cas, el worker limita a una llista de permesos les peticions
sortints de les organitzacions assignades a la UE (21-compliance.md, secció
8.1). Aquesta llista inclou els hosts que declaren els serveis configurats
per a la regió (endpoint d’emmagatzematge, proveïdor de correu, proveïdor de
vídeo allotjat, destinacions d’emmagatzematge pròpies de l’organització,
proveïdors d’IA i compte de correu), els hosts dels serveis amb una excepció
vigent i els que indiqueu a `QUIRE_EGRESS_ALLOW_HOSTS`. Es rebutja qualsevol
petició a un altre host públic abans d’enviar-la; el rebuig queda al registre
d’auditoria de l’organització com a `privacy/egress_refused` i es mostra a
Compliance, Data residency.

| Configuració | Valors | Efecte |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Llista de noms de host separats per comes, o `*.example.org` per a tots els subdominis | Hosts addicionals als quals pot accedir una organització de la UE. Els endpoints de webhooks, xAPI i SIEM, els canals RSS dels blogs i els hosts d’Amazon SES s’han d’afegir aquí perquè són decisions de l’organització i cap servei no els declara. El loopback, les adreces privades i els noms d’una sola etiqueta com `web` o `clamav` pertanyen a la vostra xarxa i no es comproven mai |

Les organitzacions del Regne Unit i dels Estats Units no estan subjectes a una
llista de hosts, però es mantenen les comprovacions de regió dels serveis.
Establiu la llista al worker; la pàgina d’administració la llegeix des de la
capa web per mostrar la llista de permesos, així que poseu-la a `docker/.env`,
que llegeixen tots els serveis.

La comprovació de l’aplicació dona un error clar i crea una entrada
d’auditoria, però no és la garantia: el codi pot ser incorrecte. La garantia
és la xarxa, i Compose no la imposa. En un stack regional, poseu `worker` i
`web` en una xarxa `internal: true` l’única sortida de la qual sigui un proxy
de trànsit de sortida (per exemple, un contenidor Squid o tinyproxy) que
permeti els mateixos hosts que `QUIRE_EGRESS_ALLOW_HOSTS`, a més dels hosts
dels serveis configurats; establiu `HTTPS_PROXY` per a aquests serveis. La
pàgina de residència enumera exactament els hosts que permet l’aplicació, de
manera que en podeu comparar les dues llistes.

## Estat de salut <!--quire:health-->

| Endpoint | Significat |
| --- | --- |
| `/healthz` | Activitat: el procés respon. Compose el fa servir en les comprovacions de salut |
| `/readyz` | Preparació: es pot accedir a les dependències i cada servei opcional indica si està configurat. Apunteu-hi el balancejador de càrrega |

`docker compose -f docker/compose.yaml ps` mostra l’estat de salut de cada
servei.

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

El servei `proxy` (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) forma part
del stack predeterminat. Escolta als ports 80 i 443 i encamina:

| Host o camí | Destinació |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, cada subdomini tenant i domini personalitzat | `web` |
| `/_collab/` en aquests hosts | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` en aquests hosts | Websocket client de `centrifugo`; la seva API de servidor mai no s’exposa |
| `/_images/` en aquests hosts | `imgproxy`, amb el perfil `images` (`IMGPROXY_URL`) |

`init-env.sh` deriva `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`,
`QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` i `IMGPROXY_URL` dels dos
orígens, de manera que no divergeixin. Si canvieu un origen manualment,
modifiqueu-los tots alhora.

Els certificats segueixen l’opció `QUIRE_PROXY_TLS`:

- `internal` (predeterminat): l’autoritat de certificació pròpia de Caddy, per
  a `localhost`, `*.localhost` i `lvh.me`. Marqueu-ne l’arrel com a fiable una
  vegada i, després, navegueu-hi:

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

  Afegiu `quire-local-ca.crt` al magatzem de certificats fiables del sistema o
  del navegador. `curl` l’utilitza amb `--cacert`.
- Una adreça de correu electrònic: certificats ACME automàtics (Let's Encrypt
  i, després, ZeroSSL) per a noms de host reals. El DNS dels dos orígens i de
  cada host tenant ha d’apuntar aquí, i els ports 80 i 443 han de ser
  accessibles des d’Internet.

Els certificats dels hosts tenant s’emeten quan cal, en la primera visita i
només si web confirma que el nom pertany a aquesta instal·lació
(`/tls-allowed`, consultat des de la xarxa de Compose). No cal cap certificat
wildcard ni cap connector de proveïdor DNS, i un desconegut que apunti un nom
a l’host no pot fer que se n’emetin certificats. Els certificats i
l’autoritat local són al volum `caddy-data`; si utilitzeu `internal`, incloeu-lo
a la resta de còpies de seguretat.

Web només confia en `X-Forwarded-For` si l’envia el proxy: el proxy té una
adreça fixa (`QUIRE_PROXY_ADDRESS`, `172.29.64.10` per defecte) en una subnet
fixa (`QUIRE_COMPOSE_SUBNET`), i `QUIRE_TRUSTED_PROXY_CIDRS` inclou aquesta
adreça. Si la subnet entra en conflicte amb una xarxa de l’host, canvieu totes
dues i executeu `docker compose down` abans de `up`.

## Darrere del vostre propi proxy invers <!--quire:behind-your-own-reverse-proxy-->

Per utilitzar el balancejador de càrrega o el proxy que ja executeu, excloeu
`proxy` (`docker compose up -d --scale proxy=0`) i acabeu TLS davant de `web`
(8080), `content` (8081), `collab` (1234, websocket) i `centrifugo` (8000,
websocket). Establiu les adreces públiques a `QUIRE_APP_ORIGIN`,
`QUIRE_CONTENT_ORIGIN` i `QUIRE_COLLAB_URL` (`wss://`), i el rang d’adreces
del vostre proxy a `QUIRE_TRUSTED_PROXY_CIDRS`.

## Resolució de problemes <!--quire:troubleshooting-->

- Si `init` surt amb «QUIRE_DATABASE_ID is not a UUID», establiu-ne un amb
  `uuidgen`.
- Si `web` es reinicia amb «did not start on compose», el registre enumera
  cada opció que no pot acceptar i què cal utilitzar en lloc seu.
- Canviar una contrasenya de rol a `.env` després de la primera arrencada no
  fa res: l’script d’inicialització només s’executa una vegada. Utilitzeu
  `ALTER ROLE`.
- Si fallen les pujades amb un error d’anàlisi quan `CLAMAV_URL` està
  establert, ClamAV està descarregant les signatures de la primera arrencada;
  això pot trigar uns minuts.

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