---
title: "Installer Quire avec Docker Compose"
description: "Installer Quire sur votre propre infrastructure avec Docker Compose."
image: "https://docs.quirelms.com/og.png"
---

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

# Installer Quire avec Docker Compose

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

Il s’agit du produit complet sur un seul hôte : le LMS, ses tâches en arrière-plan, les services temps réel et de modification collaborative, et tous les services facultatifs activés par un profil. La conception est décrite à la section 2 de `docs/architecture/23-ops.md`.

Autres cibles : [Vercel](/fr-CA/ops/vercel/) et [Cloudflare Workers](/fr-CA/ops/cloudflare/) n’exécutent que la couche Web. Les mises à niveau sont décrites dans [upgrade.md](/fr-CA/ops/upgrade/), et les sauvegardes et l’exercice de restauration dans [backup-restore.md](/fr-CA/ops/backup-restore/).

## Prérequis <!--quire:what-you-need-->

- Docker Engine 27 ou version ultérieure avec le module Compose 2.30 ou version ultérieure.
- 4 cœurs de processeur et 8 Go de mémoire pour la pile par défaut; 8 cœurs et 16 Go avec `--profile full` (ClamAV utilise à lui seul environ 1,5 Go de signatures).
- Un nom DNS pour la couche Web et un autre pour le contenu non fiable. Il doit s’agir d’hôtes différents : les modules SCORM et le HTML téléversé sont exécutés sur l’origine du contenu et ne peuvent ainsi jamais lire les témoins du LMS.
- Pour un essai local, `lvh.me` et `*.localhost` se résolvent en 127.0.0.1, comme l’utilise `docker/.env.example`. Le service `proxy` de la pile sert les deux en HTTPS avec une autorité de certification locale; aucun autre élément n’est donc installé (consultez « TLS »).
- Les ports 80 et 443 doivent être libres sur l’hôte (`QUIRE_PROXY_HTTP_PORT` et `QUIRE_PROXY_HTTPS_PORT` permettent de les déplacer).

## Premier démarrage <!--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` crée `docker/.env` à partir de `docker/.env.example` et génère tous les secrets (mots de passe de base de données, clés de signature et principale, paire de clés de lancement du contenu), ainsi que la clé de signature du point de contrôle d’audit à `docker/secrets/audit-signing-key.pem`, que Compose monte dans les processus de travail en tant que secret. Seuls `sh`, `awk` et `openssl` sont nécessaires, et le script refuse d’écraser un fichier `docker/.env` existant. Copiez les deux fichiers à l’extérieur de l’hôte : sans `QUIRE_MASTER_KEY`, une base restaurée ne peut pas déchiffrer les justificatifs qu’elle contient. Pour remplir le fichier à la main, exécutez plutôt `cp docker/.env.example docker/.env`; le fichier indique comment générer chaque secret.

Les deux origines doivent utiliser `https` : en production, le service de contenu refuse le HTTP non chiffré, et les origines ne doivent pas partager le même domaine enregistrable. Le service `proxy` termine TLS pour les deux (consultez « TLS »); `init-env.sh` refuse une origine `http://`.

La pile démarre dans un ordre fixe; chaque étape attend que la précédente soit terminée :

1. `postgres` devient sain. Lors du tout premier démarrage, son script d’initialisation (`docker/postgres/init/90-passwords.sh`) définit les mots de passe des quatre rôles.
2. `migrate` applique toutes les migrations et initialise la file de tâches dans la base de contrôle et dans chaque base de locataire dédiée; il vérifie qu’elles concordent toutes, puis se termine (docs/ops/upgrade.md).
   Les migrations sont exécutées à chaque démarrage et sont idempotentes; une mise à niveau consiste donc à utiliser une nouvelle image et à redémarrer.
3. `init` (`apps/web/src/first-run.ts`) inscrit la base de données de l’application sous `QUIRE_DATABASE_ID` et, si `QUIRE_SETUP_ADMIN_EMAIL` est défini, crée la première organisation et son administrateur. L’adresse de connexion et un mot de passe généré sont affichés une seule fois dans `docker compose logs init`.
4. `web`, `content`, `worker`, `scheduler`, `collab` et `centrifugo` démarrent.
5. `proxy` démarre lorsque `web` et `content` sont sains.

Ouvrez `https://demo.` suivi du domaine de votre application (le journal `init` affiche l’adresse de connexion exacte), puis ouvrez une session. Sur une installation locale, faites d’abord confiance à l’autorité de certification du mandataire (consultez « TLS »). Changez le mot de passe généré à `/account/security`.

Un processus lancé sans un secret obligatoire refuse de démarrer et nomme le paramètre manquant dans son journal. Aucun composant ne démarre avec une configuration incomplète.

## Services et profils <!--quire:services-and-profiles-->

| Service | Profil | Fonction |
| --- | --- | --- |
| postgres | toujours | Base de données (PostgreSQL 18 avec pgvector, compilé à partir de `docker/postgres.Dockerfile`), avec archivage du WAL dès le premier démarrage |
| migrate, init | toujours | Exécution ponctuelle : migrations, puis premier démarrage |
| web | toujours | LMS, sur `QUIRE_HTTP_PORT` (8080) |
| content | toujours | Origine du contenu non fiable, sur `QUIRE_CONTENT_PORT` (8081) |
| worker | toujours | Tâches en arrière-plan : courriels, rapports, traitement des fichiers et webhooks |
| scheduler | toujours | Tâches récurrentes : inscrit les 64 planifications d’exécution et les transmet au processus de travail; un seul responsable à la fois |
| collab | toujours | WebSocket de modification collaborative, sur `QUIRE_COLLAB_HTTP_PORT` (1234) |
| centrifugo | toujours | Diffusion temps réel, sur `QUIRE_REALTIME_PORT` (8000) |
| proxy | toujours | Caddy, point d’entrée TLS sur les ports 80 et 443 (consultez « TLS ») |
| valkey | `cache` | Cache et limites de débit |
| clamav | `scan` | Analyse des fichiers téléversés à la recherche de logiciels malveillants |
| gotenberg | `preview` | Aperçus PDF de documents Office et rendu des certificats |
| imgproxy | `images` | Redimensionnement et conversion d’images |
| transcoder | `video` | Image du processus de travail avec ffmpeg sous licence LGPL uniquement, pour créer les rendus vidéo |
| seaweedfs | `storage` | Stockage d’objets compatible S3 sur cet hôte |
| otelcol | `observability` | Collecteur OpenTelemetry |
| mailpit | `devmail` | Capture tous les courriels sortants pour permettre d’essayer Quire |
| backup | `backup` | Sauvegarde de base ponctuelle; consultez backup-restore.md |
| backup-scheduler, backup-offsite | `backup` | Sauvegarde de base toutes les `QUIRE_BACKUP_INTERVAL_HOURS` et copies chiffrées hors hôte avec exercice de vérification hebdomadaire |
| h5p | `h5p` | Image de l’outil H5P LTI 1.3 que vous fournissez dans `QUIRE_H5P_IMAGE`, sur `QUIRE_H5P_PORT` (8090); consultez « Connecter un fournisseur H5P » |

`--profile full` démarre tous les services facultatifs, sauf `backup` et `h5p`. Pour en démarrer un, exécutez `docker compose -f docker/compose.yaml --profile scan up -d`. Quire fonctionne aussi sans service facultatif et indique ce qui manque : sans analyseur, les fichiers sont enregistrés sans être analysés et l’administrateur en est informé; sans Gotenberg, les fichiers peuvent être téléchargés, mais pas prévisualisés; sans transcodeur, la vidéo est lue dans son fichier original.

Les images de tiers et leurs obligations de licence sont répertoriées dans `docker/third-party-containers.yaml`.

### Connecter un fournisseur H5P <!--quire:connecting-an-h5p-provider-->

Quire n’intègre ni ne distribue de moteur ou de service auxiliaire H5P (ADR 0019). Pour utiliser H5P, procurez-vous votre propre abonnement hébergé ou exploitez une instance H5P autohébergée séparément de Quire. Enregistrez ce fournisseur comme outil externe LTI 1.3 et ajoutez son contenu aux cours sous forme d’activités d’outil. Quire échange les notes et la progression des activités et de leur correction par l’intermédiaire des LTI Assignment and Grade Services (AGS). Si le fournisseur envoie aussi des énoncés xAPI, configurez-les séparément pour le magasin d’énoncés xAPI de Quire; l’échange des notes et de la progression AGS n’envoie pas d’énoncés xAPI. Les importations Moodle signalent que les activités H5P nécessitent une connexion à un outil LTI. Le fournisseur reste responsable de son moteur H5P, de la création du contenu, de sa banque de contenu et de l’historique des tentatives.

Pour exploiter votre propre instance autohébergée sur cet hôte, définissez `QUIRE_H5P_IMAGE` sur son image et démarrez le profil `h5p`. Compose la publie sur `QUIRE_H5P_PORT` (8090) et conserve ses données dans le volume `h5p-data`; l’image et les obligations qui s’y rattachent restent sous votre responsabilité.

## Paramètres <!--quire:settings-->

Chaque processus lit `docker/.env`. Le modèle `docker/.env.example` répertorie chaque paramètre et sa valeur par défaut. Voici les groupes :

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

| Paramètre | Signification |
| --- | --- |
| `QUIRE_APP_ORIGIN` | Adresse publique du LMS, par exemple `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Origine du contenu, sur un autre hôte |
| `QUIRE_PLATFORM_DOMAINS` | Domaines des organisations, séparés par des virgules |
| `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` ici. Consultez les autres guides pour `vercel` et `cloudflare` |
| `QUIRE_TRUSTED_PROXY_CIDRS` | Mandataires dont l’en-tête `X-Forwarded-For` est considéré comme fiable |

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

| Paramètre | Signification |
| --- | --- |
| `QUIRE_SECRET_KEY` | Signe les sessions et les jetons. 64 caractères hexadécimaux |
| `QUIRE_MASTER_KEY` | Enveloppe les justificatifs conservés, comme les secrets SSO et de webhook. 32 octets, en base64. La couche Web et le processus de travail doivent partager la même valeur. Rotation : [key-rotation.md](/fr-CA/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Étiquette de version de la clé principale, `v1` si elle n’est pas définie. Incrémentez-la lors d’une rotation |
| `QUIRE_MASTER_KEY_RETIRED` | Anciennes clés principales encore nécessaires pour lire les valeurs qu’elles ont scellées, sous la forme `v1=<base64>`. Retirez-les une fois la rotation terminée sans élément non résolu |
| `QUIRE_COLLAB_SIGNING_KEY` | Partagée entre web et collab pour signer les jetons de modification |
| `QUIRE_BACKUP_SIGNING_KEY` | Signe les sauvegardes de cours (facultative) |

Gardez une copie de `QUIRE_MASTER_KEY` ailleurs que sur cet hôte. Une base restaurée sans cette clé ne peut pas déchiffrer les justificatifs qu’elle contient.

### Base de données <!--quire:database-->

| Paramètre | Signification |
| --- | --- |
| `POSTGRES_PASSWORD` | Superutilisateur utilisé par le conteneur et les sauvegardes |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Mots de passe des rôles, définis au premier démarrage |
| `DATABASE_URL` | Rôle d’application. La sécurité au niveau des lignes s’applique à chacune de ses requêtes |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | Rôle de migration utilisé par `migrate` et `init` |
| `QUIRE_SUPERUSER_URL` | Utilisé uniquement lors du premier démarrage |
| `QUIRE_REPORT_DATABASE_URL` | Rôle de rapport en lecture seule, pour les rapports et leur générateur |
| `QUIRE_AUDIT_DATABASE_URL` | Rôle d’audit, pour la console d’audit et l’exportation SIEM |
| `QUIRE_DATABASE_ID` | N’importe quel UUID, fixe pendant toute la durée de l’installation |

Les mots de passe des rôles ne sont appliqués que lors de la création initiale du volume de la base de données. Pour en modifier un par la suite, utilisez `ALTER ROLE`, puis mettez à jour l’URL correspondante.

`QUIRE_REPORT_DATABASE_URL` s’utilise pour la base physique configurée dans `DATABASE_URL`. Pour toute autre base physique enregistrée, définissez sa propre URL de connexion `quire_report` dans les environnements Web et de travail, puis saisissez le nom de la variable dans le champ **Variable d’environnement de rapports** de cette base, sous la forme `env:NAME`. La référence doit désigner la même base que la connexion de l’application, idéalement sa réplique en lecture seule. Chaque interface de rapport suit le locataire jusqu’à la connexion de rapport de sa propre base : générateur et rapports enregistrés, livraisons planifiées, exportations de rapports, analyses, journal d’audit, ressources d’audit REST et recherche d’audit de l’assistant. Aucune ne réutilise l’URL de rapport d’une autre base. Si une base n’a aucune connexion de rapport, les rapports ordinaires utilisent sa propre connexion d’application; les analyses et toute lecture d’audit sont refusées et l’indiquent, car le rôle d’application ne peut pas lire la piste d’audit.

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

| Paramètre | Valeurs dans cette version | Notes |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (par défaut), `s3` ou `azure` | `local` conserve les fichiers dans le volume `files`. `s3` prend en charge AWS S3, R2, l’interopérabilité GCS et d’autres stockages compatibles S3, avec des téléversements multiparties reprenables |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (par défaut), `sse`, `centrifugo` ou `durable_objects` | `inprocess` convient à un seul conteneur Web; utilisez `centrifugo` ou `sse` s’il y en a plusieurs |
| `QUIRE_CACHE_DRIVER` | `memory` (par défaut), `postgres` ou `valkey` | `memory` est propre à chaque processus; utilisez `valkey` ou `postgres` pour que les limites de débit soient appliquées entre les conteneurs |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (par défaut) ou `progressive_mp4` | Ou un fournisseur hébergé : Cloudflare Stream, Mux ou Bunny, au moyen de leurs clés |
| `QUIRE_IMAGE_DRIVER` | `noop` (par défaut), `imgproxy` ou `cloudflare` | `noop` sert chaque image dans sa taille originale. `imgproxy` exige le profil `images` et les paramètres ci-dessous; `cloudflare` utilise Cloudflare Images |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` ou `in_process` | Fournisseur de la plateforme par défaut pour les séances en direct. S’il n’est pas défini, les séances en direct sont signalées comme non configurées jusqu’à ce qu’une organisation connecte son compte sous Intégrations, Fournisseur de séances en direct. Le compte propre à une organisation a toujours priorité. Les paramètres propres à chaque fournisseur (`BBB_URL` et `BBB_SECRET`, les variables `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*` et `JITSI_*`) sont lus uniquement pour le fournisseur indiqué ici |
| `QUIRE_MEETING_REGIONS` | Liste de valeurs `eu`, `uk`, `us` séparées par des virgules | Régions où le fournisseur par défaut de la plateforme traite les réunions. Si ce paramètre n’est pas défini, la région n’est pas vérifiée par rapport aux organisations rattachées à une région, comme auparavant. Le compte propre à une organisation indique ses régions sur sa page |

Si la couche Web démarre avec une valeur de pilote absente de cette version, elle refuse cette valeur en nommant le paramètre au lieu de la remplacer silencieusement par la valeur par défaut.

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

Les pages demandent les images en quatre tailles fixes par `/api/files/{id}/image/{size}`, qui vérifie les mêmes droits d’accès que le fichier, puis redirige vers le service d’images. Chaque organisation peut demander jusqu’à `QUIRE_IMAGE_SPECS_PER_HOUR` (2000 par défaut) nouvelles combinaisons d’image et de taille par heure; les tailles déjà produites durant l’heure ne comptent pas. Si vous avez plus d’un conteneur Web, utilisez `valkey` ou `postgres` pour `QUIRE_CACHE_DRIVER` afin que la limite soit commune aux conteneurs.

| Paramètre | Pilote | Notes |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Adresse à laquelle les navigateurs accèdent à imgproxy, par exemple `https://images.example.org`. Le profil `images` le publie sur `QUIRE_IMAGES_PORT` (8082) |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Chaînes hexadécimales, identiques aux valeurs utilisées pour démarrer imgproxy. Générez-les avec `openssl rand -hex 32`. Quire signe chaque adresse d’image avec ces valeurs; imgproxy ne rend donc que ce que Quire lui demande |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` avec stockage local | Emplacement où imgproxy récupère les originaux. Compose définit `http://web:3000`. Avec le stockage `s3` ou `azure`, imgproxy récupère les images dans le compartiment; ce paramètre n’est alors pas utilisé |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Jeton d’API doté du droit de modifier Images et valeur de hachage du compte indiquée sous Images, Ressources pour développeurs. Activez les variantes flexibles pour le compte |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Facultative. Lorsqu’elle est définie, les images sont privées et chaque adresse est signée et expire. Sans cette clé, les images sont publiques, à des adresses dérivées de `QUIRE_SECRET_KEY` que personne ne peut deviner |

Cloudflare Images conserve sa propre copie de chaque original servi. Lorsqu’un fichier est supprimé, le processus de travail supprime cette copie avant l’original.

### File d’attente <!--quire:queue-->

Les tâches en arrière-plan utilisent pg-boss dans la même base PostgreSQL; aucun service de file d’attente n’est donc à exécuter ou à configurer. Les tâches sont ajoutées dans la même transaction que la modification qui les a déclenchées; une panne ne peut donc ni en perdre une ni l’envoyer deux fois. Ici, `QUIRE_QUEUE_DRIVER` vaut `pgboss`, sa valeur par défaut; `vercel` et `cloudflare` déplacent uniquement les livraisons légères de notifications et de webhooks dans la file propre à la plateforme. Les guides Vercel et Cloudflare décrivent ces files et la manière dont leurs couches Web y ajoutent les tâches.

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

Définissez l’un des paramètres suivants :

- `QUIRE_EMAIL_PROVIDER_CONFIG` : objet JSON indiquant un fournisseur HTTP et ses justificatifs, comme `{"provider":"postmark","token":"..."}`. Postmark, Amazon SES, Mailgun, SendGrid et Resend sont pris en charge.
- `QUIRE_SMTP_URL` : `smtp://user:password@host:587`. Cette cible seulement; les cibles sans serveur bloquent SMTP.

`QUIRE_MAIL_FROM` indique l’expéditeur. Pour essayer Quire, démarrez le profil `devmail`, définissez `QUIRE_SMTP_URL=smtp://mailpit:1025` et consultez les courriels à `http://localhost:8025`.

### Services facultatifs <!--quire:optional-services-->

| Paramètre | Profil requis |
| --- | --- |
| `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` ou `QUIRE_MEILISEARCH_URL` | Recherche externe; recherche en texte intégral PostgreSQL sinon |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Vérification des mots de passe compromis. Activée par défaut auprès de `api.pwnedpasswords.com` (seul le préfixe de cinq caractères du hachage est envoyé); `off` la désactive et l’URL désigne une API de plage que vous hébergez |

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

`OTEL_EXPORTER_OTLP_ENDPOINT` indique le collecteur auquel chaque processus envoie les traces et les métriques; avec le profil `observability`, il vaut `http://otelcol:4318`, et `docker/otel-collector.yaml` permet d’ajouter l’exportateur de votre système. Lorsque ce paramètre est défini, les processus Web, worker, scheduler, content et collab exportent leurs traces par OTLP/HTTP (requêtes Web, transactions de base de données de locataire, tâches et appels sortants), ainsi que leurs métriques à cette même adresse chaque minute (`OTEL_METRICS_EXPORTER=none` les désactive). `OTEL_TRACES_SAMPLER_ARG` définit la proportion de traces conservées. Les journaux sont envoyés sur la sortie standard au niveau `LOG_LEVEL` et Compose les fait tourner. Les traces ne contiennent jamais de données personnelles.

### Trafic sortant régional (résidence des données de l’UE) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` indique que la pile dessert des organisations de l’Union européenne. Le processus de travail limite alors à une liste d’autorisation chaque requête sortante faite pour une organisation rattachée à l’UE (21-compliance.md, section 8.1). Cette liste comprend les hôtes déclarés pour la région par les services configurés (point de terminaison de stockage, fournisseur de courriel, fournisseur vidéo hébergé, cibles de stockage propres à l’organisation, fournisseurs d’IA et compte de courriel), les hôtes de tout service visé par une dérogation active et ceux inscrits dans `QUIRE_EGRESS_ALLOW_HOSTS`. Toute requête à un autre hôte public est refusée avant l’envoi; le refus est inscrit à la piste d’audit de l’organisation comme `privacy/egress_refused`, et apparaît sous Conformité, Résidence des données.

| Paramètre | Valeurs | Effet |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Liste de noms d’hôte séparés par des virgules ou `*.example.org` pour tous les sous-domaines | Hôtes supplémentaires qu’une organisation de l’UE peut joindre. Les points de terminaison webhook, xAPI et SIEM, les fils de blogue et les hôtes Amazon SES doivent y figurer, car ils sont choisis par l’organisation et aucun service ne les déclare. La boucle locale, les adresses privées et les noms à une seule étiquette comme `web` ou `clamav` appartiennent à votre réseau et ne sont jamais vérifiés |

Les organisations du Royaume-Uni et des États-Unis ne sont pas assujetties à une liste d’hôtes; les vérifications de région de service restent en vigueur. Définissez la liste sur le processus de travail; la page d’administration la lit sur la couche Web pour afficher la liste d’autorisation. Inscrivez-la donc dans `docker/.env`, lu par chaque service.

La vérification de l’application fournit une erreur claire et une entrée d’audit, mais ce n’est pas la garantie : le code peut être erroné. La garantie relève du réseau. Compose ne l’applique pas à votre place. Pour une pile régionale, placez les services `worker` et `web` sur un réseau `internal: true` dont la seule sortie passe par un mandataire de trafic sortant (par exemple Squid ou un conteneur tinyproxy) qui autorise les mêmes hôtes que `QUIRE_EGRESS_ALLOW_HOSTS`, ainsi que ceux des services configurés; définissez `HTTPS_PROXY` pour ces services. La page de résidence répertorie les hôtes effectivement autorisés par l’application afin que vous puissiez comparer les deux listes.

## État de santé <!--quire:health-->

| Point de terminaison | Signification |
| --- | --- |
| `/healthz` | Vitalité : le processus répond. Les vérifications de santé Compose l’utilisent |
| `/readyz` | Préparation : les dépendances sont accessibles et chaque service facultatif est indiqué comme configuré ou non. Dirigez-y votre répartiteur de charge |

`docker compose -f docker/compose.yaml ps` affiche l’état de santé de chaque service.

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

Le service `proxy` (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) fait partie de la pile par défaut. Il répond sur les ports 80 et 443 et dirige le trafic ainsi :

| Hôte ou chemin | Destination |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, chaque sous-domaine de locataire et domaine personnalisé | `web` |
| `/_collab/` sur ces hôtes | `collab` (WebSocket, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` sur ces hôtes | WebSocket client de `centrifugo`; son API serveur n’est jamais exposée |
| `/_images/` sur ces hôtes | `imgproxy`, avec le profil `images` (`IMGPROXY_URL`) |

`init-env.sh` déduit `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`, `QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL` et `IMGPROXY_URL` des deux origines, afin qu’ils ne divergent pas. Modifiez-les ensemble si vous changez une origine à la main.

Les certificats dépendent de `QUIRE_PROXY_TLS` :

- `internal` (valeur par défaut) : autorité de certification propre à Caddy, pour `localhost`, `*.localhost` et `lvh.me`. Faites confiance une fois à sa racine, puis récupérez-la ainsi :

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

  Ajoutez `quire-local-ca.crt` au magasin de certificats de confiance du système ou du navigateur. `curl` la prend en charge avec `--cacert`.
- Une adresse de courriel : certificats ACME automatiques (Let’s Encrypt, puis ZeroSSL) pour les vrais noms d’hôte. Le DNS des deux origines et de chaque hôte de locataire doit pointer ici, et les ports 80 et 443 doivent être accessibles depuis Internet.

Les certificats des hôtes de locataire sont demandés à la première visite et uniquement lorsque web confirme que le nom appartient à cette installation (`/tls-allowed`, demandé sur le réseau Compose). Aucun certificat générique ni module d’extension de fournisseur DNS n’est nécessaire; un tiers ne peut pas provoquer une demande de certificat en faisant pointer un nom vers l’hôte. Les certificats et l’autorité locale se trouvent dans le volume `caddy-data`; sauvegardez-le avec le reste si vous utilisez `internal`.

web ne fait confiance qu’au mandataire pour `X-Forwarded-For` : l’adresse du mandataire est fixe (`QUIRE_PROXY_ADDRESS`, `172.29.64.10` par défaut) sur un sous-réseau fixe (`QUIRE_COMPOSE_SUBNET`), et `QUIRE_TRUSTED_PROXY_CIDRS` indique cette adresse. Si le sous-réseau chevauche un réseau de l’hôte, modifiez les deux et exécutez `docker compose down` avant `up`.

## Derrière votre propre mandataire inverse <!--quire:behind-your-own-reverse-proxy-->

Pour utiliser plutôt un répartiteur de charge ou un mandataire que vous exploitez déjà, omettez `proxy` (`docker compose up -d --scale proxy=0`) et terminez TLS devant `web` (8080), `content` (8081), `collab` (1234, WebSocket) et `centrifugo` (8000, WebSocket). Définissez les adresses publiques dans `QUIRE_APP_ORIGIN`, `QUIRE_CONTENT_ORIGIN` et `QUIRE_COLLAB_URL` (`wss://`), ainsi que la plage d’adresses de votre mandataire dans `QUIRE_TRUSTED_PROXY_CIDRS`.

## Dépannage <!--quire:troubleshooting-->

- `init` se termine avec « QUIRE_DATABASE_ID is not a UUID » : définissez-le à l’aide de `uuidgen`.
- `web` redémarre avec « did not start on compose » : le journal répertorie chaque paramètre non pris en charge et la valeur à utiliser à sa place.
- Modifier un mot de passe de rôle dans `.env` après le premier démarrage ne change rien : le script d’initialisation ne s’exécute qu’une fois. Utilisez `ALTER ROLE`.
- Les téléversements échouent pendant l’analyse alors que `CLAMAV_URL` est défini : ClamAV télécharge ses signatures au premier démarrage, ce qui prend quelques minutes.

Source: https://docs.quirelms.com/fr-CA/ops/install/index.mdx
