---
title: "Quire mat Docker Compose installéieren"
description: "Installéiert Quire op Är eegen Infrastruktur mat Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

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

# Quire mat Docker Compose installéieren

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

Dëst ass de komplette Produit op engem Host: d'LMS, seng Hannergrond-Aarbecht, d'Realtime- an déi kollaborativ Editéierungsservicer, an all optional Service hanner engem Profil. Den Design steet an `docs/architecture/23-ops.md` Kapitel 2.

Aner Ziler: [Vercel](/lb/ops/vercel/) an [Cloudflare Workers](/lb/ops/cloudflare/) féieren nëmmen de Web-Tier. Upgrades stinn an [upgrade.md](/lb/ops/upgrade/), a Backups an den Restauratiounstest an [backup-restore.md](/lb/ops/backup-restore/).

## Wat Dir braucht <!--quire:what-you-need-->

- Docker Engine 27 oder méi nei mat dem Compose-Plugin 2.30 oder méi nei.
- 4 CPU-Kären an 8 GB Gedächtnis fir de Standard-Stack; 8 Kären an 16 GB mat `--profile full` (ClamAV eleng hält ongeféier 1.5 GB Signaturen).
- En DNS-Numm fir de Web-Tier an en zweeten fir net-vertruale Contenu. Et musse verschidde Hosten sinn: SCORM-Paketen an eropgelueden HTML lafen op der Content-Origin, sou datt se ni d'Cooke vun der LMS liese kënnen.
- Fir en lokale Test léisen `lvh.me` an `*.localhost` op 127.0.0.1 op, wat `docker/.env.example` benotzt. De stack-eegene `proxy`-Service servéiert béid iwwer https mat enger lokaler Zertifikatsautoritéit, sou datt näischt anescht installéiert gëtt (kuckt "TLS").
- D'Porten 80 an 443 fräi um Host (`QUIRE_PROXY_HTTP_PORT` an `QUIRE_PROXY_HTTPS_PORT` verréckelen se).

## Éischte Start <!--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` schreift `docker/.env` aus `docker/.env.example` mat all generéierte Geheimnis (Datebank-Passwierder, d'Signatur- an d'Master-Schlësselen, d'Schlësselpaar fir de Content-Start) an dem Signatur-Schlëssel fir d'Audit-Checkpointen an `docker/secrets/audit-signing-key.pem`, deen Compose als Geheimnis an d'Worker mount. En brauch nëmmen `sh`, `awk` an `openssl`, an en refuséiert en existente `docker/.env` ze iwwerschreiwen. Kopéiert béid Fichieren vum Host erof: ouni `QUIRE_MASTER_KEY` kann eng restauréiert Datebank hir gespäichert Zougangsdaten net entschlësselen. Fir de Fichier amplaz vun Hand ze fëllen, `cp docker/.env.example docker/.env`; de Fichier seet, wéi een all Geheimnis generéiert.

Béid Origine mussen `https` sinn: de Content-Service refuséiert plengen http an der Produktioun, an se däerfen keng registréierbar Domain deelen. De `proxy`-Service schléisst TLS fir béid of (kuckt "TLS"); `init-env.sh` refuséiert eng `http://`-Origin.

De Stack start an enger fester Reienfolleg, an all Schrëtt waart op deen virdrun:

1. `postgres` gëtt gesond. Beim alleréischte Start setzt säin Init-Skript (`docker/postgres/init/90-passwords.sh`) déi véier Roll-Passwierder.
2. `migrate` wenkt all Migratioun un a bootstrapt d'Job-Queue an der Kontroll-Datebank an an all dedikéierter Tenant-Datebank, kontrolléiert datt se all iwwereneestëmmen, da geet en eraus (docs/ops/upgrade.md). Migratioune lafen bei all Start a sinn idempotent, sou datt en Upgrade en neit Bild an en Neistart ass.
3. `init` (`apps/web/src/first-run.ts`) registréiert d'Applikatiouns-Datebank ënner `QUIRE_DATABASE_ID` an, wann `QUIRE_SETUP_ADMIN_EMAIL` gesat ass, erstellt en déi éischt Organisatioun an hiren Administrateur. D'Umeld-Adress an e generéiert Passwuert gi genee eemol gedréckt, an `docker compose logs init`.
4. `web`, `content`, `worker`, `scheduler`, `collab` a `centrifugo` starten.
5. `proxy` start, soubal `web` a `content` gesond sinn.

Maacht `https://demo.` gefollegt vun Ärer Applikatiouns-Domain op (d'`init`-Log dréckt déi exakt Umeld-Adress), a mellt Iech un. Bei enger lokaler Installatioun vertraut éischt der Zertifikatsautoritéit vum Proxy (kuckt "TLS"). Ännert dat generéiert Passwuert op `/account/security`.

E Prozess, deen ouni en erfuerderlecht Geheimnis gestart gëtt, refuséiert ze starten an nennt déi fehlend Astellung a sengem Log. Näischt start hallef konfiguréiert.

## Servicer a Profiller <!--quire:services-and-profiles-->

| Service | Profil | Wat en mécht |
| --- | --- | --- |
| postgres | always | D'Datebank (PostgreSQL 18 mat pgvector, gebaut aus `docker/postgres.Dockerfile`), mat WAL archivéiert vum éischte Boot un |
| migrate, init | always | Eemoleg: Migratiounen, dann éischte Start |
| web | always | D'LMS, op `QUIRE_HTTP_PORT` (8080) |
| content | always | D'Origin fir net-vertruale Contenu, op `QUIRE_CONTENT_PORT` (8081) |
| worker | always | Hannergrond-Joben: E-Mail, Berichter, Datei-Beaarbechtung, Webhooks |
| scheduler | always | Widderhuelend Joben: registréiert déi 64 Runtime-Pläng an iwwergëtt se dem Worker; genee ee Leader gläichzäiteg |
| collab | always | Kollaborativ Editéierungs-Websocket, op `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | always | Realtime Verdeelung, op `QUIRE_REALTIME_PORT` (8000) |
| proxy | always | Caddy, d'TLS-Dier op de Porten 80 an 443 (kuckt "TLS") |
| valkey | `cache` | Cache a Ratenlimiten |
| clamav | `scan` | Malware-Scan vun Eroplueden |
| gotenberg | `preview` | Office-nach-PDF-Virschaue, Zertifikat-Rendering |
| imgproxy | `images` | Vergréissert an ëmgewandelt Biller |
| transcoder | `video` | D'Worker-Bild mat engem LGPL-engem ffmpeg, fir Video-Versiounen |
| seaweedfs | `storage` | S3-kompatiblen Objektspeicher op dësem Host |
| otelcol | `observability` | En OpenTelemetry-Sammler |
| mailpit | `devmail` | Fänkt all erausginn Mail of, fir Quire auszebréngen |
| backup | `backup` | Eemolege Basisbackup; kuckt backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | E Basisbackup all `QUIRE_BACKUP_INTERVAL_HOURS`, a verschlësselt Kopien ausserhalb vum Host mat engem wëchentleche Verifikatiounstest |
| h5p | `h5p` | D'H5P LTI 1.3 Tool-Bild, dat Dir an `QUIRE_H5P_IMAGE` liwwert, op `QUIRE_H5P_PORT` (8090); kuckt "Connecting an H5P provider" |

`--profile full` start all optional Servicer ausser `backup` an `h5p`. Start een mat `docker compose -f docker/compose.yaml --profile scan up -d`. Ouni en optionale Service leeft Quire trotzdeem a seet, wat feelt: keen Scanner heescht datt Eroplueden ongescannt gespäichert ginn an den Administrateur informéiert gëtt; keen Gotenberg heescht datt Fichieren Download amplaz Virschau ubidden; keen Transcoder heescht datt Video als Originaldatei ofspillt.

All Drëttubidder-Bild a seng Lizenz-Flichte stinn an `docker/third-party-containers.yaml`.

### En H5P-Ubidder ubannen <!--quire:connecting-an-h5p-provider-->

Quire bett keng H5P-Runtime a liwwert kee Sidecar (ADR 0019). Wann Dir H5P benotzt, liwwert Ären eegenen gehosten Abonnement oder bedreiwt Är eegen selbst-gehosten H5P-Instanz getrennt vu Quire. Registréiert deen Ubidder als en externt LTI 1.3 Tool a setzt säi Contenu als Tool-Aktivitéiten a Coursen. Quire tauscht Noten an Aktivitéits-/Bewäertungsfortschrëtt iwwer LTI Assignment and Grade Services (AGS) aus. Wann den Ubidder och xAPI-Statementer schéckt, konfiguréiert dat getrennt fir de xAPI-Statement-Store vu Quire; den AGS Noten-/Fortschrëtt-Austausch schéckt keng xAPI-Statementer. Moodle-Importe mellen H5P-Aktivitéiten als eng LTI-Tool-Verbindung brauchend. Den Ubidder bleift responsabel fir seng H5P-Runtime, d'Autoren, d'Content-Bank an d'Versichsgeschicht.

Fir Är eegen selbst-gehosten Instanz op dësem Host ze bedreiwen, setzt `QUIRE_H5P_IMAGE` op säi Bild a start de `h5p`-Profil. Compose publizéiert en op `QUIRE_H5P_PORT` (8090) an hält seng Donnéeën am `h5p-data`-Volume; d'Bild, an d'Flichten, déi domat kommen, bleiwen Är.

## Astellungen <!--quire:settings-->

All Prozess liest `docker/.env`. D'Template, `docker/.env.example`, lëscht all Astellung mat hirem Standard. D'Gruppen:

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

| Astellung | Bedeitung |
| --- | --- |
| `QUIRE_APP_ORIGIN` | D'ëffentlech Adress vun der LMS, zum Beispill `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | D'Content-Origin, en aneren Host |
| `QUIRE_PLATFORM_DOMAINS` | Domänen, ënner deenen Organisatioune liewen, mat Komma getrennt |
| `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` | Hei `compose`. Kuckt déi aner Guiden fir `vercel` an `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Proxyen, deenen hirem `X-Forwarded-For` gegleeft gëtt |

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

| Astellung | Bedeitung |
| --- | --- |
| `QUIRE_SECRET_KEY` | Signéiert Sessiounen an Token. 64 Hex-Zeechen |
| `QUIRE_MASTER_KEY` | Wéckelt gespäichert Zougangsdaten wéi SSO- an Webhook-Geheimnisser an. 32 Bytes, base64. De Web-Tier an de Worker brauchen de selwechte Wäert. Rotatioun: [key-rotation.md](/lb/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | De Versiounslabel vum Master-Schlëssel, `v1` wann net gesat. Erhéicht en bei der Rotatioun |
| `QUIRE_MASTER_KEY_RETIRED` | Fréier Master-Schlësselen, déi nach gebraucht gi fir ze liesen, wat se versigelt hunn, als `v1=<base64>`. Ewechhuelen nodeems eng Rotatioun mat näischt Ongeléistem fäerdeg ass |
| `QUIRE_COLLAB_SIGNING_KEY` | Vu Web a Collab gedeelt, fir Editéierungs-Token ze signéieren |
| `QUIRE_BACKUP_SIGNING_KEY` | Signéiert Cours-Backups (optional) |

Halt eng Kopie vu `QUIRE_MASTER_KEY` anzwouschtesch wéi op dësem Host. Eng Datebank, déi ouni en restauréiert gëtt, kann d'Zougangsdaten, déi se hält, net entschlësselen.

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

| Astellung | Bedeitung |
| --- | --- |
| `POSTGRES_PASSWORD` | De Superuser, benotzt vum Container a Backups |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Roll-Passwierder, beim éischte Start gesat |
| `DATABASE_URL` | D'Applikatiounsroll. Row-level security gëllt fir all Ufro, déi se mécht |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | D'Migrator-Roll, fir `migrate` an `init` |
| `QUIRE_SUPERUSER_URL` | Nëmmen beim éischte Start benotzt |
| `QUIRE_REPORT_DATABASE_URL` | D'Lies-engem Berichtsroll, fir Berichter an de Berichtsbuilder |
| `QUIRE_AUDIT_DATABASE_URL` | D'Audit-Roll, fir d'Audit-Konsole an den SIEM-Export |
| `QUIRE_DATABASE_ID` | Eng belleg UUID, fix fir d'Liewen vun der Installatioun |

Roll-Passwierder gi nëmmen ugewannt, wann de Datebank-Volume éischt erstellt gëtt. Fir een méi spéit z'änneren, benotzt `ALTER ROLE` an aktualiséiert dann déi passend URL.

`QUIRE_REPORT_DATABASE_URL` gëtt fir déi physesch Datebank benotzt, déi vun `DATABASE_URL` konfiguréiert ass. Fir all aner registréiert physesch Datebank setzt seng eegen `quire_report`-Verbindungs-URL an den Ëmwelten vu Web a Worker, da setzt de Variabelen-Numm an dat **Reporting environment variable**-Feld vun där Datebank als `env:NAME`. D'Referenz muss op déiselwecht Datebank weisen wéi seng App-Verbindung, idealerweis hire Lies-Replika. All Berichtsfläch follegt dem Tenant bei seng eegen Datebank-Berichtsverbindung: de Berichtsbuilder a gespäichert Berichter, geplangte Liwwerungen, Berichts-Exporten, Analysen, den Audit-Log, d'REST-Audit-Ressourcen an d'Audit-Sich vum Assistent. Keng léint jeemools d'Berichts-URL vun enger anerer Datebank. Wann eng Datebank keng Berichtsverbindung huet, lafen gewéinlech Berichter op der eegener Applikatiounsverbindung vun där Datebank, wärend Analysen an all Audit-Lies refuséieren an dat soen, well d'Applikatiounsroll den Audit-Trail net liese kann.

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

| Astellung | Dës Release | Notizen |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (Standard), `s3` oder `azure` | `local` hält Fichieren am `files`-Volume. `s3` deckt AWS S3, R2, GCS-Interoperabilitéit an aner S3-kompatibel Späicher of, mat resumable Multipart-Eroplueden |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (Standard), `sse`, `centrifugo` oder `durable_objects` | `inprocess` ass richteg fir ee Web-Container; benotzt `centrifugo` oder `sse` wann et der méi gëtt |
| `QUIRE_CACHE_DRIVER` | `memory` (Standard), `postgres` oder `valkey` | `memory` ass pro Prozess; benotzt `valkey` oder `postgres` sou datt Ratenlimiten iwwer Container halen |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (Standard) oder `progressive_mp4` | Oder en gehosten Ubidder: Cloudflare Stream, Mux oder Bunny, iwwer hir Schlësselen |
| `QUIRE_IMAGE_DRIVER` | `noop` (Standard), `imgproxy` oder `cloudflare` | `noop` servéiert all Bild an senger Originalgréisst. `imgproxy` brauch de `images`-Profil an d'Astellungen drënner; `cloudflare` benotzt Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` oder `in_process` | De Plattform-Standard fir Live-Sessiounen. Ongesat soen Live-Sessiounen datt se net konfiguréiert sinn, bis eng Organisatioun hiren eegenen Kont ënner Integratiounen, Live-Sessiouns-Ubidder verbënnt. Den eegene Kont vun enger Organisatioun gewënnt ëmmer iwwer dëse Wäert. Déi eegen Astellunge vun all Ubidder (`BBB_URL` an `BBB_SECRET`, d'`ZOOM_*`-, `TEAMS_*`-, `GOOGLE_MEET_*`- an `JITSI_*`-Variabelen) gi nëmmen fir den Ubidder gelies, deen hei genannt ass |
| `QUIRE_MEETING_REGIONS` | Eng Komma-Lëscht vun `eu`, `uk`, `us` | Wou de Plattform-Standard-Ubidder Sessioune veraarbecht. Ongesat gëtt en net géint eng Organisatioun gepréift, déi op eng Regioun festgeluecht ass, wéi virdrun. Den eegene Kont vun enger Organisatioun nennt seng Regiounen op senger Säit |

En Driver-Wäert, deen dës Release net enthält, gëtt refuséiert wann de Web-Tier start, mat der Astellung genannt, amplaz roueg duerch de Standard ersat ze ginn.

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

Säite froe Biller a véier feste Gréissten iwwer `/api/files/{id}/image/{size}`, wat dee selwechten Zougang wéi de Fichier selwer kontrolléiert an dann op de Bildservice viruleet. All Organisatioun däerf `QUIRE_IMAGE_SPECS_PER_HOUR` (Standard 2000) nei Bild- a Gréisst-Pairen d'Stonn froen; Gréissten, déi dës Stonn scho produzéiert goufen, zielen net. Benotzt `valkey` oder `postgres` fir `QUIRE_CACHE_DRIVER` mat méi wéi engem Web-Container, sou datt d'Limitt iwwer se hält.

| Astellung | Driver | Notizen |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | D'Adress, iwwer déi Browser imgproxy erreechen, zum Beispill `https://images.example.org`. De `images`-Profil publizéiert en op `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Hex-Strings, déi selwechte Wäerter mat deenen imgproxy gestart gëtt. Generéiert all mat `openssl rand -hex 32`. Quire signéiert all Bild-Adress mat hinnen, sou datt imgproxy näischt rendert wat Quire net gefrot huet |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` mat lokalem Späicher | Wou imgproxy Originaler hier hëlt. Compose setzt `http://web:3000`. Mat `s3`- oder `azure`-Späicher hëlt imgproxy aus dem Bucket an dëst gëtt net benotzt |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | En API-Token mat Images-Edit-Permissioun, an den Account-Hash aus Images, Developer-Ressourcen. Maacht flexibel Varianten fir de Kont un |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Optional. Wann gesat, si Biller privat an all Adress ass signéiert a leeft of. Ouni et si Biller ëffentlech op Adressen ofgeleet vu `QUIRE_SECRET_KEY` déi keen rode kann |

Cloudflare Images hält seng eegen Kopie vun all Original, dat en servéiert. Wann e Fichier geläscht gëtt, läscht de Worker déi Kopie virum Original.

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

Hannergrond-Jobe benotzen pg-boss an derselwechter Postgres-Datebank, sou datt et kee Queue-Service ze bedreiwen an näischt ze konfiguréieren gëtt. Jobe ginn an derselwechter Transaktioun an d'Queue geluecht wéi d'Ännerung, déi se verursaacht huet, sou datt e Crash keen verléiere kann oder een duebel schécken. `QUIRE_QUEUE_DRIVER` ass hei `pgboss`, säi Standard; `vercel` a `cloudflare` verréckelen nëmmen déi liicht Notifikatiouns- a Webhook-Liwwerungen op déi eegen Queue vun der Plattform, an d'Vercel- an d'Cloudflare-Guiden beschreiwen se a wéi hir Web-Tiere an d'Queue leeën.

### E-Mail <!--quire:email-->

Setzt een vun:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: en JSON-Objet, deen en HTTP-Ubidder a seng Zougangsdaten nennt, zum Beispill `{"provider":"postmark","token":"..."}`. Postmark, Amazon SES, Mailgun, SendGrid a Resend gi ënnerstëtzt.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Nëmmen dëst Zil; d'serverlos Ziler blockéieren SMTP.

`QUIRE_MAIL_FROM` ass den Absender. Fir Quire auszebréngen, start de `devmail`-Profil, setzt `QUIRE_SMTP_URL=smtp://mailpit:1025`, a liest Mail op `http://localhost:8025`.

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

| Astellung | Mat Profil |
| --- | --- |
| `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` oder `QUIRE_MEILISEARCH_URL` | Extern Sich; soss Postgres-Volltext |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Passwuert-Breach-Check. Standardméisseg un géint `api.pwnedpasswords.com` (nëmmen e fënnef-Zeechen Hash-Präfix gëtt geschéckt); `off` schalt en aus, an d'URL weist op eng Range-API déi Dir host |

### Observabilitéit <!--quire:observability-->

`OTEL_EXPORTER_OTLP_ENDPOINT` nennt de Sammler un deen all Prozess Tracen a Metriken schéckt; mam `observability`-Profil ass et `http://otelcol:4318`, an `docker/otel-collector.yaml` ass wou Dir den Exporter fir Äre Backend derbäisetzt. De Web-Tier, Worker, Scheduler, Content- a Collab-Prozesser exportéieren Spannen iwwer OTLP/HTTP (Web-Demanden, Tenant-Datebank-Transaktiounen, Worker-Joben an erausginn Appellen) wann et gesat ass, a Metriken op dee selwechten Endpoint all Minutt (`OTEL_METRICS_EXPORTER=none` schalt se aus). `OTEL_TRACES_SAMPLER_ARG` setzt den Undeel vun den Tracen, déi behale ginn. Logge ginn op Standard-Output op `LOG_LEVEL`, a Compose rotéiert se. Tracen droen ni perséinlech Donnéeën.

### Regional Egress (EU-Datenresidenz) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` seet datt de Stack Organisatioune vun der Europäescher Unioun bedéngt. De Worker hält dann all erausginn Ufro, déi fir eng Organisatioun gemaach gëtt, déi op d'EU festgeluecht ass, un eng Allowlist (21-compliance.md Kapitel 8.1). D'Allowlist sinn d'Hosten, déi déi konfiguréiert Servicer fir d'Regioun deklaréieren (den Späicher-Endpoint, den E-Mail-Ubidder, en gehosten Video-Ubidder, d'eegen Späicherziler vun der Organisatioun, KI-Ubidder an E-Mail-Kont), d'Hosten vun all Service ënner enger aktiver Derogatioun, an d'Hosten, déi Dir an `QUIRE_EGRESS_ALLOW_HOSTS` lëscht. Eng Ufro un all aneren ëffentlechen Host gëtt refuséiert ier se geschéckt gëtt, d'Refus gëtt an den Audit-Trail vun der Organisatioun als `privacy/egress_refused` geschriwwen, an en ass ënner Compliance, Datenresidenz gelëscht.

| Astellung | Wäerter | Effekt |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Eng Komma-Lëscht vun Hostnamen, oder `*.example.org` fir all Ënnerdomain | Extra Hosten, déi eng EU-Organisatioun erreechen däerf. Webhook-, xAPI- an SIEM-Endpoints, Blog-Feeds an Amazon SES-Hosten gehéieren heihin, well se d'eegen Wiel vun enger Organisatioun sinn a kee Service se deklaréiert. Loopback, privat Adressen an eenzel Label-Nimm wéi `web` oder `clamav` sinn Ären eegenen Netzwierk a gi ni gepréift |

UK- an US-Organisatioune gi net un eng Host-Lëscht gehalen; se behalen d'Service-Regiouns-Checken. Setzt d'Lëscht op dem Worker; d'Admin-Säit liest se um Web-Tier fir d'Allowlist ze weisen, sou setzt se an `docker/.env`, wat all Service liest.

De Check vun der Applikatioun gëtt e kloere Feeler an en Audit-Agank, an en ass net d'Garantie: Code ka falsch sinn. D'Garantie ass den Netzwierk. Compose setzt en net fir Iech duerch. Fir e regionale Stack setzt d'`worker`- an d'`web`-Servicer op en `internal: true`-Netzwierk, deem seng eenzeg Streck eraus en Egress-Proxy ass (zum Beispill Squid oder en tinyproxy-Container) deen déi selwecht Hosten erlaabt wéi `QUIRE_EGRESS_ALLOW_HOSTS` plus d'Hosten vun Äre konfiguréierte Servicer, a setzt `HTTPS_PROXY` fir déi Servicer. D'Residenz-Säit lëscht déi exakt Hosten, déi d'Applikatioun erlaabt, sou datt déi zwou Lëschte verglach kënne ginn.

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

| Endpoint | Bedeitung |
| --- | --- |
| `/healthz` | Liveness: de Prozess äntwert. Compose-Gesondheets-Checke benotzen dëst |
| `/readyz` | Readiness: Ofhängegkeeten erreechbar, an all optionale Service als konfiguréiert oder net gemellt. Riicht Äre Load-Balancer heihin |

`docker compose -f docker/compose.yaml ps` weist d'Gesondheet vun all Service.

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

De `proxy`-Service (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) ass Deel vum Standard-Stack. En äntwert op de Porten 80 an 443 a rout:

| Host oder Wee | Geet bei |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, all Tenant-Ënnerdomain an personaliséiert Domain | `web` |
| `/_collab/` op deenen Hosten | `collab` (Websocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` op deenen Hosten | De Client-Websocket vum `centrifugo`; seng Server-API gëtt ni exposéiert |
| `/_images/` op deenen Hosten | `imgproxy`, mam `images`-Profil (`IMGPROXY_URL`) |

`init-env.sh` leet `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`, `QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` an `IMGPROXY_URL` vun deenen zwou Originen of, sou datt se net ausernee drifte kënnen. Editéiert se zesummen wann Dir eng Origin vun Hand ännert.

Zertifikater follegen `QUIRE_PROXY_TLS`:

- `internal` (de Standard): Caddy seng eegen Zertifikatsautoritéit, fir `localhost`, `*.localhost` an `lvh.me`. Vertraut hirer Root eemol, da browst:

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

  Setzt `quire-local-ca.crt` an de System- oder Browser-Vertrauensstore. `curl` hëlt en mat `--cacert`.
- Eng E-Mail-Adress: automatesch ACME-Zertifikater (Let's Encrypt, dann ZeroSSL) fir richteg Hostnamen. DNS fir béid Originen an all Tenant-Host muss heihin weisen, an d'Porten 80 an 443 musse vum Internet erreechbar sinn.

Tenant-Hoste ginn op Demande ausgestallt, beim éischte Besuch, an nëmmen wann Web bestätegt datt den Numm zu dëser Installatioun gehéiert (`/tls-allowed`, gefrot um Compose-Netzwierk). Kee Wildcard-Zertifikat oder DNS-Ubidder-Plugin ass néideg, an e Friemen, deen en Numm op de Host weist, kann en net dozou bréngen Zertifikater unzefroen. Zertifikater an déi lokal Autoritéit liewen am `caddy-data`-Volume; sichert en mat de Rescht wann Dir `internal` benotzt.

Web gleeft `X-Forwarded-For` nëmmen vum Proxy: de Proxy huet eng fix Adress (`QUIRE_PROXY_ADDRESS`, Standard `172.29.64.10`) op engem fixen Ënnernetz (`QUIRE_COMPOSE_SUBNET`), an `QUIRE_TRUSTED_PROXY_CIDRS` nennt déi Adress. Wann d'Ënnernetz mat engem Netzwierk um Host kollidéiert, ännert béid a féiert `docker compose down` virum `up` aus.

## Hanner Ärem eegenen Reverse-Proxy <!--quire:behind-your-own-reverse-proxy-->

Fir e Load-Balancer oder Proxy ze benotzen, deen Dir scho bedreiwt, loosst `proxy` ewech (`docker compose up -d --scale proxy=0`) a schléisst TLS viru `web` (8080), `content` (8081), `collab` (1234, Websocket) a `centrifugo` (8000, Websocket) of. Setzt déi ëffentlech Adressen an `QUIRE_APP_ORIGIN`, `QUIRE_CONTENT_ORIGIN` an `QUIRE_COLLAB_URL` (`wss://`), an d'Adress-Beräich vun Ärem Proxy an `QUIRE_TRUSTED_PROXY_CIDRS`.

## Problemléisung <!--quire:troubleshooting-->

- `init` geet eraus mat "QUIRE_DATABASE_ID is not a UUID": setzt en mat `uuidgen`.
- `web` start nei mat "did not start on compose": de Log lëscht all Astellung déi en net respektéiere kann a wat amplaz ze benotzen ass.
- En Roll-Passwuert an `.env` no dem éischte Start änneren mécht näischt: den Init-Skript leeft eemol. Benotzt `ALTER ROLE`.
- Eroplueden feelen mat engem Scan-Feeler wärend `CLAMAV_URL` gesat ass: ClamAV luet seng Signaturen beim éischte Start erof, wat e puer Minutten dauert.

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