---
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/am/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፣ የጀርባ ሥራዎቹ፣ የቅጽበታዊ ግንኙነትና የትብብር አርትዖት አገልግሎቶች፣ እንዲሁም በprofile ስር ያሉ ሁሉም አማራጭ አገልግሎቶች። የአርክቴክቸር ንድፉ በ`docs/architecture/23-ops.md` ክፍል 2 ላይ ተገልጿል።

ሌሎች የማስኬጃ አማራጮች፦ [Vercel](/am/ops/vercel/) እና [Cloudflare Workers](/am/ops/cloudflare/) የweb ክፍሉን ብቻ ያስኬዳሉ። ማሻሻያዎች በ[upgrade.md](/am/ops/upgrade/) ውስጥ ተገልጸዋል፤ ምትኬዎችና የመመለሻ ልምምዱ ደግሞ በ[backup-restore.md](/am/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 የፊርማ ውሂብ ይይዛል)።
- ለweb ክፍሉ አንድ የDNS ስምና ለማይታመን ይዘት ሁለተኛ ስም። የተለያዩ አስተናጋጆች መሆን አለባቸው፤ SCORM ጥቅሎችና የተጫኑ HTML ፋይሎች በይዘት መነሻው ላይ ስለሚሰሩ የLMS ኩኪዎችን ፈጽሞ ማንበብ አይችሉም።
- ለአካባቢያዊ ሙከራ፣ `lvh.me` እና `*.localhost` ወደ 127.0.0.1 ይመለሳሉ፤ `docker/.env.example` የሚጠቀመውም ይህንኑ ነው። የstack-ው `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` ውስጥ የaudit checkpoint ፊርማ ቁልፍን ይፈጥራል፤ Compose ይህን ለworker-ዎች እንደ secret ያገናኘዋል። `sh`፣ `awk` እና `openssl` ብቻ ያስፈልጉታል፤ ነባር `docker/.env`ን ለመተካት ግን እምቢ ይላል። ሁለቱንም ፋይሎች ከዚህ አስተናጋጅ ውጭ ወዳለ ቦታ ይቅዱ፤ `QUIRE_MASTER_KEY` ከሌለ የተመለሰ የውሂብ ጎታ የተቀመጡ ማረጋገጫዎችን መፍታት አይችልም። ፋይሉን በእጅ ለመሙላት፣ `cp docker/.env.example docker/.env` ያስኪዱ፤ እያንዳንዱን ሚስጥር እንዴት ማመንጨት እንደሚቻል በፋይሉ ውስጥ ተጽፏል።

ሁለቱም መነሻ አድራሻዎች `https` መሆን አለባቸው፤ የይዘት አገልግሎቱ በምርት አካባቢ ተራ httpን አይቀበልም፣ እንዲሁም ተመዝጋቢ የሆነ የጎራ ስም በጋራ መጠቀም የለባቸውም። `proxy` አገልግሎቱ ለሁለቱም TLSን ያቋርጣል («TLS»ን ይመልከቱ)፤ `init-env.sh` `http://` የሚጀምር መነሻ አድራሻ አይቀበልም።

stack-ው በተወሰነ ቅደም ተከተል ይነሳል፣ እያንዳንዱም ደረጃ የቀደመው እስኪጠናቀቅ ይጠብቃል፦

1. `postgres` ጤናማ ይሆናል። በመጀመሪያው ጅማሬ ላይ የማስጀመሪያ ስክሪፕቱ (`docker/postgres/init/90-passwords.sh`) የአራቱን role የይለፍ ቃሎች ያዘጋጃል።
2. `migrate` ሁሉንም migration-ዎች ይተገብራል፣ በcontrol database እና በእያንዳንዱ የተለየ tenant database ውስጥ የjob queueን ያስጀምራል፣ ሁሉም እኩል መሆናቸውን ያረጋግጥና ይወጣል (docs/ops/upgrade.md)። migration-ዎች በእያንዳንዱ ጅማሬ ላይ ይሰራሉ፣ ድጋሚ ሲሰሩም ደህና ናቸው፤ ስለዚህ ማሻሻል አዲስ image አምጥቶ እንደገና ማስነሳት ብቻ ነው።
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` ማስታወሻ ውስጥ ታይቷል። በአካባቢያዊ ጭነት ላይ መጀመሪያ የproxy የምስክር ባለሥልጣንን እንደሚታመን ያድርጉ («TLS»ን ይመልከቱ)። የተመነጨውን የይለፍ ቃል በ`/account/security` ይቀይሩ።

የሚያስፈልገው ሚስጥር ሳይኖረው የተነሳ ሂደት መጀመር አይችልም፤ በማስታወሻውም የጎደለውን ቅንብር ስም ያሳያል። በከፊል ብቻ በተዋቀረ ሁኔታ ምንም አይነሳም።

## አገልግሎቶችና profile-ዎች <!--quire:services-and-profiles-->

| አገልግሎት | Profile | የሚሰራው |
| --- | --- | --- |
| postgres | ሁልጊዜ | የውሂብ ጎታ (PostgreSQL 18 ከpgvector ጋር፣ ከ`docker/postgres.Dockerfile` የተገነባ)፤ WAL ከመጀመሪያው ማስነሻ ጀምሮ ይመዘገባል |
| migrate, init | ሁልጊዜ | አንድ ጊዜ የሚሰራ ሥራ፦ መጀመሪያ migration-ዎች፣ ከዚያ የመጀመሪያ ቅንብር |
| web | ሁልጊዜ | LMS፣ በ`QUIRE_HTTP_PORT` (8080) ላይ |
| content | ሁልጊዜ | የማይታመን ይዘት መነሻ፣ በ`QUIRE_CONTENT_PORT` (8081) ላይ |
| worker | ሁልጊዜ | የጀርባ ሥራዎች፦ ኢሜይል፣ ሪፖርቶች፣ ፋይል ማቀናበር፣ webhook-ዎች |
| scheduler | ሁልጊዜ | ተደጋጋሚ ሥራዎች፦ 64 የሩጫ ጊዜ መርሐግብሮችን ይመዘግባልና ለworker ያስተላልፋል፤ በአንድ ጊዜ አንድ መሪ ብቻ |
| collab | ሁልጊዜ | የትብብር አርትዖት websocket፣ በ`QUIRE_COLLAB_HTTP_PORT` (1234) ላይ |
| centrifugo | ሁልጊዜ | የቅጽበታዊ መልዕክት ማሰራጫ፣ በ`QUIRE_REALTIME_PORT` (8000) ላይ |
| proxy | ሁልጊዜ | Caddy፣ በ80 እና 443 ወደቦች ላይ የTLS መግቢያ ( «TLS»ን ይመልከቱ) |
| valkey | `cache` | መሸጎጫና የፍጥነት ገደቦች |
| clamav | `scan` | የተጫኑ ፋይሎችን ማልዌር መፈተሽ |
| gotenberg | `preview` | የOffice ፋይሎችን ወደ PDF ቅድመ እይታ መቀየር፣ የምስክር ማቅረብ |
| imgproxy | `images` | ምስሎችን መጠን መቀየርና መለወጥ |
| transcoder | `video` | ለቪዲዮ ስሪቶች LGPL-only ffmpeg ያለው የworker image |
| 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 tool image፣ በ`QUIRE_H5P_PORT` (8090) ላይ፤ «H5P provider ማገናኘት»ን ይመልከቱ |

`--profile full` `backup` እና `h5p`ን ሳይጨምር ሁሉንም አማራጭ አገልግሎቶች ያስነሳል። አንዱን ለማስነሳት `docker compose -f docker/compose.yaml --profile scan up -d`ን ያስኪዱ። አማራጭ አገልግሎት ባይኖርም Quire ይሰራልና የጎደለውን ያሳያል፤ scanner ከሌለ ፋይሎች ሳይፈተሹ ይቀመጣሉ እና አስተዳዳሪው ይነገረዋል፤ Gotenberg ከሌለ ፋይሎች ከቅድመ እይታ ይልቅ ማውረድ ያቀርባሉ፤ transcoder ከሌለ ቪዲዮ እንደ መጀመሪያው ፋይል ይጫወታል።

የሁሉም የሶስተኛ ወገን image-ዎችና የፈቃድ ግዴታዎቻቸው በ`docker/third-party-containers.yaml` ተዘርዝረዋል።

### H5P provider ማገናኘት <!--quire:connecting-an-h5p-provider-->

Quire H5P runtime ወይም sidecar አያካትትም፣ አያቀርብምም (ADR 0019)። H5P ከተጠቀሙ፣ የራስዎን የተስተናገደ subscription ያቅርቡ ወይም Quireን በተለየ ሁኔታ የራስዎን H5P instance ያስተዳድሩ። provider-ውን እንደ LTI 1.3 external tool ይመዝግቡ፣ ይዘቱንም በtool activity እንደ ኮርስ ያክሉ። Quire በLTI Assignment and Grade Services (AGS) በኩል ውጤቶችንና የእንቅስቃሴ/ውጤት እድገትን ይለዋወጣል። provider-ው የxAPI statement-ዎችንም ከላከ፣ ለQuire የxAPI statement store ያንን በተለየ ሁኔታ ያዋቅሩ፤ የAGS ውጤትና እድገት ልውውጥ xAPI statement-ዎችን አይልክም። Moodle የሚያስገባቸው H5P እንቅስቃሴዎች የLTI tool ግንኙነት እንደሚያስፈልጋቸው ያሳያሉ። የH5P runtime፣ የይዘት ፈጠራ፣ የይዘት ባንክና የሙከራ ታሪክ ኃላፊነት በprovider-ው ላይ ይቀራል።

በዚህ አስተናጋጅ ላይ የራስዎን H5P instance ለማስኬድ፣ `QUIRE_H5P_IMAGE`ን በimage-ው ያዘጋጁና `h5p` profileን ያስነሱ። Compose በ`QUIRE_H5P_PORT` (8090) ላይ ያቀርበዋል፤ ውሂቡንም በ`h5p-data` volume ያስቀምጣል። image-ውም ሆነ ከእሱ ጋር የሚመጡ ግዴታዎች በእርስዎ ኃላፊነት ይቀራሉ።

## ቅንብሮች <!--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` መረጃቸው የሚታመንባቸው proxy-ዎች |

### ሚስጥሮች <!--quire:secrets-->

| ቅንብር | ትርጉም |
| --- | --- |
| `QUIRE_SECRET_KEY` | የsession-ዎችንና token-ዎችን ይፈርማል። 64 hexadecimal ቁምፊዎች |
| `QUIRE_MASTER_KEY` | እንደ SSO እና webhook ሚስጥሮች ያሉ የተቀመጡ ማረጋገጫዎችን ይሸፍናል። 32 byte፣ base64። የweb ክፍሉና worker ተመሳሳይ እሴት ይፈልጋሉ። ለመቀየር፦ [key-rotation.md](/am/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | የዋና ቁልፉ ስሪት መለያ፤ ካልተዘጋጀ `v1` ነው። ቁልፉን ሲቀይሩ ከፍ ያድርጉት |
| `QUIRE_MASTER_KEY_RETIRED` | ቀድሞ የነበሩና የሸፈኑትን ውሂብ ለማንበብ አሁንም የሚያስፈልጉ ዋና ቁልፎች፤ ቅርጹ `v1=<base64>` ነው። ምንም ያልተፈታ ነገር ሳይቀር ቀያይሩን ከጨረሱ በኋላ ያስወግዱት |
| `QUIRE_COLLAB_SIGNING_KEY` | የአርትዖት token-ዎችን ለመፈረም በweb እና collab የሚጋራ |
| `QUIRE_BACKUP_SIGNING_KEY` | የኮርስ ምትኬዎችን ይፈርማል (አማራጭ) |

የ`QUIRE_MASTER_KEY`ን ቅጂ ከዚህ አስተናጋጅ ውጭ ባለ ቦታ ያስቀምጡ። ያለው የውሂብ ጎታ ከተመለሰ በውስጡ ያሉ ማረጋገጫዎችን መፍታት አይቻልም።

### የውሂብ ጎታ <!--quire:database-->

| ቅንብር | ትርጉም |
| --- | --- |
| `POSTGRES_PASSWORD` | ሱፐርዩዘር፤ በcontainer-ውና በምትኬዎች ይጠቀማል |
| `QUIRE_DB_APP_PASSWORD`፣ `QUIRE_DB_MIGRATOR_PASSWORD`፣ `QUIRE_DB_REPORT_PASSWORD`፣ `QUIRE_DB_AUDIT_PASSWORD` | በመጀመሪያ ማስነሻ የሚዘጋጁ የrole የይለፍ ቃሎች |
| `DATABASE_URL` | የመተግበሪያ role። በሚያደርገው እያንዳንዱ query ላይ row-level security ይተገበራል |
| `DATABASE_MIGRATOR_URL`፣ `QUIRE_MIGRATION_URL` | ለ`migrate` እና `init` የሚሆን migrator role |
| `QUIRE_SUPERUSER_URL` | በመጀመሪያ ማስነሻ ብቻ ይጠቀማል |
| `QUIRE_REPORT_DATABASE_URL` | ለሪፖርቶችና ሪፖርት ሰሪ የሚሆን ለማንበብ ብቻ የተፈቀደ report role |
| `QUIRE_AUDIT_DATABASE_URL` | ለaudit console እና SIEM ወደ ውጭ ማውጣት የሚሆን audit role |
| `QUIRE_DATABASE_ID` | ማንኛውም UUID፤ በጭነቱ ዕድሜ ሁሉ አይቀየርም |

የrole የይለፍ ቃሎች የውሂብ ጎታው የvolume ማከማቻ መጀመሪያ ሲፈጠር ብቻ ይተገበራሉ። በኋላ ለመቀየር `ALTER ROLE`ን አስኪዱ፣ ከዚያም ተዛማጁን URL ያዘምኑ።


`QUIRE_REPORT_DATABASE_URL` በ`DATABASE_URL` ለተዋቀረው ቁሳዊ የውሂብ ጎታ ይጠቀማል። ለማንኛውም ሌላ የተመዘገበ ቁሳዊ የውሂብ ጎታ፣ በweb እና worker አካባቢዎች የራሱን `quire_report` ግንኙነት URL ያዘጋጁ፤ ከዚያም በዚያ የውሂብ ጎታ **Reporting environment variable** መስክ ውስጥ የተለዋዋጩን ስም `env:NAME` በሚለው ቅርጽ ያስገቡ። ማጣቀሻው ከመተግበሪያ ግንኙነቱ ጋር ወደ ተመሳሳይ የውሂብ ጎታ፣ በተቻለ መጠንም ወደ read replica መጠቆም አለበት። እያንዳንዱ የሪፖርት በይነገጽ tenant-ውን ተከትሎ የራሱን የውሂብ ጎታ report ግንኙነት ይጠቀማል፦ report builder እና የተቀመጡ ሪፖርቶች፣ በመርሐግብር የሚላኩ ሪፖርቶች፣ የሪፖርት ማውጫዎች፣ analytics፣ audit log፣ REST audit resource-ዎችና የassistant audit ፍለጋ። ከሌላ የውሂብ ጎታ report URL አንዳቸውም አይዋሱም። የውሂብ ጎታው report ግንኙነት ከሌለው መደበኛ ሪፖርቶች የዚያውን የውሂብ ጎታ መተግበሪያ ግንኙነት ይጠቀማሉ፤ የመተግበሪያ role የaudit ታሪክን ማንበብ ስለማይችል ግን analytics እና audit ንባብ እምቢ ይላሉና ምክንያቱን ያሳያሉ።

### ነጂዎች <!--quire:drivers-->

| ቅንብር | በዚህ ስሪት ያሉ እሴቶች | ማስታወሻ |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (ነባሪ)፣ `s3` ወይም `azure` | `local` ፋይሎችን በ`files` volume ያስቀምጣል። `s3` AWS S3፣ R2፣ GCS ተስማሚነትና ሌሎች S3-ተስማሚ ማከማቻዎችን ከresume ሊደረግ ከሚችል multipart upload ጋር ይደግፋል |
| `QUIRE_REALTIME_DRIVER` | `inprocess` (ነባሪ)፣ `sse`፣ `centrifugo` ወይም `durable_objects` | `inprocess` ለአንድ web container ተስማሚ ነው፤ ብዙ ሲኖሩ ግን `centrifugo` ወይም `sse` ይጠቀሙ |
| `QUIRE_CACHE_DRIVER` | `memory` (ነባሪ)፣ `postgres` ወይም `valkey` | `memory` በእያንዳንዱ ሂደት የተለየ ነው፤ የፍጥነት ገደቦች በcontainer-ዎች መካከል እንዲተገበሩ `valkey` ወይም `postgres` ይጠቀሙ |
| `QUIRE_VIDEO_DRIVER` | `ffmpeg` (ነባሪ) ወይም `progressive_mp4` | ወይም በተስተናገደ አቅራቢ፦ Cloudflare Stream፣ Mux ወይም Bunny፣ በቁልፎቻቸው |
| `QUIRE_IMAGE_DRIVER` | `noop` (ነባሪ)፣ `imgproxy` ወይም `cloudflare` | `noop` ሁሉንም ምስሎች በመጀመሪያ መጠናቸው ያቀርባል። `imgproxy` `images` profileንና ከታች ያሉ ቅንብሮችን ይፈልጋል፤ `cloudflare` Cloudflare Imagesን ይጠቀማል |
| `QUIRE_MEETING_PROVIDER` | `bbb`፣ `zoom`፣ `teams`፣ `meet`፣ `jitsi` ወይም `in_process` | ለቀጥታ ጊዜ ክፍለ ጊዜዎች የመድረኩ ነባሪ። ካልተዘጋጀ ድርጅት በIntegrations, Live session provider ስር የራሱን መለያ እስኪያገናኝ ድረስ ቀጥታ ክፍለ ጊዜዎች እንዳልተዋቀሩ ይታያሉ። የድርጅቱ የራሱ መለያ ሁልጊዜ ከዚህ እሴት ቅድሚያ አለው። የእያንዳንዱ አቅራቢ ቅንብሮች (`BBB_URL` እና `BBB_SECRET`፣ `ZOOM_*`፣ `TEAMS_*`፣ `GOOGLE_MEET_*` እና `JITSI_*` ተለዋዋጮች) እዚህ ለተጠቀሰው አቅራቢ ብቻ ይነበባሉ |
| `QUIRE_MEETING_REGIONS` | በኮማ የሚለዩ `eu`፣ `uk`፣ `us` | የመድረኩ ነባሪ አቅራቢ ስብሰባዎችን የሚያቀናብርባቸው ክልሎች። ካልተዘጋጀ፣ ከክልል ጋር ከተያያዘ ድርጅት ጋር አይነጻጸርም (እንደ ቀድሞው)። የድርጅቱ የራሱ መለያ ክልሎቹን በገጹ ላይ ይገልጻል |

ይህ ስሪት የማያካትተው የdriver እሴት ካለ፣ በዝምታ ወደ ነባሪው ከመቀየር ይልቅ web ሲነሳ ይከለክላል፣ የቅንብሩንም ስም ይጠቅሳል።

### ምስሎች <!--quire:images-->

ገጾች ምስሎችን በአራት ቋሚ መጠኖች በ`/api/files/{id}/image/{size}` ይጠይቃሉ፤ ይህም ከፋይሉ ጋር ተመሳሳይ የመዳረሻ መብት ይፈትሻል፣ ከዚያም ወደ ምስል አገልግሎቱ ያዞራል። እያንዳንዱ ድርጅት በሰዓት `QUIRE_IMAGE_SPECS_PER_HOUR` (ነባሪ 2000) አዲስ የምስልና መጠን ጥምረቶችን ሊጠይቅ ይችላል፤ በዚያ ሰዓት አስቀድሞ የተፈጠሩ መጠኖች አይቆጠሩም። ከአንድ በላይ web container ካለ፣ ገደቡ በሁሉም ላይ እንዲተገበር `valkey` ወይም `postgres`ን ለ`QUIRE_CACHE_DRIVER` ይጠቀሙ።

| ቅንብር | Driver | ማስታወሻ |
| --- | --- | --- |
| `IMGPROXY_URL` | `imgproxy` | አሳሾች የሚደርሱበት imgproxy አድራሻ፣ ለምሳሌ `https://images.example.org`። `images` profile በ`QUIRE_IMAGES_PORT` (8082) ላይ ያቀርበዋል |
| `IMGPROXY_KEY`፣ `IMGPROXY_SALT` | `imgproxy` | hexadecimal ሕብረቁምፊዎች፤ imgproxy ሲነሳ ከተሰጡት ጋር አንድ ይሁኑ። እያንዳንዱን በ`openssl rand -hex 32` ያመንጩ። Quire እያንዳንዱን የምስል አድራሻ በእነሱ ይፈርማል፤ ስለዚህ imgproxy Quire ያልጠየቀውን አያቀርብም |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | አካባቢያዊ ማከማቻ ከ`imgproxy` ጋር | imgproxy የመጀመሪያ ምስሎችን የሚያመጣበት አድራሻ። Compose `http://web:3000`ን ያዘጋጃል። የማከማቻ driver `s3` ወይም `azure` ሲሆን imgproxy ከbucket-ው ያመጣል፤ ይህ ቅንብር አይጠቀምም |
| `CLOUDFLARE_ACCOUNT_ID`፣ `CLOUDFLARE_IMAGES_TOKEN`፣ `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Images ላይ edit ፈቃድ ያለው API token እና ከImages, Developer resources የሚገኘው account hash። ለመለያው flexible variantsን ያብሩ |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | አማራጭ። ሲዘጋጅ ምስሎች የግል ይሆናሉ፣ እያንዳንዱም አድራሻ ይፈረማልና ጊዜው ያበቃል። ከሌለ ምስሎች ይፋዊ ናቸው፤ አድራሻቸውም ከ`QUIRE_SECRET_KEY` የሚመነጭ ስለሆነ ማንም መገመት አይችልም |

Cloudflare Images የሚያቀርበውን የመጀመሪያ ፋይል የራሱን ቅጂ ያስቀምጣል። ፋይል ሲሰረዝ፣ worker-ው ከመጀመሪያው በፊት ያንን ቅጂ ይሰርዛል።
### Queue <!--quire:queue-->

የጀርባ ሥራዎች በተመሳሳይ Postgres የውሂብ ጎታ ውስጥ pg-bossን ይጠቀማሉ፤ ስለዚህ የqueue አገልግሎት ማስኬድም ሆነ ማዋቀር አያስፈልግም። ሥራዎች እንዲከናወኑ ያደረገው ለውጥ ከተፈጸመበት transaction ጋር በአንድነት queue ውስጥ ይገባሉ፤ ስለዚህ ብልሽት አንዱን ሊያጠፋ ወይም ሁለት ጊዜ ሊልክ አይችልም። እዚህ `QUIRE_QUEUE_DRIVER` `pgboss` ነው፣ ይህም ነባሪው ነው፤ `vercel` እና `cloudflare` ቀላል የማሳወቂያና webhook ማድረሻዎችን ብቻ ወደ መድረኩ የራሱ queue ያዛውራሉ። የVercel እና Cloudflare መመሪያዎች እነዚህንና የweb ክፍሎቻቸው እንዴት queue እንደሚጠቀሙ ያብራራሉ።

### ኢሜይል <!--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` profileን ያስነሱ፣ `QUIRE_SMTP_URL=smtp://mailpit:1025`ን ያዘጋጁና ኢሜይሉን በ`http://localhost:8025` ያንብቡ።

### አማራጭ አገልግሎቶች <!--quire:optional-services-->

| ቅንብር | ከየትኛው profile ጋር |
| --- | --- |
| `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 full text ይጠቀማል |
| `QUIRE_BREACH_CHECK_PROVIDER=off`፣ `QUIRE_BREACH_CHECK_URL` | የይለፍ ቃል መፍሰስ ምርመራ። በነባሪ በ`api.pwnedpasswords.com` ላይ ነቅቷል (የhash ቅድመ ክፍል አምስት ቁምፊዎች ብቻ ይላካሉ)፤ `off` ያሰናክለዋል፣ URL-ውም ወደ range API ይጠቁማል። |

### ክትትል <!--quire:observability-->

`OTEL_EXPORTER_OTLP_ENDPOINT` እያንዳንዱ ሂደት trace-ዎችንና metric-ዎችን የሚልክበትን ሰብሳቢ ይወስናል፤ `observability` profile ሲነሳ `http://otelcol:4318` ነው፣ ለbackend-ዎ የሚሆነውን exporter ደግሞ በ`docker/otel-collector.yaml` ያክሉ። ቅንብሩ ሲኖር የweb ክፍሉ፣ worker፣ scheduler፣ content እና collab ሂደቶች span-ዎችን በOTLP/HTTP ያወጣሉ (የweb ጥያቄዎች፣ የtenant የውሂብ ጎታ transaction-ዎች፣ የworker ሥራዎችና ወደ ውጭ ጥሪዎች)፤ በየደቂቃውም metric-ዎችን ወደዚያው አድራሻ ይልካሉ (`OTEL_METRICS_EXPORTER=none` ያጠፋቸዋል)። `OTEL_TRACES_SAMPLER_ARG` የሚቀመጡትን trace-ዎች መጠን ይወስናል። log-ዎች በ`LOG_LEVEL` መሠረት ወደ standard output ይወጣሉ፣ Composeም ያዞራቸዋል። Trace-ዎች የግል መረጃ ፈጽሞ አይይዙም።

### የክልል ውጪ ጥሪዎች (የEU ውሂብ መኖሪያ) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` ይህ stack የአውሮፓ ህብረት ድርጅቶችን እንደሚያገለግል ያመለክታል። ከዚያ worker-ው ለEU ክልል የተመደበ ድርጅት የሚያደርገውን እያንዳንዱን ወደ ውጭ ጥያቄ በተፈቀዱ አስተናጋጆች ዝርዝር ውስጥ ይገድባል (21-compliance.md ክፍል 8.1)። ዝርዝሩ በተዋቀሩ አገልግሎቶች ለክልሉ ያስታወቁትን አስተናጋጆች (የማከማቻ መድረሻ፣ የኢሜይል አቅራቢ፣ የተስተናገደ የቪዲዮ አቅራቢ፣ የድርጅቱ የራሱ የማከማቻ መድረሻዎች፣ AI አቅራቢዎችና የኢሜይል መለያ)፣ በንቃት የተፈቀደ ልዩ ሁኔታ ስር ያሉ አገልግሎቶችን፣ እንዲሁም በ`QUIRE_EGRESS_ALLOW_HOSTS` የዘረዘሯቸውን አስተናጋጆች ያካትታል። ወደ ሌላ ይፋዊ አስተናጋጅ የሚደረግ ጥያቄ ከመላኩ በፊት ይከለከላል፤ ውድቅ መደረጉም በድርጅቱ audit trail ላይ `privacy/egress_refused` ተብሎ ይመዘገባል፣ በCompliance, Data residency ስርም ይታያል።

| ቅንብር | እሴቶች | ተጽዕኖ |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | በኮማ የሚለዩ የአስተናጋጅ ስሞች፣ ወይም ሁሉንም subdomain የሚወክል `*.example.org` | የEU ድርጅት ሊደርስባቸው የሚችሉ ተጨማሪ አስተናጋጆች። Webhook፣ xAPI እና SIEM መድረሻዎች፣ blog feed-ዎችና Amazon SES አስተናጋጆች በድርጅቱ ራሱ ስለሚመረጡና ምንም አገልግሎት ስለማያስታውቃቸው እዚህ ይካተታሉ። Loopback፣ የግል አድራሻዎችና እንደ `web` ወይም `clamav` ያሉ አንድ ቃል የያዙ ስሞች የእርስዎ የውስጥ ኔትወርክ ስለሆኑ ፈጽሞ አይመረመሩም |

የUK እና US ድርጅቶች በአስተናጋጅ ዝርዝር አይገደቡም፤ የአገልግሎት ክልል ፍተሻዎች ግን ይቀጥላሉ። ዝርዝሩን በworker ላይ ያዘጋጁ፤ የአስተዳዳሪው ገጽ ዝርዝሩን ለማሳየት በweb ላይ ያነባል፣ ስለዚህ ሁሉም አገልግሎቶች በሚያነቡት `docker/.env` ውስጥ ያስቀምጡት።

የመተግበሪያው ፍተሻ ግልጽ ስህተትና audit መዝገብ ይሰጣል፣ ዋስትናው ግን አይደለም፤ ኮድ ሊሳሳት ይችላል። ዋስትናው የኔትወርክ ገደቡ ነው። Compose ይህን በራሱ አያስፈጽምም። ለክልል ስብስብ `worker` እና `web` አገልግሎቶችን በ`internal: true` ኔትወርክ ላይ ያድርጉ፤ ወደ ውጭ የሚወጣው ብቸኛ መንገድ ተመሳሳይ አስተናጋጆችን የሚፈቅድ egress proxy (ለምሳሌ Squid ወይም tinyproxy container) ይሁን። `QUIRE_EGRESS_ALLOW_HOSTS` ውስጥ ያሉትንና የተዋቀሩ አገልግሎቶች አስተናጋጆችን ይፍቀዱ፣ ለእነዚያም `HTTPS_PROXY`ን ያዘጋጁ። የresidency ገጹ መተግበሪያው በትክክል የሚፈቅዳቸውን አስተናጋጆች ያሳያል፤ ስለዚህ ሁለቱን ዝርዝሮች ማነጻጸር ይችላሉ።

## ጤና <!--quire:health-->

| መድረሻ | ትርጉም |
| --- | --- |
| `/healthz` | ንቃት፦ ሂደቱ ምላሽ ይሰጣል። Compose የጤና ፍተሻዎች ይህን ይጠቀማሉ |
| `/readyz` | ዝግጁነት፦ ጥገኛ አገልግሎቶች ይደረስባቸዋል፣ እያንዳንዱም አማራጭ አገልግሎት ተዋቅሯል ወይም አልተዋቀረም ተብሎ ይዘገባል። load balancer-ዎን እዚህ ያመልክቱ |

`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`፣ እያንዳንዱ tenant subdomain እና custom domain | `web` |
| በእነዚያ አስተናጋጆች ላይ `/_collab/` | `collab` (websocket፣ `QUIRE_COLLAB_URL`) |
| በእነዚያ አስተናጋጆች ላይ `/_realtime/connection/` | `centrifugo` የclient websocket፤ የserver API ፈጽሞ አይጋለጥም |
| በእነዚያ አስተናጋጆች ላይ `/_images/` | `imgproxy`፣ ከ`images` profile ጋር (`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)። የሁለቱም መነሻዎችና የእያንዳንዱ tenant አስተናጋጅ DNS ወደዚህ መጠቆም አለበት፤ ወደቦች 80 እና 443 ከኢንተርኔት መድረስ አለባቸው።

Tenant አስተናጋጆች በመጀመሪያ ጊዜ ሲጎበኙ ብቻ፣ እና web ስሙ የዚህ ጭነት እንደሆነ ሲያረጋግጥ ብቻ (`/tls-allowed`፣ በCompose ኔትወርክ የሚጠየቅ) ምስክር ይሰጣቸዋል። wildcard ምስክር ወይም የDNS provider plugin አያስፈልግም፤ ወደዚህ አስተናጋጅ ስም የሚያመለክት እንግዳ ሰው ምስክር እንዲጠየቅ ማድረግ አይችልም። ምስክሮችና አካባቢያዊ ባለሥልጣኑ በ`caddy-data` volume ውስጥ ይኖራሉ፤ `internal`ን ከተጠቀሙ ከቀሪው ጋር ምትኬ ይውሰዱለት።

Web ከproxy ብቻ የሚመጣውን `X-Forwarded-For` ያምናል፤ proxy-ው ቋሚ አድራሻ (`QUIRE_PROXY_ADDRESS`፣ ነባሪ `172.29.64.10`) በቋሚ subnet (`QUIRE_COMPOSE_SUBNET`) ላይ አለው፣ `QUIRE_TRUSTED_PROXY_CIDRS`ም ያንን አድራሻ ይጠቅሳል። subnet-ው በአስተናጋጁ ላይ ካለ ኔትወርክ ጋር ከተጋጨ፣ ሁለቱንም ይቀይሩና `docker compose down`ን ከ`up` በፊት ያስኪዱ።

## ከራስዎ reverse proxy ጀርባ <!--quire:behind-your-own-reverse-proxy-->

ቀድሞ የሚያስኬዱትን load balancer ወይም proxy ለመጠቀም `proxy`ን ከስብስቡ ያስወግዱ (`docker compose up -d --scale proxy=0`)፤ TLSንም ከ`web` (8080)፣ `content` (8081)፣ `collab` (1234፣ websocket) እና `centrifugo` (8000፣ websocket) ፊት ያቋርጡ። ይፋዊ አድራሻዎችን በ`QUIRE_APP_ORIGIN`፣ `QUIRE_CONTENT_ORIGIN` እና `QUIRE_COLLAB_URL` (`wss://`) ያዘጋጁ፤ የproxy-ዎን አድራሻ ክልልም በ`QUIRE_TRUSTED_PROXY_CIDRS` ያስገቡ።

## መላ መፈለግ <!--quire:troubleshooting-->

- `init` ከ"QUIRE_DATABASE_ID is not a UUID" በሚል ስህተት ከወጣ፦ `uuidgen`ን ተጠቅመው ያዘጋጁት።
- `web` "did not start on compose" በሚል እንደገና ከተነሳ፦ ማስታወሻው ሊያከብራቸው የማይችላቸውን ቅንብሮችና በምትካቸው ምን መጠቀም እንዳለብዎ ይዘረዝራል።
- ከመጀመሪያው ጅማሬ በኋላ በ`.env` ውስጥ የrole የይለፍ ቃል መቀየር ምንም ካልቀየረ፦ የማስጀመሪያ ስክሪፕቱ አንድ ጊዜ ብቻ ይሰራል። `ALTER ROLE`ን ይጠቀሙ።
- `CLAMAV_URL` ተዘጋጅቶ ሳለ ሰቀላዎች በscan ስህተት ከወደቁ፦ ClamAV በመጀመሪያ ማስነሻ የፊርማ ውሂቡን ያወርዳል፤ ይህም ጥቂት ደቂቃዎች ይፈጃል።

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