---
title: "Installà Quire cù Docker Compose"
description: "Installate Quire nant'à a vostra infrastruttura cù Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

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

# Installà Quire cù Docker Compose

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

Questu hè u pruduttu cumpletu nant'à un host: u LMS, i so travaglii in sfondu, i
servizii in tempu reale è di mudificazione cullaburativa, è ogni serviziu facultativu
sottu à un prufilu. U disignu hè in a sezzione 2 di `docs/architecture/23-ops.md`.

Altri target: [Vercel](/co/ops/vercel/) è [Cloudflare Workers](/co/ops/cloudflare/) eseguiscenu
solu u nivellu web. L'aghjurnamenti sò in [upgrade.md](/co/ops/upgrade/), è e copie di salvezza è
l'eserciziu di risturazione in [backup-restore.md](/co/ops/backup-restore/).

## Ciò chì vi ci vole <!--quire:what-you-need-->

- Docker Engine 27 o più recente cù u plugin Compose 2.30 o più recente.
- 4 nuclei CPU è 8 GB di memoria per u stack predefinitu; 8 nuclei è 16 GB
  cù `--profile full` (ClamAV solu occupa circa 1.5 GB di signature).
- Un nome DNS per u nivellu web è un secondu per u cuntenutu micca fidatu. Devenu
  esse host sfarenti: i pacchetti SCORM è l'HTML caricatu funzionanu à l'origine di cuntenutu
  per ùn pudè mai leghje i cookies di u LMS.
- Per una prova lucale, `lvh.me` è `*.localhost` risolvenu versu 127.0.0.1, ciò chì
  usa `docker/.env.example`. U serviziu `proxy` propiu di u stack serve
  tramindui via https cù una autorità di certificazione lucale, dunque ùn ci vole à installà nunda altru (vede «TLS»).
- I porti 80 è 443 liberi nant'à l'host (`QUIRE_PROXY_HTTP_PORT` è
  `QUIRE_PROXY_HTTPS_PORT` li cambianu).

## Prima esecuzione <!--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` scrive `docker/.env` da `docker/.env.example`
cù tutti i sicreti generati (password di basa di dati, chjave di firma è maestra,
parigliu di chjave di lanciu di cuntenutu) è a chjave di firma di u puntu di cuntrollu d'audit in
`docker/secrets/audit-signing-key.pem`, chì Compose monta in i worker
cum'è sicretu. Hà bisognu solu di `sh`, `awk` è `openssl`, è ricusa di
sovrascrive un `docker/.env` esistente. Copiate i dui schedarii fora di l'host: senza
`QUIRE_MASTER_KEY` una basa risturata ùn pò decifrà e credenziali cunservate.
Per riempie u schedariu à manu invece, `cp docker/.env.example docker/.env`; u
schedariu spiega cumu generà ogni sicretu.

E duie origine devenu esse `https`: u serviziu di cuntenutu ricusa http pianu in
pruduzzione, è ùn devenu micca sparte u listessu duminiu registrabile. U serviziu `proxy`
finisce TLS per e duie (vede «TLS»); `init-env.sh` ricusa un'origine
`http://`.

U stack s'avvia in un ordine fissu, è ogni passu aspetta u precedente:

1. `postgres` diventa sanu. À u primu avviu, u so script d'inizializazione
   (`docker/postgres/init/90-passwords.sh`) stabilisce e password di i quattru rolli.
2. `migrate` applica ogni migrazione è inizializeghja a fila di travagli in
   a basa di cuntrollu è in ogni basa di tenant dedicata, verifica ch'elle
   sianu tutte d'accordu, dopu esce (docs/ops/upgrade.md).
   E migrazioni si eseguenu à ogni avviu è sò idempotenti, dunque un aghjurnamentu hè una nova
   imagine è un riavviu.
3. `init` (`apps/web/src/first-run.ts`) registra a basa di dati di l'applicazione sottu
   `QUIRE_DATABASE_ID` è, quandu `QUIRE_SETUP_ADMIN_EMAIL` hè stabilitu, crea a
   prima urganizazione è u so amministratore. L'indirizzu di cunnessione è una
   password generata sò stampati una volta in `docker compose logs init`.
4. `web`, `content`, `worker`, `scheduler`, `collab` è `centrifugo` s'avvianu.
5. `proxy` s'avvia quandu `web` è `content` sò sani.

Aprite `https://demo.` seguitatu da u vostru duminiu d'applicazione (u registru `init`
stampa l'indirizzu esattu di cunnessione) è cunnette vi. Nant'à un'installazione lucale, fidate
prima di l'autorità di certificazione di proxy (vede «TLS»). Cambiate a password generata in `/account/security`.

Un prucessu avviatu senza un sicretu necessariu ricusa di parte è nomina u
paràmetru mancante in u so registru. Nunda ùn s'avvia cù una cunfigurazione à mezu.

## Servizii è prufili <!--quire:services-and-profiles-->

| Serviziu | Prufilu | Ciò ch'ellu face |
| --- | --- | --- |
| postgres | sempre | A basa di dati (PostgreSQL 18 cù pgvector, custruita da `docker/postgres.Dockerfile`), cù u WAL archiviatu da u primu avviu |
| migrate, init | sempre | Una sola esecuzione: migrazioni, dopu prima esecuzione |
| web | sempre | U LMS, in `QUIRE_HTTP_PORT` (8080) |
| content | sempre | Origine di cuntenutu micca fidatu, in `QUIRE_CONTENT_PORT` (8081) |
| worker | sempre | Travaglii in sfondu: email, rapporti, trasfurmazione di schedarii, webhooks |
| scheduler | sempre | Travaglii ricurrenti: registra i 64 piani d'esecuzione è li passa à u worker; un capu à volta |
| collab | sempre | Websocket di mudificazione cullaburativa, in `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | sempre | Distribuzione in tempu reale, in `QUIRE_REALTIME_PORT` (8000) |
| proxy | sempre | Caddy, porta TLS d'entrata nantu à i porti 80 è 443 (vede «TLS») |
| valkey | `cache` | Cache è limiti di frequenza |
| clamav | `scan` | Scansione di malware di i caricamenti |
| gotenberg | `preview` | Previsualizazioni Office in PDF, rende di certificati |
| imgproxy | `images` | Ridimensiona è cunverte imagini |
| transcoder | `video` | L'imagine di worker cù ffmpeg solu LGPL, per rende video |
| seaweedfs | `storage` | Almacenamentu d'ogetti cumpatibile S3 nant'à questu host |
| otelcol | `observability` | Un cullettore OpenTelemetry |
| mailpit | `devmail` | Intercepte tutta a posta in uscita, per pruvà Quire |
| backup | `backup` | Copia di salvezza di basa d'una sola esecuzione; vede backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | Copia di salvezza di basa ogni `QUIRE_BACKUP_INTERVAL_HOURS`, è copie cifrate fora di l'host cù verificazione settimanale |
| h5p | `h5p` | Imagine strumentu H5P LTI 1.3 furnita da voi in `QUIRE_H5P_IMAGE`, in `QUIRE_H5P_PORT` (8090); vede «Cunnette un fornitore H5P» |

`--profile full` avvia ogni serviziu facultativu fora di `backup` è `h5p`.
Avviate unu cù `docker compose -f docker/compose.yaml --profile scan up -d`.
Senza un serviziu facultativu Quire funziona sempre è indica ciò chì manca: senza
scanner i caricamenti sò cunservati senza scansione è l'amministratore hè avvistatu; senza Gotenberg i schedarii ponu esse scaricati invece d'avè una previsualizazione; senza transcoder i video
sò riprudutti cum'è schedariu originale.

Ogni imagine di terza parte è i so obblighi di licenza sò elencati in
`docker/third-party-containers.yaml`.

### Cunnette un fornitore H5P <!--quire:connecting-an-h5p-provider-->

Quire ùn integra nè distribuisce un runtime o sidecar H5P (ADR 0019). S'è vo aduprate
H5P, furnite u vostru abbonamentu ospitatu o gestite separatamente da Quire a vostra propria istanza H5P
autugestionata. Registrate stu fornitore cum'è strumentu esternu LTI 1.3
è aghjunghjite u so cuntenutu à i corsi cum'è attività di strumentu. Quire scambia i voti
è u prugressu d'attività/valutazione via LTI Assignment and Grade Services (AGS).
S'è u fornitore manda dinù dichjarazioni xAPI, cunfigurate lu à parte per u magazinu di dichjarazioni xAPI
di Quire; u scambiu di voti/prugressu AGS ùn manda dichjarazioni xAPI. L'impurtazioni Moodle
signalanu l'attività H5P cum'è bisognose d'una cunnessione à u strumentu LTI.
U fornitore ferma rispunsevule di u so runtime H5P, di a creazione, di a banca di cuntenutu è di a storia di tentativi.

Per eseguisce a vostra propria istanza autugestionata nant'à questu host, stabilite `QUIRE_H5P_IMAGE` à a so
imagine è avviate u prufilu `h5p`. Compose a publica in `QUIRE_H5P_PORT`
(8090) è cunserva i so dati in u volume `h5p-data`; l'imagine è l'
obblighi ch'ella porta fermanu à voi.

## Paràmetri <!--quire:settings-->

Ogni prucessu leghje `docker/.env`. U mudellu, `docker/.env.example`, elenca
ogni paràmetru cù u so predefinitu. I gruppi:

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

| Paràmetru | Significatu |
| --- | --- |
| `QUIRE_APP_ORIGIN` | Indirizzu publicu di LMS, cum'è `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Origine di cuntenutu, un host sfarente |
| `QUIRE_PLATFORM_DOMAINS` | Duminii sottu à i quali sò e urganizazioni, siparati da virgule |
| `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` quì. Vede l'altre guide per `vercel` è `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Proxy di quale si fidanu l'intestazioni `X-Forwarded-For` |

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

| Paràmetru | Significatu |
| --- | --- |
| `QUIRE_SECRET_KEY` | Firma e sessioni è i gettoni. 64 caratteri esadecimali |
| `QUIRE_MASTER_KEY` | Incapsula e credenziali cunservate cum'è sicreti SSO è webhook. 32 byte, base64. U nivellu web è u worker anu bisognu di u listessu valore. Rotazione: [key-rotation.md](/co/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Etichetta di versione di a chjave maestra, `v1` s'ella ùn hè stabilita. Aumentate la quandu fate a rotazione |
| `QUIRE_MASTER_KEY_RETIRED` | Chjave maestre precedente sempre necessarie per leghje ciò ch'elle anu sigillatu, cum'è `v1=<base64>`. Cacciate le dopu à compie a rotazione senza valori irrisolti |
| `QUIRE_COLLAB_SIGNING_KEY` | Spartuta da web è collab per firmà i gettoni di mudificazione |
| `QUIRE_BACKUP_SIGNING_KEY` | Firma e copie di salvezza di corsu (facultativu) |

Cunservate una copia di `QUIRE_MASTER_KEY` in un locu altru chè questu host. Una basa di dati
risturata senza ella ùn pò decifrà e credenziali ch'ella cuntene.

### Basa di dati <!--quire:database-->

| Paràmetru | Significatu |
| --- | --- |
| `POSTGRES_PASSWORD` | U superuser, adupratu da u cuntainer è e copie di salvezza |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Password di rollu, stabilite à u primu avviu |
| `DATABASE_URL` | U rollu di l'applicazione. A sicurezza à livellu di fila si applica à ogni dumanda ch'ellu face |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | U rollu di migratore, per `migrate` è `init` |
| `QUIRE_SUPERUSER_URL` | Adupratu solu à a prima esecuzione |
| `QUIRE_REPORT_DATABASE_URL` | Rollu di rapportu in sola lettura, per i rapporti è u creatore di rapporti |
| `QUIRE_AUDIT_DATABASE_URL` | Rollu d'audit, per a cunsola d'audit è l'esportazione SIEM |
| `QUIRE_DATABASE_ID` | Qualsiasi UUID, fissu per tutta a vita di l'installazione |

E password di rollu sò applicate solu quandu u volume di basa di dati hè creatu per a prima volta.
Per cambià ne una dopu, aduprate `ALTER ROLE` è aghjurnate dopu l'URL currispundente.

`QUIRE_REPORT_DATABASE_URL` hè adupratu per a basa fisica cunfigurata da
`DATABASE_URL`. Per qualsiasi altra basa fisica registrata, stabilite u so propiu
URL di cunnessione `quire_report` in l'ambienti web è worker, dopu mettite
u nome di variabile in u campu **Variabile d'ambiente per i rapporti** di quella basa
cum'è `env:NAME`. A riferenza deve indicà a stessa basa di dati cum'è a cunnessione di l'app,di preferenza a so replica in sola lettura. Ogni interfaccia di rapportu seguita u
tenant versu a so cunnessione di rapportu propria: u creatore di rapporti è i
rapporti salvati, e consegne pianificate, l'esportazioni di rapporti, l'analitiche,
u registru d'audit, e risorse d'audit REST è a ricerca d'audit di l'assistente. Nisuna
aduprà mai l'URL di rapportu d'un'altra basa. Quandu una basa ùn hà micca una
cunnessione di rapportu, i rapporti nurmali funzionanu cù a so propria cunnessione di l'applicazione,
mentre l'analitiche è ogni lettura d'audit ricusanu è l'indicanu, perchè u rollu
applicazione ùn pò leghje a pista d'audit.

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

| Paràmetru | Sta versione | Note |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (predefinitu), `s3` o `azure` | `local` cunserva i schedarii in u volume `files`. `s3` copre AWS S3, cumpatibilità R2 è GCS è altri magazini cumpatibili S3, cù caricamenti multipart ripigliabili |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (predefinitu), `sse`, `centrifugo` o `durable_objects` | `inprocess` cunvene à un solu cuntainer web; aduprate `centrifugo` o `sse` quandu ci n'hè parechji |
| `QUIRE_CACHE_DRIVER` | `memory` (predefinitu), `postgres` o `valkey` | `memory` hè per prucessu; aduprate `valkey` o `postgres` affinchì i limiti di frequenza sianu spartuti trà cuntainer |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (predefinitu) o `progressive_mp4` | O un fornitore ospitatu: Cloudflare Stream, Mux o Bunny, cù e so chjave |
| `QUIRE_IMAGE_DRIVER` | `noop` (predefinitu), `imgproxy` o `cloudflare` | `noop` serve ogni imagine à a so dimensione originale. `imgproxy` hà bisognu di u prufilu `images` è di i paràmetri sottu; `cloudflare` usa Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` o `in_process` | Fornitore predefinitu di a piattaforma per e sessioni in direttu. S'ellu ùn hè stabilitu, e sessioni in direttu indicanu ch'elle ùn sò cunfigurate, finch'è un'urganizazione ùn cunnette u so contu in Integrazioni, Fornitore di sessione in direttu. U contu propiu di l'urganizazione hà sempre a precedenza annantu à stu valore. I paràmetri specifici d'ogni fornitore (`BBB_URL` è `BBB_SECRET`, e variabili `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*` è `JITSI_*`) sò letti solu per u fornitore indicatu quì |
| `QUIRE_MEETING_REGIONS` | Una lista siparata da virgule di `eu`, `uk`, `us` | Induve u fornitore predefinitu di a piattaforma tratta e riunioni. S'ella ùn hè stabilita, ùn hè micca verificata contr'à un'urganizazione fissata à una regione, cum'è nanzu. U contu propiu d'una urganizazione indica e so regioni nantu à a so pagina |

Un valore di driver chì sta versione ùn include micca hè ricusatu à l'avviu di u nivellu web,
indicendu u paràmetru, invece d'esse rimpiazzatu in silenziu da u
predefinitu.

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

E pagine dumandanu imagines in quattru dimensioni fisse via
`/api/files/{id}/image/{size}`, chì verifica u listessu accessu chè u schedariu
stessu è poi redirige à u serviziu d'imagine. Ogni urganizazione pò dumandà
`QUIRE_IMAGE_SPECS_PER_HOUR` (predefinitu 2000) novi accoppiamenti imagine/dimensione per
ora; e dimensioni digià prodotte in quell'ora ùn contanu. Aduprate `valkey` o
`postgres` per `QUIRE_CACHE_DRIVER` cù più d'un cuntainer web, affinchì u
limitu sia spartutu trà elli.

| Paràmetru | Driver | Note |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Indirizzu à u quale i navigatori accedenu à imgproxy, per esempiu `https://images.example.org`. U prufilu `images` u publica in `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Stringhe esadecimali, listessi valori cù i quali imgproxy hè avviatu. Generate ognunu cù `openssl rand -hex 32`. Quire firma ogni indirizzu d'imagine cun elli, cusì imgproxy ùn rende nunda chì Quire ùn hà dumandatu |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` cù almacenamentu lucale | Induve imgproxy ricupera l'uriginali. Compose stabilisce `http://web:3000`. Cù almacenamentu `s3` o `azure`, imgproxy ricupera da u bucket è questu paràmetru ùn hè adupratu |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Gettone API cù permessu di mudificazione Images è l'hash di contu da Images, Risorse sviluppatore. Attivate varianti flessibili per u contu |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Facultativu. Quandu hè stabilitu, l'imagines sò private è ogni indirizzu hè firmatu è scade. Senza ella, l'imagines sò publiche à indirizzi derivati da `QUIRE_SECRET_KEY` chì nimu pò indovinà |

Cloudflare Images cunserva a so propria copia di ogni uriginale ch'ellu serve. Quandu un
schedariu hè sguassatu, u worker sguassa quella copia prima di l'uriginale.

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

I travaglii in sfondu usanu pg-boss in a stessa basa di dati Postgres, dunque ùn ci hè nisun
serviziu di fila da eseguisce è nunda da cunfigurà. I travaglii sò accodati in a stessa
transazzione chè u cambiamentu chì l'hà causati, dunque un crash ùn pò perde ne unu nè
mandà ne unu duie volte. `QUIRE_QUEUE_DRIVER` hè `pgboss` quì, u so predefinitu;
`vercel` è `cloudflare` spiazzanu solu e cunsegne ligeri di notificazioni è webhook à
fila propria di a piattaforma; e guide Vercel è Cloudflare discrivenu li è cumu i so
nivelli web li accodanu.

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

Stabilite unu di:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: un oggettu JSON chì nomina un fornitore HTTP è
  e so credenziali, per esempiu `{"provider":"postmark","token":"..."}`. Postmark,
  Amazon SES, Mailgun, SendGrid è Resend sò cumpatibili.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Solu stu target; i
  target serverless impediscenu SMTP.

`QUIRE_MAIL_FROM` hè u mittente. Per pruvà Quire, avviate u prufilu `devmail`,
stabilite `QUIRE_SMTP_URL=smtp://mailpit:1025`, è leghjite a posta in
`http://localhost:8025`.

### Servizii facultativi <!--quire:optional-services-->

| Paràmetru | Cù prufilu |
| --- | --- |
| `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` | Ricerca esterna; altrimenti ricerca testuale cumpleta Postgres |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Verifica password esposta. Attivata per predefinitu cù `api.pwnedpasswords.com` (solu un prefissu d'hash di cinque caratteri hè mandatu); `off` a disattiva, è l'URL punta à un'API di intervalli ospitata da voi |

### Osservabilità <!--quire:observability-->

`OTEL_EXPORTER_OTLP_ENDPOINT` nomina u cullettore à u quale ogni prucessu manda
tracce è metriche; cù u prufilu `observability` hè
`http://otelcol:4318`, è `docker/otel-collector.yaml` hè u locu induve aghjunghje l'
esportatore per u vostru backend. Quandu hè stabilitu, i prucessi web, worker, scheduler, content è collab
esportanu intervalli via OTLP/HTTP (dumande web, transazzioni di basa tenant,
travagli worker è chjame in uscita) è metriche versu u listessu endpoint ogni minutu (`OTEL_METRICS_EXPORTER=none` li disattiva).
`OTEL_TRACES_SAMPLER_ARG` stabilisce a parte di tracce cunservate. I registri vanu à a surtita
standard cù `LOG_LEVEL`, è Compose li rotea. E tracce ùn cuntenenu mai dati persunali.

### Uscita regiunale (residenza di dati UE) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` indica chì u stack serve urganizazioni di l'Unione Europea. U
worker limita tandu ogni dumanda in uscita fatta per un'urganizazione fissata à
l'UE à una lista di permessu (sezzione 8.1 di 21-compliance.md). A lista cuntene l'
host dichjarati da i servizii cunfigurati per a regione (endpoint d'almacenamentu,
fornitore di posta, fornitore video ospitatu, destinazioni d'almacenamentu proprie di l'urganizazione,
fornitori IA è contu di posta), l'host di qualsiasi serviziu sottu à una deroga attiva, è l'host chì elencate in
`QUIRE_EGRESS_ALLOW_HOSTS`. Una dumanda à qualsiasi altru host publicu hè ricusata
nanzu d'esse mandata; u rifiutu hè scrittu in a pista d'audit di l'urganizazione cum'è
`privacy/egress_refused`, è hè elencatu in Cunfurmità, Residenza di dati.

| Paràmetru | Valori | Effettu |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Lista di nomi host siparati da virgule, o `*.example.org` per ogni sottuduminiu | Host addiziunali chì un'urganizazione UE pò cuntattà. Endpoint webhook, xAPI è SIEM, flussi di blog è host Amazon SES vanu quì, perchè sò scelte proprie di l'urganizazione è nisun serviziu li dichjara. Loopback, indirizzi privati è nomi à una sola etichetta cum'è `web` o `clamav` appartenenu à a vostra rete è ùn sò mai verificati |

L'urganizazioni britanniche è statunitensi ùn sò micca limitate à una lista d'host; conservanu i cuntrolli di regione di serviziu. Stabilite a lista in u worker; a pagina amministrativa a leghje in u nivellu web
per mustrà a lista di permessu, dunque mettite la in `docker/.env`, chì ogni serviziu
leghje.

U cuntrollu di l'applicazione dà un errore chjaru è una voce d'audit, ma ùn hè micca
una garanzia: u codice pò esse sbagliatu. A garanzia hè a rete. Compose ùn
l'applica micca per voi. Per un stack regiunale, mettite i servizii `worker` è `web`
nant'à una rete `internal: true` chì hà cum'è sola strada in uscita un proxy d'uscita
(per esempiu Squid o un cuntainer tinyproxy) chì permette i stessi host
chì `QUIRE_EGRESS_ALLOW_HOSTS` è l'host di i servizii cunfigurati, è
stabilite `HTTPS_PROXY` per quelli servizii. A pagina di residenza elenca l'host esatti
permessi da l'applicazione, cusì e duie liste ponu esse paragunate.

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

| Endpoint | Significatu |
| --- | --- |
| `/healthz` | Vitalità: u prucessu risponde. I cuntrolli di salute Compose l'adopranu |
| `/readyz` | Prontezza: dipendenze accessibili, è ogni serviziu facultativu signalatu cum'è cunfiguratu o micca. Puntate quì u bilanciatore di carica |

`docker compose -f docker/compose.yaml ps` mostra a salute di ogni serviziu.

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

U serviziu `proxy` (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) face parte di
u stack predefinitu. Risponde nantu à i porti 80 è 443 è redirige:

| Host o percorsu | Va versu |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, ogni sottuduminiu tenant è duminiu persunalizatu | `web` |
| `/_collab/` nant'à quelli host | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` nant'à quelli host | Websocket di cliente di `centrifugo`; a so API server ùn hè mai esposta |
| `/_images/` nant'à quelli host | `imgproxy`, cù u prufilu `images` (`IMGPROXY_URL`) |

`init-env.sh` deriva `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`,
`QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` è `IMGPROXY_URL` da e duie
origine, cusì ùn ponu micca svià l'una da l'altra. Mudificate le inseme s'è cambiate un'
origine à manu.

I certificati dipendenu da `QUIRE_PROXY_TLS`:

- `internal` (predefinitu): autorità di certificazione propria di Caddy, per
  `localhost`, `*.localhost` è `lvh.me`. Fidate vi di u certificatu radicale una volta, dopu navigate:

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

  Aghjunghjite `quire-local-ca.crt` à u magazinu di fiducia di u sistema o navigatore. `curl`
  l'adopra cù `--cacert`.
- Un indirizzu email: certificati ACME automatichi (Let's Encrypt, dopu
  ZeroSSL) per nomi host veri. DNS di e duie origine è d'ogni host tenant
  deve puntà quì, è i porti 80 è 443 devenu esse accessibili da Internet.

L'host tenant ricevenu certificati à dumanda, à a prima visita, è solu quandu u nivellu web
cunfirma chì u nome appartene à st'installazione (`/tls-allowed`, dumandatu nantu à a
rete Compose). Ùn ci vole nè certificatu wildcard nè plugin di fornitore DNS,
è un stranieru chì punta un nome versu l'host ùn pò fà li dumandà
certificati. I certificati è l'autorità lucale sò in u
volume `caddy-data`; fate ne una copia cù u restu s'è aduprate `internal`.

U nivellu web crede `X-Forwarded-For` solu da u proxy: u proxy hà un indirizzu fissu
(`QUIRE_PROXY_ADDRESS`, predefinitu `172.29.64.10`) nantu à una sotturete fissa
(`QUIRE_COMPOSE_SUBNET`), è `QUIRE_TRUSTED_PROXY_CIDRS` nomina quellu indirizzu.
S'è a sotturete entre in cunflittu cù una rete di l'host, cambiate tramindui è eseguite
`docker compose down` nanzu à `up`.

## Daretu à u vostru proxy inversu <!--quire:behind-your-own-reverse-proxy-->

Per aduprà invece un bilanciatore di carica o proxy chì avete digià, lasciate fora
`proxy` (`docker compose up -d --scale proxy=0`) è terminate TLS davanti à `web`
(8080), `content` (8081), `collab` (1234, websocket) è `centrifugo` (8000,
websocket). Stabilite l'indirizzi publichi in `QUIRE_APP_ORIGIN`,
`QUIRE_CONTENT_ORIGIN` è `QUIRE_COLLAB_URL` (`wss://`), è l'intervallu d'indirizzi di u vostru proxy
in `QUIRE_TRUSTED_PROXY_CIDRS`.

## Risoluzione di prublemi <!--quire:troubleshooting-->

- `init` esce cù «QUIRE_DATABASE_ID is not a UUID»: stabilite lu cù `uuidgen`.
- `web` riparte cù «did not start on compose»: u registru elenca ogni paràmetru
  ch'ellu ùn pò rispettà è ciò chì ci vole à aduprà invece.
- Mudificà una password di rollu in `.env` dopu à u primu avviu ùn face nunda: u
  script d'inizializazione funziona una sola volta. Aduprate `ALTER ROLE`.
- I caricamenti fiascanu cù un errore di scansione mentre `CLAMAV_URL` hè stabilitu: ClamAV scarica
  e so signature à u primu avviu, ciò chì dura qualchì minutu.

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