---
title: "Docker Compose વડે Quire ઇન્સ્ટૉલ કરો"
description: "તમારા પોતાના ઇન્ફ્રાસ્ટ્રક્ચર પર Docker Compose વડે Quire ઇન્સ્ટૉલ કરો."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/gu/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](/gu/ops/vercel/) અને [Cloudflare Workers](/gu/ops/cloudflare/) ફક્ત વેબ સ્તર ચલાવે છે. અપગ્રેડ [upgrade.md](/gu/ops/upgrade/) માં છે અને બૅકઅપ તથા પુનઃસ્થાપન કવાયત [backup-restore.md](/gu/ops/backup-restore/) માં છે.

## તમને શું જોઈએ <!--quire:what-you-need-->

- Compose પ્લગઇન 2.30 અથવા પછીના સંસ્કરણ સાથે Docker Engine 27 અથવા પછીનું.
- ડિફૉલ્ટ સ્ટૅક માટે 4 CPU કોર અને 8 GB મેમરી; `--profile full` માટે 8 કોર અને 16 GB (એકલું ClamAV લગભગ 1.5 GB સહી રાખે છે).
- વેબ સ્તર માટે એક DNS નામ અને અવિશ્વસનીય સામગ્રી માટે બીજું નામ. તે જુદા હોસ્ટ હોવા જોઈએ: SCORM પૅકેજ અને અપલોડ કરેલું HTML સામગ્રીના origin પર ચાલે છે, તેથી તે 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 તેને રહસ્ય તરીકે વર્કરમાં માઉન્ટ કરે છે. તેને ફક્ત `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` સ્વસ્થ થાય છે. પ્રથમ શરૂઆત વખતે તેની init સ્ક્રિપ્ટ (`docker/postgres/init/90-passwords.sh`) ચાર ભૂમિકાના પાસવર્ડ સેટ કરે છે.
2. `migrate` દરેક migration લાગુ કરે છે અને નિયંત્રણ ડેટાબેઝ તથા દરેક સમર્પિત ટૅનન્ટ ડેટાબેઝમાં જૉબ કતાર સ્થાપે છે, તેઓ બધા સહમત છે તે તપાસે છે અને પછી બહાર નીકળે છે (docs/ops/upgrade.md). દરેક શરૂઆત વખતે migrations ચાલે છે અને idempotent છે; તેથી અપગ્રેડ માટે નવી ઇમેજ અને ફરી શરૂઆત પૂરતી છે.
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 | હંમેશાં | એક જ વાર ચાલે: migrations, પછી પ્રથમ રન |
| web | હંમેશાં | LMS, `QUIRE_HTTP_PORT` (8080) પર |
| content | હંમેશાં | અવિશ્વસનીય સામગ્રીનું origin, `QUIRE_CONTENT_PORT` (8081) પર |
| worker | હંમેશાં | પૃષ્ઠભૂમિ જૉબ: ઇમેઇલ, અહેવાલ, ફાઇલ પ્રક્રિયા, webhooks |
| 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 ઇમેજ |
| 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 વાપરો તો તમારું હોસ્ટેડ સબ્સ્ક્રિપ્શન આપો અથવા Quire થી અલગ તમારું સ્વ-હોસ્ટેડ H5P ઇન્સ્ટન્સ ચલાવો. એ પ્રદાતાને LTI 1.3 બાહ્ય ટૂલ તરીકે નોંધો અને તેની સામગ્રી ટૂલ પ્રવૃત્તિ તરીકે અભ્યાસક્રમોમાં ઉમેરો. Quire LTI Assignment and Grade Services (AGS) મારફતે ગ્રેડ અને પ્રવૃત્તિ/ગ્રેડિંગ પ્રગતિની આપ-લે કરે છે. પ્રદાતા xAPI statement પણ મોકલતો હોય, તો Quire ના xAPI statement store માટે તેને અલગથી ગોઠવો; AGS ગ્રેડ/પ્રગતિની આપ-લે xAPI statement મોકલતી નથી. 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` | સામગ્રીનું 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 અને webhook રહસ્ય જેવા સંગ્રહેલા પ્રમાણપત્રને લપેટે છે. 32 બાઇટ, base64. વેબ સ્તર અને worker માં એક જ મૂલ્ય જોઈએ. રોટેશન: [key-rotation.md](/gu/ops/key-rotation/) |
| `QUIRE_MASTER_KEY_VERSION` | માસ્ટર કીનું આવૃત્તિ લેબલ, સેટ ન હોય તો `v1`. રોટેટ કરો ત્યારે વધારો |
| `QUIRE_MASTER_KEY_RETIRED` | સીલ કરેલા ડેટા વાંચવા હજી જરૂરી જૂની માસ્ટર કી, `v1=<base64>` રૂપે. કશું અનિર્ધારિત બાકી ન રહે તે રીતે રોટેશન પૂરી થયા પછી દૂર કરો |
| `QUIRE_COLLAB_SIGNING_KEY` | સંપાદન ટોકન પર સહી કરવા web અને 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` | ઍપ્લિકેશન ભૂમિકા. તે કરે તે દરેક ક્વેરી પર row-level સુરક્ષા લાગુ થાય છે |
| `DATABASE_MIGRATOR_URL`, `QUIRE_MIGRATION_URL` | `migrate` અને `init` માટે migration ભૂમિકા |
| `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` વડે ગોઠવેલા ભૌતિક ડેટાબેઝ માટે વપરાય છે. બીજા કોઈ નોંધાયેલા ભૌતિક ડેટાબેઝ માટે web અને worker પર તેનું પોતાનું `quire_report` જોડાણ URL સેટ કરો, પછી તે ડેટાબેઝના **Reporting environment variable** ક્ષેત્રમાં તેનું ચલ નામ `env:NAME` તરીકે મૂકો. સંદર્ભ ઍપ્લિકેશન જોડાણવાળા એ જ ડેટાબેઝ તરફ હોવો જોઈએ, આદર્શ રીતે તેના વાંચવા-માત્ર પ્રતિકૃતિ તરફ. દરેક અહેવાલ સપાટી ટૅનન્ટને તેના પોતાના ડેટાબેઝના અહેવાલ જોડાણ તરફ દોરી જાય છે: અહેવાલ નિર્માતા અને સાચવેલા અહેવાલ, નિર્ધારિત ડિલિવરી, અહેવાલ નિકાસ, ઍનલિટિક્સ, ઑડિટ લૉગ, REST ઑડિટ સંસાધન અને સહાયકની ઑડિટ શોધ. તેમાંથી કોઈ બીજા ડેટાબેઝનો અહેવાલ URL કદી ઉધાર લેતું નથી. ડેટાબેઝમાં અહેવાલ જોડાણ ન હોય ત્યારે સામાન્ય અહેવાલ તેના પોતાના ઍપ્લિકેશન જોડાણ પર ચાલે છે, પરંતુ ઍનલિટિક્સ અને દરેક ઑડિટ વાંચન નકારે છે અને કારણ કહે છે, કારણ કે ઍપ્લિકેશન ભૂમિકા ઑડિટ ટ્રેલ વાંચી શકતી નથી.

### ડ્રાઇવર <!--quire:drivers-->

| સેટિંગ | આ રિલીઝમાં | નોંધ |
| --- | --- | --- |
| `QUIRE_STORAGE_DRIVER` | `local` (ડિફૉલ્ટ), `s3` અથવા `azure` | `local` ફાઇલો `files` વૉલ્યુમમાં રાખે છે. `s3` AWS S3, R2, GCS આંતરકાર્યક્ષમતા અને અન્ય 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 દરેક ચિત્ર સરનામા પર તેનાથી સહી કરે છે; Quire એ ન માગ્યું હોય તે imgproxy રેન્ડર કરતું નથી |
| `QUIRE_IMAGE_SOURCE_ORIGIN` | સ્થાનિક સંગ્રહ સાથે `imgproxy` | imgproxy મૂળ ચિત્રો અહીંથી મેળવે છે. Compose તેને `http://web:3000` રાખે છે. `s3` અથવા `azure` સંગ્રહ સાથે imgproxy બકેટમાંથી મેળવે છે, તેથી આ વપરાતું નથી |
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_IMAGES_TOKEN`, `CLOUDFLARE_IMAGES_ACCOUNT_HASH` | `cloudflare` | Images સંપાદન પરવાનગી ધરાવતું API ટોકન અને Images, Developer resources માંથી ખાતાનો hash. ખાતા માટે લવચીક variants ચાલુ કરો |
| `CLOUDFLARE_IMAGES_SIGNING_KEY` | `cloudflare` | વૈકલ્પિક. સેટ હોય ત્યારે ચિત્રો ખાનગી હોય છે અને દરેક સરનામે સહી થાય છે તથા તે સમાપ્ત થાય છે. તેના વિના `QUIRE_SECRET_KEY` પરથી બનેલા, કોઈ અનુમાન ન કરી શકે એવા સરનામે ચિત્રો જાહેર હોય છે |

Cloudflare Images આપતા દરેક મૂળ ચિત્રની પોતાની નકલ રાખે છે. ફાઇલ કાઢી નાખવામાં આવે ત્યારે worker મૂળ પહેલાં આ નકલ કાઢે છે.

### કતાર <!--quire:queue-->

પૃષ્ઠભૂમિ જૉબ એ જ Postgres ડેટાબેઝમાં pg-boss વાપરે છે, તેથી કતાર સેવા ચલાવવી કે કંઈ ગોઠવવું પડતું નથી. જૉબને જન્મ આપતા ફેરફાર સાથેના એ જ transaction માં કતારમાં મૂકાય છે, જેથી ક્રૅશ તેને ગુમાવી કે બે વાર મોકલી શકતો નથી. અહીં `QUIRE_QUEUE_DRIVER` ડિફૉલ્ટ `pgboss` છે; `vercel` અને `cloudflare` ફક્ત હલકી સૂચના અને webhook ડિલિવરીને પ્લૅટફૉર્મની પોતાની કતારમાં ખસેડે છે. 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`. ફક્ત આ લક્ષ્ય; સર્વરલેસ લક્ષ્ય 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` સામે ચાલુ છે (ફક્ત પાંચ અક્ષરની hash prefix મોકલાય છે); `off` બંધ કરે છે અને URL તમે હોસ્ટ કરેલી range API તરફ જાય છે |

### અવલોકનક્ષમતા <!--quire:observability-->

દરેક પ્રક્રિયા જેના તરફ trace અને metric મોકલે છે તે કલેક્ટર `OTEL_EXPORTER_OTLP_ENDPOINT` દર્શાવે છે; `observability` પ્રોફાઇલ સાથે તે `http://otelcol:4318` છે, અને તમારા બૅકએન્ડ માટે exporter ઉમેરવાની જગ્યા `docker/otel-collector.yaml` છે. સેટ હોય ત્યારે web tier, worker, scheduler, content અને collab પ્રક્રિયાઓ OTLP/HTTP પર span નિકાસ કરે છે (વેબ વિનંતી, ટૅનન્ટ ડેટાબેઝ transaction, worker જૉબ અને બહારના કૉલ); દર મિનિટે એ જ endpoint પર metric પણ મોકલે છે (`OTEL_METRICS_EXPORTER=none` તેને બંધ કરે છે). `OTEL_TRACES_SAMPLER_ARG` રાખવાના trace નો હિસ્સો સેટ કરે છે. લૉગ `LOG_LEVEL` પર standard output પર જાય છે અને Compose તેને ફેરવે છે. Trace માં કદી વ્યક્તિગત ડેટા હોતો નથી.

### પ્રદેશ બહારનો પ્રવાહ (EU ડેટા નિવાસ) <!--quire:regional-egress-eu-data-residency-->

`QUIRE_REGION=eu` કહે છે કે સ્ટૅક યુરોપિયન યુનિયનની સંસ્થાઓને સેવા આપે છે. EU સાથે બાંધેલી સંસ્થા માટે worker દરેક બહાર જતી વિનંતી allowlist પર રોકે છે (21-compliance.md વિભાગ 8.1). ગોઠવેલી સેવાઓ પ્રદેશ માટે જાહેર કરે તે હોસ્ટ (સંગ્રહ endpoint, ઇમેઇલ પ્રદાતા, હોસ્ટેડ વિડિયો પ્રદાતા, સંસ્થાના પોતાના સંગ્રહ લક્ષ્યો, AI પ્રદાતા અને ઇમેઇલ ખાતું), સક્રિય છૂટ હેઠળની સેવાઓના હોસ્ટ અને તમે `QUIRE_EGRESS_ALLOW_HOSTS` માં આપેલા હોસ્ટ allowlist બને છે. બીજા કોઈ જાહેર હોસ્ટ પરની વિનંતી મોકલાય તે પહેલાં નકારાય છે; ઇનકાર `privacy/egress_refused` તરીકે સંસ્થાના ઑડિટ ટ્રેલમાં લખાય છે અને અનુપાલન, ડેટા નિવાસ હેઠળ દેખાય છે.

| સેટિંગ | મૂલ્યો | અસર |
| --- | --- | --- |
| `QUIRE_EGRESS_ALLOW_HOSTS` | હોસ્ટનામની અલ્પવિરામવાળી યાદી અથવા દરેક સબડોમેન માટે `*.example.org` | EU સંસ્થા પહોંચી શકે તે વધારાના હોસ્ટ. Webhook, xAPI અને SIEM endpoint, બ્લૉગ ફીડ તથા Amazon SES હોસ્ટ અહીં ઉમેરો, કારણ કે તે સંસ્થાની પોતાની પસંદગી છે અને કોઈ સેવા જાહેર કરતી નથી. Loopback, ખાનગી સરનામાં અને `web` અથવા `clamav` જેવા એક જ label વાળા નામો તમારું પોતાનું નેટવર્ક છે; કદી તપાસાતા નથી |

UK અને US સંસ્થાઓ પર હોસ્ટ યાદી લાગુ પડતી નથી; તેમના માટે સેવા પ્રદેશની તપાસ ચાલુ રહે છે. worker પર યાદી સેટ કરો; allowlist બતાવવા admin પૃષ્ઠ વેબ સ્તર પર તે વાંચે છે, તેથી તેને `docker/.env` માં મૂકો, જે દરેક સેવા વાંચે છે.

ઍપ્લિકેશન તપાસ સ્પષ્ટ ભૂલ અને ઑડિટ નોંધ આપે છે, પણ એ ખાતરી નથી: કોડ ખોટો હોઈ શકે. ખાતરી નેટવર્ક આપે છે. Compose તે તમારા માટે લાગુ કરતું નથી. પ્રદેશીય સ્ટૅક માટે `worker` અને `web` સેવાઓને `internal: true` નેટવર્ક પર મૂકો, જેમાં બહાર જવાનો એકમાત્ર રસ્તો egress પ્રૉક્સી હોય (ઉદાહરણ તરીકે Squid અથવા tinyproxy કન્ટેનર); તે `QUIRE_EGRESS_ALLOW_HOSTS` અને ગોઠવેલી સેવાઓના એ જ હોસ્ટને મંજૂરી આપે. આ સેવાઓ માટે `HTTPS_PROXY` સેટ કરો. ઍપ્લિકેશન જે ચોક્કસ હોસ્ટ મંજૂર કરે છે તે નિવાસ પૃષ્ઠ બતાવે છે, તેથી બંને યાદી સરખાવી શકાય છે.

## આરોગ્ય <!--quire:health-->

| Endpoint | અર્થ |
| --- | --- |
| `/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`, દરેક ટૅનન્ટ સબડોમેન અને કસ્ટમ ડોમેન | `web` |
| આ હોસ્ટ પર `/_collab/` | `collab` (websocket, `QUIRE_COLLAB_URL`) |
| આ હોસ્ટ પર `/_realtime/connection/` | `centrifugo` નું client websocket; તેનું server 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` (ડિફૉલ્ટ): `localhost`, `*.localhost` અને `lvh.me` માટે Caddy ની પોતાની પ્રમાણપત્ર સત્તા. તેની root પર એક વાર વિશ્વાસ મૂકો, પછી બ્રાઉઝ કરો:

  ```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 નેટવર્ક પર પૂછાય છે). Wildcard પ્રમાણપત્ર કે DNS provider પ્લગઇન જરૂરી નથી; હોસ્ટ પર નામ નિર્દેશતો અજાણ્યો વ્યક્તિ પ્રમાણપત્રની વિનંતી કરાવી શકતો નથી. પ્રમાણપત્ર અને સ્થાનિક સત્તા `caddy-data` વૉલ્યુમમાં રહે છે; `internal` વાપરો તો બાકીની સાથે તેનો પણ બૅકઅપ લો.

Web ફક્ત પ્રૉક્સી તરફથી આવેલા `X-Forwarded-For` પર વિશ્વાસ કરે છે: પ્રૉક્સીનું નિશ્ચિત સરનામું (`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` છોડી દો (`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` માં ભૂમિકા પાસવર્ડ બદલવાથી કંઈ થતું નથી: init સ્ક્રિપ્ટ એક વાર ચાલે છે. `ALTER ROLE` વાપરો.
- `CLAMAV_URL` સેટ હોય ત્યારે સ્કૅન ભૂલ સાથે અપલોડ નિષ્ફળ થાય: ClamAV પ્રથમ શરૂ થાય ત્યારે પોતાની સહી ડાઉનલોડ કરે છે, જેમાં થોડી મિનિટ લાગે છે.

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