---
title: "Quire-ის ინსტალაცია Docker Compose-ით"
description: "Quire-ის ინსტალაცია საკუთარ ინფრასტრუქტურაზე Docker Compose-ით."
image: "https://docs.quirelms.com/og.png"
---

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

# Quire-ის ინსტალაცია Docker Compose-ით

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

ეს სრული პროდუქტია ერთ ჰოსტზე: LMS, მისი ფონური სამუშაო, რეალურ დროში
და ერთობლივი რედაქტირების სერვისები და ყველა არჩევითი სერვისი
პროფილის უკან. დიზაინია `docs/architecture/23-ops.md` მე-2 სექცია.

სხვა სამიზნეები: [Vercel](/ka/ops/vercel/) და [Cloudflare Workers](/ka/ops/cloudflare/) აწარმოებენ
მხოლოდ ვებ-დონეს. განახლებებია [upgrade.md](/ka/ops/upgrade/)-ში, ხოლო სარეზერვო ასლები და
აღდგენის წვრთნა [backup-restore.md](/ka/ops/backup-restore/)-ში.

## რა გჭირდებათ <!--quire:what-you-need-->

- Docker Engine 27 ან უფრო ახალი, Compose მოდულით 2.30 ან უფრო ახალი.
- 4 CPU ბირთვი და 8 GB მეხსიერება ნაგულისხმევი სტეკისთვის; 8 ბირთვი და 16 GB
  `--profile full`-ით (მარტო ClamAV იჭერს დაახლოებით 1.5 GB ხელმოწერებს).
- DNS სახელი ვებ-დონისთვის და მეორე უნდობელი კონტენტისთვის. ისინი
  სხვადასხვა ჰოსტები უნდა იყოს: SCORM პაკეტები და ატვირთული HTML მუშაობს კონტენტის
  საწყისზე, რათა მათ ვერასდროს წაიკითხონ LMS-ის ქუქიები.
- ლოკალური ტესტისთვის `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 მონტაჟებს worker-ებში
საიდუმლოდ. მას მხოლოდ `sh`, `awk` და `openssl` სჭირდება და ის უარს ამბობს
არსებული `docker/.env`-ის გადაწერაზე. ორივე ფაილის ასლი ჰოსტიდან გაიტანეთ: `QUIRE_MASTER_KEY`-ის
გარეშე აღდგენილი მონაცემთა ბაზა ვერ გაშიფრავს თავის შენახულ რწმუნებათა სიგელებს.
ფაილის ხელით შესავსებად ამის ნაცვლად `cp docker/.env.example docker/.env`; ფაილი
ამბობს, როგორ გენერირდეს თითოეული საიდუმლო.

ორივე საწყისი `https` უნდა იყოს: კონტენტის სერვისი საწარმოოში უბრალო http-ზე უარს
ამბობს და მათ არ უნდა ჰქონდეთ საერთო რეგისტრირებადი დომენი. `proxy`
სერვისი წყვეტს TLS-ს ორივესთვის (იხ. „TLS“); `init-env.sh` უარყოფს
`http://` საწყისს.

სტეკი იწყება ფიქსირებული თანმიმდევრობით და ყოველი ნაბიჯი იცდის წინას:

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 | ყოველთვის | მონაცემთა ბაზა (PostgreSQL 18 pgvector-ით, აგებული `docker/postgres.Dockerfile`-დან), WAL დაარქივებული პირველი ჩართვიდან |
| migrate, init | ყოველთვის | ერთჯერადი: მიგრაციები, შემდეგ პირველი გაშვება |
| web | ყოველთვის | LMS `QUIRE_HTTP_PORT`-ზე (8080) |
| content | ყოველთვის | უნდობელი კონტენტის საწყისი `QUIRE_CONTENT_PORT`-ზე (8081) |
| worker | ყოველთვის | ფონური სამუშაოები: ელფოსტა, ანგარიშები, ფაილების დამუშავება, ვებჰუკები |
| scheduler | ყოველთვის | განმეორებადი სამუშაოები: არეგისტრირებს 64 გაშვების განრიგს და გადასცემს მათ worker-ს; ერთდროულად ერთი ლიდერი |
| collab | ყოველთვის | ერთობლივი რედაქტირების ვებსოკეტი `QUIRE_COLLAB_HTTP_PORT`-ზე (1234) |
| centrifugo | ყოველთვის | რეალურ დროში გაშლა `QUIRE_REALTIME_PORT`-ზე (8000) |
| proxy | ყოველთვის | Caddy, TLS წინა კარი 80 და 443 პორტებზე (იხ. „TLS“) |
| valkey | `cache` | ქეში და სიჩქარის ლიმიტები |
| clamav | `scan` | ატვირთვების მავნე პროგრამებზე სკანირება |
| gotenberg | `preview` | Office PDF გადახედვებში, სერტიფიკატების რენდერი |
| imgproxy | `images` | ზომაშეცვლილი და გარდაქმნილი სურათები |
| transcoder | `video` | worker იმიჯი მხოლოდ-LGPL ffmpeg-ით, ვიდეოს რენდერებისთვის |
| 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` | H5P LTI 1.3 ინსტრუმენტის იმიჯი, რომელსაც თქვენ აწვდით `QUIRE_H5P_IMAGE`-ში, `QUIRE_H5P_PORT`-ზე (8090); იხ. „H5P პროვაიდერის შეერთება“ |

`--profile full` უშვებს ყველა არჩევით სერვისს `backup`-ისა და `h5p`-ის გარდა.
გაუშვით ერთი `docker compose -f docker/compose.yaml --profile scan up -d`-ით.
არჩევითი სერვისის გარეშე Quire მაინც მუშაობს და ამბობს, რა აკლია: სკანერის გარეშე
ატვირთვები ინახება დაუსკანირებელი და ადმინისტრატორს ეუბნებიან; Gotenberg-ის გარეშე
ფაილები გადახედვის ნაცვლად ჩამოტვირთვას სთავაზობენ; ტრანსკოდერის გარეშე
ვიდეო უკრავს, როგორც ორიგინალი ფაილი.

ყოველი მესამე მხარის იმიჯი და მისი სალიცენზიო ვალდებულებები ჩამოთვლილია
`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` ტომში; იმიჯი და
ვალდებულებები, რომლებიც მას მოჰყვება, თქვენი რჩება.

## პარამეტრები <!--quire:settings-->

ყოველი პროცესი კითხულობს `docker/.env`-ს. შაბლონი, `docker/.env.example`, ჩამოთვლის
თითოეულ პარამეტრს ნაგულისხმევით. ჯგუფები:

### მისამართები <!--quire:addresses-->

| პარამეტრი | მნიშვნელობა |
| --- | --- |
| `QUIRE_APP_ORIGIN` | LMS-ის საჯარო მისამართი, როგორიცაა `https://learn.example.com` |
| `QUIRE_CONTENT_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` | ხელს აწერს სესიებსა და ტოკენებს. 64 თექვსმეტობითი სიმბოლო |
| `QUIRE_MASTER_KEY` | ხვევს შენახულ რწმუნებათა სიგელებს, როგორიცაა SSO და ვებჰუკის საიდუმლოებები. 32 ბაიტი, base64. ვებ-დონესა და worker-ს ერთი და იგივე მნიშვნელობა სჭირდება. როტაცია: [key-rotation.md](/ka/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | მასტერ გასაღების ვერსიის იარლიყი, `v1` დაყენების გარეშე. აწიეთ ის როტაციისას |
| `QUIRE_MASTER_KEY_RETIRED` | ადრინდელი მასტერ გასაღებები, რომლებიც კვლავ საჭიროა იმის წასაკითხად, რაც მათ დალუქეს, როგორც `v1=<base64>`. ამოიღეთ როტაციის დასრულების შემდეგ მოუგვარებლის გარეშე |
| `QUIRE_COLLAB_SIGNING_KEY` | გაზიარებულია ვებისა და collab-ის მიერ რედაქტირების ტოკენების მოსაწერად |
| `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, ფიქსირებული ინსტალაციის სიცოცხლისთვის |

როლების პაროლები გამოიყენება მხოლოდ მაშინ, როცა მონაცემთა ბაზის ტომი პირველად იქმნება.
ერთის მოგვიანებით შესაცვლელად გამოიყენეთ `ALTER ROLE` და შემდეგ განაახლეთ შესაბამისი URL.

`QUIRE_REPORT_DATABASE_URL` გამოიყენება ფიზიკური მონაცემთა ბაზისთვის, კონფიგურირებულს
`DATABASE_URL`-ით. ნებისმიერი სხვა რეგისტრირებული ფიზიკური მონაცემთა ბაზისთვის დააყენეთ მისი საკუთარი
`quire_report` შეერთების URL ვებისა და worker-ის გარემოებში, შემდეგ ჩადეთ
ცვლადის სახელი იმ მონაცემთა ბაზის **ანგარიშის გარემოს ცვლადის** ველში,
როგორც `env:NAME`. მითითება უნდა მიუთითებდეს იმავე მონაცემთა ბაზაზე, რაზეც მისი აპის
შეერთება, იდეალურად მის წაკითხვის რეპლიკაზე. ყოველი ანგარიშის ზედაპირი მიჰყვება
მოიჯარეს საკუთარი მონაცემთა ბაზის ანგარიშის შეერთებამდე: ანგარიშის შემქმნელი და
შენახული ანგარიშები, დაგეგმილი მიწოდებები, ანგარიშის ექსპორტები, ანალიტიკა, აუდიტის
ჟურნალი, REST აუდიტის რესურსები და ასისტენტის აუდიტის ძიება. არცერთი
არასდროს სესხულობს სხვა მონაცემთა ბაზის ანგარიშის URL-ს. როცა მონაცემთა ბაზას ანგარიშის
შეერთება არ აქვს, ჩვეულებრივი ანგარიშები მუშაობს იმ მონაცემთა ბაზის საკუთარ აპლიკაციის
შეერთებაზე, ხოლო ანალიტიკა და ყოველი აუდიტის წაკითხვა უარყოფილია და ამას ამბობს, რადგან
აპლიკაციის როლს აუდიტის კვალის წაკითხვა არ შეუძლია.

### დრაივერები <!--quire:drivers-->

| პარამეტრი | ამ რელიზში | შენიშვნები |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (ნაგულისხმევი), `s3` ან `azure` | `local` ფაილებს `files` ტომში ინახავს. `s3` ფარავს AWS S3-ს, R2-ს, GCS თავსებადობას და სხვა S3-თავსებად საცავებს, განახლებადი მრავალნაწილიანი ატვირთვებით |
| `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` ლოკალური საცავით | საიდანაც imgproxy ორიგინალებს იღებს. Compose აყენებს `http://web:3000`-ს. `s3` ან `azure` საცავთან imgproxy ბაკეტიდან იღებს და ეს არ გამოიყენება |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | API ტოკენი Images-ის რედაქტირების ნებართვით და ანგარიშის ჰეში Images-დან, დეველოპერის რესურსებიდან. ჩართეთ მოქნილი ვარიანტები ანგარიშისთვის |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | არჩევითი. დაყენებისას სურათები პირადია და ყველა მისამართი ხელმოწერილია და იწურება. მის გარეშე სურათები საჯაროა მისამართებზე, წარმოებულს `QUIRE_SECRET_KEY`-დან, რომლის გამოცნობაც არავის შეუძლია |

Cloudflare Images ინახავს საკუთარ ასლს თითოეული ორიგინალისა, რომელსაც ის ემსახურება. როცა
ფაილი იშლება, worker-ი შლის იმ ასლს ორიგინალამდე.

### რიგი <!--quire:queue-->

ფონური სამუშაოები იყენებენ pg-boss-ს იმავე Postgres მონაცემთა ბაზაში, ასე რომ გასაშვები რიგის
სერვისი არ არის და საკონფიგურირებელი არაფერია. სამუშაოები რიგში დგება იმავე
ტრანზაქციაში, რაც ცვლილება, რომელმაც ისინი გამოიწვია, ასე რომ ავარიამ ვერ დაკარგოს ერთი ან
გაგზავნოს ერთი ორჯერ. `QUIRE_QUEUE_DRIVER` აქ `pgboss`-ია, მისი ნაგულისხმევი; `vercel`
და `cloudflare` მხოლოდ მსუბუქ შეტყობინებებისა და ვებჰუკის მიწოდებებს გადააქვს
პლატფორმის საკუთარ რიგში, ხოლო Vercel-ისა და Cloudflare-ის სახელმძღვანელოები აღწერენ მათ
და როგორ დგება მათი ვებ-დონეები რიგში.

### ელფოსტა <!--quire:email-->

დააყენეთ ერთ-ერთი:

- `QUIRE_EMAIL_PROVIDER_CONFIG`: JSON ობიექტი, რომელიც ასახელებს HTTP პროვაიდერს და
  მის რწმუნებათა სიგელებს, როგორიცაა `{"provider":"postmark","token":"..."}`. Postmark,
  Amazon SES, Mailgun, SendGrid და Resend მხარდაჭერილია.
- `QUIRE_SMTP_URL`: `smtp://user:password@host:587`. მხოლოდ ეს სამიზნე; უსერვერო
  სამიზნეები 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` არის ადგილი, სადაც ამატებთ
ექსპორტიორს თქვენი ბექენდისთვის. ვებ-დონე, worker-ი, განრიგი, კონტენტი და collab
პროცესები ექსპორტავენ სპანებს OTLP/HTTP-ზე (ვებმოთხოვნები, მოიჯარის მონაცემთა ბაზის
ტრანზაქციები, worker-ის სამუშაოები და გამავალი ზარები), როცა ის დაყენებულია, ხოლო მეტრიკებს
იმავე ენდპოინთზე ყოველ წუთს (`OTEL_METRICS_EXPORTER=none` თიშავს მათ).
`OTEL_TRACES_SAMPLER_ARG` აყენებს შენახული ტრასების წილს. ჟურნალები სტანდარტულ
გამოტანაში მიდის `LOG_LEVEL`-ზე და Compose ატრიალებს მათ. ტრასებს პერსონალური
მონაცემები არასდროს ახლავს.

### რეგიონული გასვლა (EU მონაცემთა რეზიდენტობა) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` ამბობს, რომ სტეკი ევროკავშირის ორგანიზაციებს ემსახურება.
worker-ი მაშინ ყველა გამავალ მოთხოვნას, გაკეთებულს EU-ზე მიბმული ორგანიზაციისთვის, დასაშვებთა სიაში
აქცევს (21-compliance.md 8.1 სექცია). დასაშვებთა სიაა ჰოსტები, რომლებსაც კონფიგურირებული
სერვისები აცხადებენ რეგიონისთვის (საცავის ენდპოინთი, ელფოსტის პროვაიდერი, მასპინძელი ვიდეოს
პროვაიდერი, ორგანიზაციის საკუთარი საცავის სამიზნეები, AI პროვაიდერები და ელფოსტის ანგარიში), ნებისმიერი სერვისის
ჰოსტები აქტიური შეღავათის ქვეშ და ჰოსტები, რომლებსაც თქვენ ჩამოთვლით
`QUIRE_EGRESS_ALLOW_HOSTS`-ში. მოთხოვნა ნებისმიერ სხვა საჯარო ჰოსტზე უარყოფილია
გაგზავნამდე, უარყოფა ორგანიზაციის აუდიტის კვალში იწერება, როგორც
`privacy/egress_refused`, და ის ჩამოთვლილია შესაბამისობის, მონაცემთა რეზიდენტობის ქვეშ.

| პარამეტრი | მნიშვნელობები | ეფექტი |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | ჰოსტების სახელების მძიმით სია ან `*.example.org` ყველა ქვედომენისთვის | დამატებითი ჰოსტები, რომლებსაც EU ორგანიზაცია შეიძლება აღწევდეს. ვებჰუკის, xAPI-ისა და SIEM ენდპოინთები, ბლოგის არხები და Amazon SES ჰოსტები აქ ეკუთვნის, რადგან ისინი ორგანიზაციის საკუთარი არჩევანია და არცერთი სერვისი მათ არ აცხადებს. უკუმარშრუტი, პირადი მისამართები და ერთ იარლიყიანი სახელები, როგორიცაა `web` ან `clamav`, თქვენი საკუთარი ქსელია და არასდროს მოწმდება |

გაერთიანებული სამეფოსა და აშშ-ის ორგანიზაციები ჰოსტების სიაში არ არიან მოქცეული; ისინი ინარჩუნებენ სერვისის
რეგიონის შემოწმებებს. დააყენეთ სია worker-ზე; ადმინისტრატორის გვერდი მას ვებზე კითხულობს
დასაშვებთა სიის საჩვენებლად, ამიტომ ჩადეთ ის `docker/.env`-ში, რომელსაც ყოველი სერვისი
კითხულობს.

აპლიკაციის შემოწმება იძლევა ნათელ შეცდომასა და აუდიტის ჩანაწერს და ის გარანტია
არ არის: კოდი შეიძლება ცდებოდეს. გარანტია ქსელია. Compose მას თქვენთვის
არ აღასრულებს. რეგიონული სტეკისთვის `worker` და `web` სერვისები დადეთ
`internal: true` ქსელზე, რომლის ერთადერთი გასასვლელი გამავალი
პროქსია (მაგალითად Squid ან tinyproxy კონტეინერი), რომელიც უშვებს იმავე ჰოსტებს,
რაც `QUIRE_EGRESS_ALLOW_HOSTS`, პლუს თქვენი კონფიგურირებული სერვისების ჰოსტები, და
დააყენეთ `HTTPS_PROXY` იმ სერვისებისთვის. რეზიდენტობის გვერდი ჩამოთვლის ზუსტ
ჰოსტებს, რომლებსაც აპლიკაცია უშვებს, ასე რომ ორი სიის შედარება შეიძლება.

## ჯანმრთელობა <!--quire:health-->

| ენდპოინთი | მნიშვნელობა |
| --- | --- |
| `/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`-ში (ვებსოკეტი, `QUIRE_COLLAB_URL`) |
| `/_realtime/connection/` იმ ჰოსტებზე | `centrifugo`-ს კლიენტის ვებსოკეტი; მისი სერვერის API არასდროს ჩანს |
| `/_images/` იმ ჰოსტებზე | `imgproxy`-ში, `images` პროფილით (`IMGPROXY_URL`) |

`init-env.sh` იღებს `QUIRE_PROXY_APP_HOST`-ს, `QUIRE_PROXY_CONTENT_HOST`-ს,
`QUIRE_PROXY_HTTPS_PORT`-ს, `QUIRE_COLLAB_URL`-სა და `IMGPROXY_URL`-ს ორი
საწყისიდან, ასე რომ ისინი ვერ დაშორდებიან ერთმანეთს. დაარედაქტირეთ ისინი ერთად, თუ საწყისს
ხელით ცვლით.

სერტიფიკატები მიჰყვება `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) ნამდვილი ჰოსტების სახელებისთვის. ორივე საწყისისა და ყოველი მოიჯარის ჰოსტის
  DNS აქ უნდა მიუთითებდეს, ხოლო 80 და 443 პორტები ინტერნეტიდან მისაწვდომი უნდა
  იყოს.

მოიჯარის ჰოსტები გაიცემა მოთხოვნაზე, პირველი ვიზიტისას, და მხოლოდ მაშინ, როცა ვები
ადასტურებს, რომ სახელი ამ ინსტალაციას ეკუთვნის (`/tls-allowed`, ნასვამი
Compose ქსელზე). ვაილდქარდის სერტიფიკატი ან DNS პროვაიდერის მოდული საჭირო არ არის,
ხოლო უცნობს, რომელიც სახელს ჰოსტზე მიუთითებს, არ შეუძლია სერტიფიკატების მოთხოვნა.
სერტიფიკატები და ლოკალური ავტორიტეტი `caddy-data` ტომში ცხოვრობენ; მისი სარეზერვო ასლი
დანარჩენთან ერთად გააკეთეთ, თუ `internal`-ს იყენებთ.

ვები `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`) და შეწყვიტეთ TLS `web`-ის წინ
(8080), `content`-ის (8081), `collab`-ის (1234, ვებსოკეტი) და `centrifugo`-ს (8000,
ვებსოკეტი) წინ. დააყენეთ საჯარო მისამართები `QUIRE_APP_ORIGIN`-ში,
`QUIRE_CONTENT_ORIGIN`-სა და `QUIRE_COLLAB_URL`-ში (`wss://`), ხოლო თქვენი პროქსის
მისამართების დიაპაზონი `QUIRE_TRUSTED_PROXY_CIDRS`-ში.

## პრობლემების მოგვარება <!--quire:troubleshooting-->

- `init` გამოდის „QUIRE_DATABASE_ID არ არის UUID“-ით: დააყენეთ ის `uuidgen`-ით.
- `web` გადაიტვირთება „compose-ზე არ გაშვებულა“-თი: ჟურნალი ჩამოთვლის თითოეულ პარამეტრს,
  რომლის შესრულებაც მას არ შეუძლია, და სანაცვლოდ რა გამოიყენოს.
- როლის პაროლის შეცვლა `.env`-ში პირველი გაშვების შემდეგ არაფერს აკეთებს: საწყისი
  სკრიპტი ერთხელ მუშაობს. გამოიყენეთ `ALTER ROLE`.
- ატვირთვები ვარდება სკანირების შეცდომით, სანამ `CLAMAV_URL` დაყენებულია: ClamAV ტვირთავს
  თავის ხელმოწერებს პირველ გაშვებაზე, რაც რამდენიმე წუთს იღებს.

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