---
title: "Docker Compose ашиглан Quire суулгах"
description: "Quire-г өөрийн дэд бүтэц дээр Docker Compose ашиглан суулгах."
image: "https://docs.quirelms.com/og.png"
---

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

# Docker Compose ашиглан Quire суулгах

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

Энэ нь нэг хост дээрх бүтэн бүтээгдэхүүн: LMS, түүний арын ажлууд, бодит цагийн болон хамтран засах үйлчилгээнүүд, мөн профайлын ард байгаа бүх сонголттой үйлчилгээнүүд. Зохион байгуулалт нь `docs/architecture/23-ops.md` хэсэг 2 юм.

Өөр зорилтууд: [Vercel](/mn/ops/vercel/) болон [Cloudflare Workers](/mn/ops/cloudflare/) нь зөвхөн веб түвшинг ажиллуулна. Шинэчлэлтүүд [upgrade.md](/mn/ops/upgrade/) дотор, нөөцлөлт болон сэргээлтийн дасгал [backup-restore.md](/mn/ops/backup-restore/) дотор байна.

## Юу шаардлагатай вэ <!--quire:what-you-need-->

- Docker Engine 27 эсвэл дээш, Compose plugin 2.30 эсвэл дээштэй.
- Өгөгдсөн багцад 4 CPU цөм, 8 GB санах ой; `--profile full`-тэй 8 цөм, 16 GB (ClamAV ганцаараа бараг 1.5 GB шинжийг барина).
- Веб түвшинд зориулсан DNS нэр, мөн итгэж болохгүй агуулгад зориулсан хоёр дахь нэр. Тэд өөр өөр хост байх ёстой: SCORM багцууд болон байршуулсан HTML нь агуулгын origin дээр ажилладаг тул LMS-ийн cookie-г хэзээ ч уншиж чадахгүй.
- Орон нутгийн туршилтын хувьд `lvh.me` болон `*.localhost` нь 127.0.0.1 рүү шийдэгддэг — энэ нь `docker/.env.example` ашигладаг зүйл юм. Багцын өөрийн `proxy` үйлчилгээ нь орон нутгийн гэрчилгээний эрх бүхийг ашиглан хоёуланг https-ээр үйлчилдэг тул өөр юу ч суулгах шаардлагагүй ("TLS" үз).
- Хост дээр 80, 443 портууд чөлөөтэй байх (`QUIRE_PROXY_HTTP_PORT` болон `QUIRE_PROXY_HTTPS_PORT` тэдгээрийг хөдөлгөнө).

## Анхны ажиллагаа <!--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` нь `docker/.env`-ийг `docker/.env.example`-аас, бүх нууцлал үүсгэсэн (өгөгдлийн сангийн нууц үгүүд, гарын үсэглэх болон мастер түлхүүрүүд, агуулгын эхлүүлэх түлхүүрийн хослол) байхад нь бичдэг бөгөөд аудитын бэхлэлтийн гарын үсэглэх түлхүүрийг `docker/secrets/audit-signing-key.pem`-д, Compose үүнийг нууцлалаар ажилчдад шигтгэдэг газарт нь байрлуулна. Үүнд зөвхөн `sh`, `awk`, `openssl` шаардлагатай бөгөөд байгаа `docker/.env`-ийг дарж бичихээс татгалздаг. Хоёр файлыг хостоос гадагш хуулж авна уу: `QUIRE_MASTER_KEY`-гүйгээр сэргээсэн өгөгдлийн сан хадгалагдсан итгэмжлэлүүдээ задалж чадахгүй. Файлыг гараар бөглөхийн тулд `cp docker/.env.example docker/.env`; файл бүр нууцлалыг хэрхэн үүсгэхийг хэлдэг.

Хоёр origin аль аль нь `https` байх ёстой: агуулгын үйлчилгээ үйлдвэрлэлийн үедэн хэвийн http-г татгалздаг бөгөөд тэд бүртгэгдэх боломжтой ижил домейн хуваалцахгүй. `proxy` үйлчилгээ хоёулангийн TLS-ийг тасладаг ("TLS" үз); `init-env.sh` нь `http://` origin-г татгалздаг.

Багц тогтсон дарааллаар эхэлдэг бөгөөд алхам бүр өмнөхөө хүлээнэ:

1. `postgres` эрүүл болно. Анхны ажиллагааны үед түүний эхлүүлэх скрипт (`docker/postgres/init/90-passwords.sh`) дөрвөн үүргийн нууц үгийг тогтоодог.
2. `migrate` бүх шилжүүлэлтийг хэрэгжүүлж, ажлын ээлжийг хяналтын өгөгдлийн сан болон бүр тусгай түрээсчийн өгөгдлийн сан бүрд эхлүүлж, тэд бүгд тохирч байгааг шалгаад, дараа нь гарна (docs/ops/upgrade.md). Шилжүүлэлтүүд бүр ажиллагаандаа ажиллаж, идемпотент байдаг тул шинэчлэлт нь шинэ дүрс болон дахин ачаалалт юм.
3. `init` (`apps/web/src/first-run.ts`) нь программын өгөгдлийн санг `QUIRE_DATABASE_ID`-н доор бүртгэж, `QUIRE_SETUP_ADMIN_EMAIL` тогтоогдсон үед анхны байгууллага, түүний администраторыг үүсгэнэ. Нэвтрэх хаяг болон үүсгэсэн нууц үг нэг удаа `docker compose logs init` дээр хэвлэгдэнэ.
4. `web`, `content`, `worker`, `scheduler`, `collab`, `centrifugo` эхэлнэ.
5. `proxy` нь `web`, `content` эрүүл болсны дараа эхэлнэ.

`https://demo.`-г өөрийн программын домейн дагуулан нээнэ үү (`init` лог нэвтрэх яг тэр хаягийг хэвлэдэг), мөн нэвтэрнэ үү. Орон нутгийн суулгалтад эхлээд проксигийн гэрчилгээний эрхийг итгэлд оруулна уу ("TLS" үз). Үүсгэсэн нууц үгээ `/account/security` дээр солино уу.

Шаардлагатай нууцлалгүйгээр эхэлсэн процесс эхлэхээс татгалзаж, лог дээрээ дутагдаж буй тохиргоог нэрлэнэ. Юу ч хагас тохируулагдсан байдлаар эхлэхгүй.

## Үйлчилгээнүүд болон профайлууд <!--quire:services-and-profiles-->

| Үйлчилгээ | Профайл | Юу хийдэг вэ |
| --- | --- | --- |
| postgres | always | Өгөгдлийн сан (pgvector-тэй PostgreSQL 18, `docker/postgres.Dockerfile`-аас бүтээгдсэн), анхны ачааллагаанаас хойш WAL архивлагдсан |
| migrate, init | always | Нэг удаагийн: шилжүүлэлтүүд, дараа нь анхны ажиллагаа |
| web | always | LMS, `QUIRE_HTTP_PORT` (8080) дээр |
| content | always | Итгэж болохгүй агуулгын origin, `QUIRE_CONTENT_PORT` (8081) дээр |
| worker | always | Арын ажлууд: имэйл, тайлан, файл боловсруулалт, вебхүүкүүд |
| scheduler | always | Давтан гардаг ажлууд: 64 ажиллагааны хуваарийг бүртгээд worker-т өгдөг; нэгэн зэрэг нэг л удирдагч |
| collab | always | Хамтран засах websocket, `QUIRE_COLLAB_HTTP_PORT` (1234) дээр |
| centrifugo | always | Бодит цагийн тархалт, `QUIRE_REALTIME_PORT` (8000) дээр |
| proxy | always | Caddy, 80, 443 портууд дээрх TLS үүд ("TLS" үз) |
| valkey | `cache` | Кэш болон хурдын хязгаарууд |
| clamav | `scan` | Байршуулалтын хортой програмын шалгалт |
| gotenberg | `preview` | Office-оос PDF урьдчилж харах, гэрчилгээ дүрслэл |
| imgproxy | `images` | Хэмжээлсэн, хөрвүүлсэн зургууд |
| transcoder | `video` | Зөвхөн LGPL ffmpeg-тэй worker дүрс, видео хувилбаруудад |
| seaweedfs | `storage` | Энэ хост дээрх S3-тай тохирох объект хадгалалт |
| otelcol | `observability` | OpenTelemetry коллектор |
| mailpit | `devmail` | Бүх гарсан шууданг барина, Quire-г туршихад |
| backup | `backup` | Нэг удаагийн үндсэн нөөцлөлт; backup-restore.md үз |
| backup-scheduler, backup-offsite | `backup` | `QUIRE_BACKUP_INTERVAL_HOURS` тутам үндсэн нөөцлөлт, мөн долоо хоног бүрийн баталгаажуулалтын дасгалтай шифрэлсэн хостын гаднах хуулбарууд |
| h5p | `h5p` | Та `QUIRE_H5P_IMAGE`-д өгдөг H5P LTI 1.3 хэрэгслийн дүрс, `QUIRE_H5P_PORT` (8090) дээр; "H5P өгөгч холбох" үз |

`--profile full` нь `backup` болон `h5p`-ээс бусад бүх сонголттой үйлчилгээг эхлүүлнэ. Нэгийг нь `docker compose -f docker/compose.yaml --profile scan up -d` ашиглан эхлүүлнэ. Сонголттой үйлчилгээгүйгээр Quire хэвээр ажиллаж, юу дутагдаж байгааг хэлнэ: сканергүй бол байршуулалтууд шалгагдаагүйгээр хадгалагдаж, администраторт мэдэгдэнэ; Gotenbergгүй бол файлууд урьдчилж харахын оронд татан авалтыг санал болгоно; transcoderгүй бол видео анхны файлаараа тоглогдоно.

Бүх гуравдагч талын дүрс болон түүний лицензийн үүргүүд `docker/third-party-containers.yaml`-д жагсаагдсан.

### H5P өгөгч холбох <!--quire:connecting-an-h5p-provider-->

Quire H5P ажиллагааны эсвэл хажуугийн туслах багцыг шигтгэж эсвэл нийлүүлдэггүй (ADR 0019). Та H5P ашиглаж байвал өөрийн хостлогдсон захиалга өгөх эсвэл өөрийн өөрийн сервер дээрх H5P инстанцыг Quire-ээс тусад нь ажиллуулна уу. Тэр өгөгчийг LTI 1.3 гадаад хэрэгсэл болгон бүртгээд, түүний агуулгыг хэрэгслийн үйл ажиллагаа болгон сургалтуудад нэмнэ үү. Quire LTI Даалгавар ба үнэлгээний үйлчилгээ (AGS)-ээр дамжуулан дүн, үйл ажиллагаа/үнэлгээний дэвшил солилцдог. Хэрэв өгөгч мөн xAPI мэдэгдэл илгээвэл үүнийг Quire-н xAPI мэдэгдлийн агуулгад тусад нь тохируулна уу; AGS дүн/дэвшил солилцоо нь xAPI мэдэгдэл илгээдэггүй. Moodle импортууд H5P үйл ажиллагуудыг LTI хэрэгслийн холболт шаардлагатай гэж тайлагдаг. Өгөгч өөрийн H5P ажиллагаа, зохиолт, агуулгын банк, оролдлогын түүхээс хариуцлага хэвээр үүрнэ.

Энэ хост дээр өөрийн өөрийн серверийн инстанцыг ажиллуулахын тулд `QUIRE_H5P_IMAGE`-ийг түүний дүрсэд тогтооод `h5p` профайлыг эхлүүлнэ үү. Compose үүнийг `QUIRE_H5P_PORT` (8090) дээр нийтлээд өгөгдлийг нь `h5p-data` volume-д хадгална; дүрс, түүний дагалдах үүрэг нь таных хэвээр үлдэнэ.

## Тохиргоонууд <!--quire:settings-->

Бүх процесс `docker/.env` уншдаг. Загвар `docker/.env.example` нь тохиргоо бүрийг өгөгдсөн утгатай нь жагсаана. Бүлгүүд:

### Хаягууд <!--quire:addresses-->

| Тохиргоо | Утга |
| --- | --- |
| `QUIRE_APP_ORIGIN` | LMS-ийн нийтлэг хаяг, жишээ нь `https://learn.example.com` |
| `QUIRE_CONTENT_ORIGIN` | Агуулгын origin, өөр хост |
| `QUIRE_PLATFORM_DOMAINS` | Байгууллагууд байрладог домейнүүд, таслагчаар тусгаарласан |
| `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`. `vercel` болон `cloudflare`-ийн тулд бусад гарын авлагуудыг үз |
| `QUIRE_TRUSTED_PROXY_CIDRS` | `X-Forwarded-For`-ийг нь итгэдэг проксиуд |

### Нууцлалууд <!--quire:secrets-->

| Тохиргоо | Утга |
| --- | --- |
| `QUIRE_SECRET_KEY` | Сесси болон token-уудыг гарын үсэглэнэ. 64 шигтгээт тэмдэгт |
| `QUIRE_MASTER_KEY` | SSO болон вебхүүкийн нууц зэрэг хадгалагдсан итгэмжлэлүүдийг орооно. 32 байт, base64. Веб түвшин, worker адил утга шаардана. Эргэлт: [key-rotation.md](/mn/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | Мастер түлхүүрийн хувилбарын шошго, тогтоогдоогүй үед `v1`. Эргэлт хийхдээ өсгөнө |
| `QUIRE_MASTER_KEY_RETIRED` | Өмнөх мастер түлхүүрүүд — тэдний оруулсныг уншихад хэрэгтэй хэвээр байгаа нь, `v1=<base64>` хэлбэрээр. Эргэлт дуусаад шийдвэрлэгдээгүй зүйлгүй болсны дараа арилгана |
| `QUIRE_COLLAB_SIGNING_KEY` | Web болон collab-аар хуваалцагдаж засах token-уудыг гарын үсэглэхэд |
| `QUIRE_BACKUP_SIGNING_KEY` | Сургалтын нөөцлөлтүүдийг гарын үсэглэнэ (сонголттой) |

`QUIRE_MASTER_KEY`-н хуулбарыг энэ хостоос өөр газар хадгалаарай. Үгүйгээр сэргээсэн өгөгдлийн сан хадгалж буй итгэмжлэлүүдээ задалж чадахгүй.

### Өгөгдлийн сан <!--quire:database-->

| Тохиргоо | Утга |
| --- | --- |
| `POSTGRES_PASSWORD` | Супер хэрэглэгч, контейнер болон нөөцлөлтүүд ашиглана |
| `QUIRE_DB_APP_PASSWORD`, `QUIRE_DB_MIGRATOR_PASSWORD`, `QUIRE_DB_REPORT_PASSWORD`, `QUIRE_DB_AUDIT_PASSWORD` | Үүргийн нууц үгүүд, анхны ажиллагаанд тогтоогдсон |
| `DATABASE_URL` | Програмын үүрэг. Тэр хийж буй бүх асуултанд мөр түвшний хамгаалалт хэрэглэгдэнэ |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | Шилжүүлэгчийн үүрэг, `migrate` болон `init`-д |
| `QUIRE_SUPERUSER_URL` | Зөвхөн анхны ажиллагаа ашиглана |
| `QUIRE_REPORT_DATABASE_URL` | Зөвхөн унших тайлангийн үүрэг, тайлан болон тайлангийн үүсгэгчид |
| `QUIRE_AUDIT_DATABASE_URL` | Аудитын үүрэг, аудитын консол болон SIEM экспортод |
| `QUIRE_DATABASE_ID` | Ямар ч UUID, суулгалтын насан туршид тогтмол |

Үүргийн нууц үгүүд зөвхөн өгөгдлийн сангийн volume анх үүсгэгдэхэд хэрэглэгдэнэ. Дараа нь солихын тулд `ALTER ROLE` ашиглаад, дараа нь тохирох URL-ийг шинэчлэнэ үү.

`QUIRE_REPORT_DATABASE_URL` нь `DATABASE_URL`-аар тохируулагдсан физик өгөгдлийн санд ашиглагдана. Бусад ямар ч бүртгэгдсэн физик өгөгдлийн санд веб болон worker орчинд өөрийн `quire_report` холболтын URL-ийг тогтооод, дараа нь хувьсагчийн нэрийг тэр өгөгдлийн сангийн **Тайлангийн орчны хувьсагч** талбарт `env:NAME` хэлбэрээр оруулна уу. Иш нь өөрийн аппликейшн холболттой адил өгөгдлийн санг заах ёстой — боломж бол өөрийн унших реплика. Бүх тайлангийн гадаргуу түрээсчийг өөрийн өгөгдлийн сангийн тайлангийн холболт руу дагадаг: тайлангийн үүсгэгч, хадгалсан тайлан, товлосон хүргэлт, тайлангийн экспорт, шинжилгээ, аудит лог, REST аудит нөөцүүд, мөн туслахын аудит хайлт. Тэдгээрийн аль нь ч өөр өгөгдлийн сангийн тайлангийн URL-ийг хэзээ ч зээлдэггүй. Өгөгдлийн санд тайлангийн холболтгүй бол энгийн тайлангууд тэр өгөгдлийн сангийн өөрийн аппликейшн холболтоор ажиллах бөгөөд шинжилгээ болон бүх аудит уншлага татгалзаж, үүнийг хэлнэ — учир нь аппликейшнийн үүрэг аудитын мөрийг унших чадваргүй.

### Драйверүүд <!--quire:drivers-->

| Тохиргоо | Энэ хувилбар | Тэмдэглэл |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (өгөгдсөн), `s3` эсвэл `azure` | `local` нь файлуудыг `files` volume-д барьна. `s3` нь AWS S3, R2, GCS interoperability болон бусад S3-тай тохирох хадгалалтуудыг, үргэлжлүүлж болох multipart байршуулалттай хамт хамрана |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (өгөгдсөн), `sse`, `centrifugo` эсвэл `durable_objects` | `inprocess` нь нэг веб контейнерт тохирно; хэд хэдэн байвал `centrifugo` эсвэл `sse` ашиглаарай |
| `QUIRE_CACHE_DRIVER` | `memory` (өгөгдсөн), `postgres` эсвэл `valkey` | `memory` нь процесс бүрт; хурдын хязгаарууд контейнрүүдийн дунд баталгаатай байхын тулд `valkey` эсвэл `postgres` ашиглаарай |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (өгөгдсөн) эсвэл `progressive_mp4` | Эсвэл хостлогдсон өгөгч: Cloudflare Stream, Mux эсвэл Bunny, тэдгээрийн түлхүүрээр |
| `QUIRE_IMAGE_DRIVER` | `noop` (өгөгдсөн), `imgproxy` эсвэл `cloudflare` | `noop` нь бүх зургийг анхны хэмжээгээр үйлчилнэ. `imgproxy`-д `images` профайл болон дээрх тохиргоонууд хэрэгтэй; `cloudflare` нь Cloudflare Images ашиглана |
| `QUIRE_MEETING_PROVIDER` | `bbb`, `zoom`, `teams`, `meet`, `jitsi` эсвэл `in_process` | Амьд хичээлүүдийн платформын өгөгдсөн утга. Тогтоогдоогүй үед амьд хичээлүүд тохируулагдаагүй гэдгийг хэлнэ — нэг байгууллага Холболтууд, Амьд хичээл өгөгч дор өөрийн дансаа холболт хүртэл. Байгууллагын өөрийн данс үргэлж энэ утгаас илүү давамгайлна. Өгөгч бүрийн өөрийн тохиргоонууд (`BBB_URL` болон `BBB_SECRET`, `ZOOM_*`, `TEAMS_*`, `GOOGLE_MEET_*`, `JITSI_*` хувьсагчууд) зөвхөн энд нэрлэгдсэн өгөгчийн хувьд уншигдана |
| `QUIRE_MEETING_REGIONS` | `eu`, `uk`, `us`-ийн таслагын жагсаалт | Платформын өгөгдсөн өгөгч уулзалтуудыг хаана боловсруулдаг вэ. Тогтоогдоогүй үед бүсэд бэхэлэгдсэн байгууллагатай харьцуулагдахгүй — өмнөх шигээр. Байгууллагын өөрийн данс өөрийн хуудас дээрээ бүсүүдээ тэмдэглэнэ |

Энэ хувилбарт багтаагүй драйверийн утга веб түвшин эхлэх үед татгалзагдах бөгөөд тохиргоог нэрлэх бөгөөд өгөгдсөнөөр нь дуугүй солигдохгүй.

### Зургууд <!--quire:images-->

Хуудсууд зургийг дөрвөн тогтсон хэмжээгээр `/api/files/{id}/image/{size}`-аар асуудаг — энэ нь файл өөрөөтэй ижил хандалгыг шалгаад, дараа нь зурагийн үйлчилгээ рүү шилжүүлдэг. Бүр байгууллага цагт `QUIRE_IMAGE_SPECS_PER_HOUR` (өгөгдсөнөөр 2000) шинэ зураг, хэмжээний хос асууж болно; тэр цагт аль хэдийн үйлдвэрлэсэн хэмжээнүүд тооцогдохгүй. Нэгээс олон веб контейнертэй бол `valkey` эсвэл `postgres`-ийг `QUIRE_CACHE_DRIVER`-д ашиглаарай — ингэснээр хязгаар тэдгээрийн дунд хадгалагдана.

| Тохиргоо | Драйвер | Тэмдэглэл |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | Хөтлөгчүүд imgproxy-д хүрдэг хаяг, жишээ нь `https://images.example.org`. `images` профайл үүнийг `QUIRE_IMAGES_PORT` (8082) дээр нийтлэнэ |
| `IMGPROXY_KEY`, `IMGPROXY_SALT` | `imgproxy` | Шигтгээт мөрүүд, imgproxy эхэлдэгтэй ижил утгууд. Бүрнийг `openssl rand -hex 32`-оор үүсгэнэ үү. Quire бүх зурагийн хаягийг тэдгээрээр гарын үсэглэдэг тул imgproxy Quire хүсээгүй зүйлийг дүрсэлдэггүй |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | `imgproxy` ба local хадгалалт | imgproxy анхны файлуудыг хаанаас татдаг вэ. Compose `http://web:3000` тогтоодог. `s3` эсвэл `azure` хадгалалттай бол imgproxy савнаас татдаг бөгөөд үүнийг ашиглахгүй |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Images засах эрхтэй API token, мөн Images, Developer resources-аас авсан дансны хэш. Дансанд уян хатан хувилбаруудыг нээнэ үү |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | Сонголттой. Тогтоогдсон үед зургууд нууц байх бөгөөд бүх хаяг гарын үсэглэгдэж, хугацаа нь дуусна. Үгүй бол зургууд нийтлэг бөгөөд `QUIRE_SECRET_KEY`-ээс гарган авсан, хэн ч тааж чадахгүй хаягуудтай байдаг |

Cloudflare Images нь үйлчилж буй анхны файл бүрийн өөрийн хуулбарыг хадгалдаг. Файл устгагдахад worker тэр хуулбарыг анхны файлаасаа өмнө устгадаг.

### Ээлж <!--quire:queue-->

Арын ажлууд ижил PostgreSQL өгөгдлийн сан дээр pg-boss ашигладаг тул ажиллуулах ээлжийн үйлчилгээ, тохируулах зүйлгүй. Ажлууд үүнийг үүсгэсэн өөрчлөлттэй ижил гүйлгээнд ээлжлэгддэг тул осол нэгийг нь алдах эсвэл хоёр удаа илгээх чадахгүй. `QUIRE_QUEUE_DRIVER` энд `pgboss` — өгөгдсөн утга нь; `vercel` болон `cloudflare` зөвхөн хөнгөн мэдэгдэл болон вебхүүкийн хүргэлтүүдийг платформын өөрийн ээлж рүү шилжүүлдэг бөгөөд Vercel, Cloudflare гарын авлагууд тэдгээрийг болон тэдний веб түвшин хэрхэн ээлжлдэгийг тайлбарлана.

### Имэйл <!--quire:email-->

Дараагуудаас нэгийг тохируулна уу:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: HTTP өгөгч, түүний итгэмжлэлийг нэрлэсэн JSON объект — жишээ нь `{"provider":"postmark","token":"..."}`. Postmark, Amazon SES, Mailgun, SendGrid, Resend дэмжигдэнэ.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. Зөвхөн энэ зорилт; serverless зорилтууд SMTP-г хаадаг.

`QUIRE_MAIL_FROM` нь илгээгч. Quire-г туршихын тулд `devmail` профайлыг эхлүүлээд, `QUIRE_SMTP_URL=smtp://mailpit:1025` тогтоогоод, имэйлийг `http://localhost:8025` дээр уншина уу.

### Сонголттой үйлчилгээнүүд <!--quire:optional-services-->

| Тохиргоо | Профайлтай |
| --- | --- |
| `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` эсвэл `QUIRE_MEILISEARCH_URL` | Гадаад хайлт; өгөгдсөнөөр Postgres бүтэн текст |
| `QUIRE_BREACH_CHECK_PROVIDER=off`, `QUIRE_BREACH_CHECK_URL` | Нууц үгийн зөрчлийн шалгалт. Өгөгдсөнөөр `api.pwnedpasswords.com`-тэй идэвхтэй (зөвхөн таван тэмдэгтийн хэш урд хэсэг илгээгдэнэ); `off` үүнийг унтраадаг, мөн URL нь та өөрөө ажиллуулдаг диапазоны API-г заана |

### Ажиглалт <!--quire:observability-->

`OTEL_EXPORTER_OTLP_ENDPOINT` нь бүх процесс мөр болон хэмжигдэхүүдээ илгээдэг коллекторыг нэрлэнэ; `observability` профайлын үед `http://otelcol:4318` байх бөгөөд `docker/otel-collector.yaml` нь та өөрийн backend-д зориулсан экспортлогчийг нэмдэг газар юм. Энэ тогтоогдсон үед веб түвшин, worker, scheduler, content, collab процесууд OTLP/HTTP-ээр span-уудыг (веб хүсэлт, түрээсчийн өгөгдлийн сангийн гүйлгээ, worker ажлууд, гарсан дуудлагууд) экспортолж, ижил endpoint-д хэмжигдэхүүдийг минут тутам илгээнэ (`OTEL_METRICS_EXPORTER=none` тэдгээрийг унтраадаг). `OTEL_TRACES_SAMPLER_ARG` нь хадгалагдсан мөрүүдийн хувийг тогтоодог. Логууд `LOG_LEVEL`-оор стандарт гаралт руу явна, мөн Compose тэдгээрийг эргэлдүүлдэг. Мөрүүд хэзээ ч хувийн өгөгдөл ачдаггүй.

### Бүс нутгийн гарц (ЕХ-ны өгөгдлийн байршил) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` нь багц Европын Холбооны байгууллагуудад үйлчилдэг гэдгийг хэлнэ. Дараа нь ажилч нь ЕХ-д бэхэлэгдсэн байгууллагаар хийгдсэн бүх гарсан хүсэлтийг зөвшөөрөгдсөн жагсаалтад барина (21-compliance.md хэсэг 8.1). Зөвшөөрөгдсөн жагсаалт нь тохируулсан үйлчилгээнүүд бүс нутгийнхаа тулд зарладаг хостууд (хадгалалтын endpoint, имэйлийн өгөгч, хостлогдсон видео өгөгч, байгууллагын өөрийн хадгалалтын зорилтууд, AI өгөгчүүд, имэйлийн данс), идэвхтэй хөнгөлөлттэй ямар ч үйлчилгээний хостууд, мөн та `QUIRE_EGRESS_ALLOW_HOSTS`-д жагсаасан хостууд юм. Бусад ямар ч нийтлэг хост руугийн хүсэлт илгээгдэхээс өмнө татгалзагдаж, татгалз нь байгууллагын аудитын мөр дээр `privacy/egress_refused` байдлаар бичигдэж, Compliance, Өгөгдлийн байршил дор жагсаагдана.

| Тохиргоо | Утгууд | Үр дүн |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | Хост нэрүүдийн таслагын жагсаалт, эсвэл бүх дэд домейний хувьд `*.example.org` | ЕХ-н байгууллага хүрч болох нэмэлт хостууд. Вебхүүк, xAPI, SIEM endpoint-үүд, блогийн тэжээл, Amazon SES хостууд энд багтах ёстой — учир нь тэд байгууллагын өөрийн сонголт бөгөөд ямар ч үйлчилгээ тэдгээрийг зарладаггүй. Loopback, хувийн хаягууд, мөн `web` эсвэл `clamav` шиг нэг үгтэй нэрүүд нь таны өөрийн сүлжээ бөгөөд хэзээ ч шалгагдахгүй |

Их Британи, Америкийн байгууллагууд хостын жагсаалтад хүлээгдэхгүй; тэд үйлчилгээний бүс нутгийн шалгалтуудаа хадгална. Жагсаалтыг ажилч дээр тогтооно уу; администраторын хуудас үүнийг веб түвшин дээр уншиж зөвшөөрөгдсөн жагсаалтыг харуулдаг тул үүнийг бүх үйлчилгээ уншдаг `docker/.env`-д тавина уу.

Програмын шалгалт тодорхой алдаа болон аудит бичлэг өгдөг бөгөөд энэ нь баталгаа биш: код буруу байж болно. Баталгаа нь сүлжээ юм. Compose үүнийг таны өмнөөс хэрэгжүүлдэггүй. Бүс нутгийн багцын хувьд `worker` болон `web` үйлчилгээнүүдийг зөвхөн гарцын зам нь гарц прокси (жишээ нь Squid эсвэл tinyproxy контейнер) байх `internal: true` сүлжээнд тавиад — тэр прокси нь `QUIRE_EGRESS_ALLOW_HOSTS`-тэй ижил хостууд, мөн тохируулсан үйлчилгээнүүдийн хостуудыг зөвшөөрөх бөгөөд тэдгээр үйлчилгээнүүдэд `HTTPS_PROXY` тогтооно уу. Тэгээд хоёр жагсаалтыг харьцуулж болно. Байршиллагын хуудас програм зөвшөөрдөг яг тэр хостуудыг жагсаадаг тул тэдгээрийг харьцуулж болно.

## Эрүүл мэнд <!--quire:health-->

| Endpoint | Утга |
| --- | --- |
| `/healthz` | Амьд байдал: процесс хариулна. Compose-ийн эрүүл мэндийн шалгалт үүнийг ашиглана |
| `/readyz` | Бэлэн байдал: хамааралтууд хүртээмжтэй, мөн сонголттой үйлчилгээ бүр тохируулагдсан эсэхээ тайлагдсан. Ачаалал тэнцвэрүүлэгчээ энд чиглүүлнэ үү |

`docker compose -f docker/compose.yaml ps` нь үйлчилгээ бүрийн эрүүл мэндийг харуулна.

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

`proxy` үйлчилгээ (Caddy, Apache-2.0, `docker/caddy/Caddyfile`) нь өгөгдсөн багцын хэсэг юм. Тэр 80, 443 портууд дээр хариулаад замчилдаг:

| Хост эсвэл зам | хаашаа явна вэ |
| --- | --- |
| `QUIRE_PROXY_CONTENT_HOST` | `content` |
| `QUIRE_PROXY_APP_HOST`, бүр түрээсчийн дэд домейн, хувийн домейн | `web` |
| Тэдгээр хостууд дээрх `/_collab/` | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| Тэдгээр хостууд дээрх `/_realtime/connection/` | `centrifugo`-ийн клиент websocket; түүний серверийн API хэзээ ч ил болдоггүй |
| Тэдгээр хостууд дээрх `/_images/` | `imgproxy`, `images` профайлаар (`IMGPROXY_URL`) |

`init-env.sh` нь хоёр origin-ээс `QUIRE_PROXY_APP_HOST`, `QUIRE_PROXY_CONTENT_HOST`, `QUIRE_PROXY_HTTPS_PORT`, `QUIRE_COLLAB_URL`, `IMGPROXY_URL`-ийг гарган авдаг тул тэд салж чадахгүй. Гараар origin өөрчилбөл хамтдаа засна уу.

Гэрчилгээнүүд `QUIRE_PROXY_TLS`-ийг дагана:

- `internal` (өгөгдсөн): Caddy-н өөрийн гэрчилгээний эрх — `localhost`, `*.localhost`, `lvh.me`-н хувьд. Үүнийг үндсэнд нь нэг удаа итгээд, дараа нь хөтлөнө үү:

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

  `quire-local-ca.crt`-ийг систем эсвэл хөтөчийн итгэлийн санд нэмнэ үү. `curl` нь үүнийг `--cacert`-аар авна.
- Имэйл хаяг: бодит нэртэй домейнүүдэд автомат ACME гэрчилгээнүүд (Let's Encrypt, дараа нь ZeroSSL). Хоёр origin, бүр түрээсчийн хостын DNS энд заах ёстой бөгөөд 80, 443 портууд интернетээс хүртээмжтэй байх ёстой.

Түрээсчийн хостууд шаардлагын дагуу, анхны зочлолтоор, мөн зөвхөн web энэ нэр нь энэ суулгалтын хувь гэдгийг баталгаажуулсны дараа (`/tls-allowed`, Compose сүлжээнээс асуугддаг) олгогддог. Юмар ч шаардлагагүй бөгөөд хост руу гадны хүн нэр зааж ч гэрчилгээ хүсэхэд чадахгүй. Гэрчилгээнүүд болон орон нутгийн эрх `caddy-data` volume-д байрлана; `internal` ашиглаж байвал бусадтайгаа хамт нөөцлөнө үү.

Web нь проксиээс л `X-Forwarded-For`-ийг итгэдэг: проксиг тогтсон хаягтай (`QUIRE_PROXY_ADDRESS`, өгөгдсөнөөр `172.29.64.10`) тогтсон дэд сүлжээтэй (`QUIRE_COMPOSE_SUBNET`) байдаг бөгөөд `QUIRE_TRUSTED_PROXY_CIDRS` тэр хаягийг нэрлэнэ. Хэрэв дэд сүлжээ хостын сүлжээтэй зөрвөл хоёуланг нь өөрчлөөд `docker compose down`-ийг `up`-аас өмнө ажиллуулна уу.

## Өөрийн эсрэг проксигийн ард <!--quire:behind-your-own-reverse-proxy-->

Аль хэдийн ажиллуулж буй ачаалал тэнцвэрүүлэгч эсвэл прокси ашиглахын тулд `proxy`-г гаргаж үлдээнэ (`docker compose up -d --scale proxy=0`) мөн `web` (8080), `content` (8081), `collab` (1234, websocket) болон `centrifugo` (8000, websocket)-ийн өмнө TLS-ийг таслана. Нийтлэг хаягуудыг `QUIRE_APP_ORIGIN`, `QUIRE_CONTENT_ORIGIN`, `QUIRE_COLLAB_URL` (`wss://`)-д, мөн таны проксигийн хаягийн хүрээг `QUIRE_TRUSTED_PROXY_CIDRS`-д тогтооно уу.

## Алдаа шийдвэрлэх <!--quire:troubleshooting-->

- `init` "QUIRE_DATABASE_ID is not a UUID" мэдэгдэлтэйгээр гарна: үүнийг `uuidgen`-аар тогтооно уу.
- `web` "did not start on compose" мэдэгдэлтэйгээр дахин ачаалагдана: лог нь чадахгүй байгаа тохиргоо бүрийг болон оронд нь юу ашиглахыг жагсаана.
- Анхны ажиллагааны дараа `.env` дээр үүргийн нууц үг өөрчилсөн нь юу ч хийхгүй: эхлүүлэх скрипт нэг удаа ажиллана. `ALTER ROLE` ашиглаарай.
- `CLAMAV_URL` тогтоогдсон үед байршуулалт сканерын алдаатай амжилтгүй болдог: ClamAV анхны ажиллагаандаа шинжүүдээ татдаг бөгөөд энэ нь хэдэн минут шаарддаг.

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