এক হোস্টে এটিই সম্পূর্ণ পণ্য: LMS, এর পটভূমির কাজ, রিয়েলটাইম ও যৌথ সম্পাদনার সেবা, এবং প্রোফাইলের মাধ্যমে চালু করা সব ঐচ্ছিক সেবা। নকশা docs/architecture/23-ops.md-এর section 2-এ।
অন্য লক্ষ্য: Vercel ও Cloudflare Workers শুধু web tier চালায়। Upgrade নির্দেশনা upgrade.md-তে; পরিবর্তনের আগে backup ও restore drill-এর জন্য backup-restore.md কাছে রাখুন।
যা প্রয়োজন
- Docker Engine 27 বা পরের সংস্করণ এবং Compose plugin 2.30 বা পরের সংস্করণ।
- Default stack-এর জন্য 4 CPU core ও 8 GB memory;
--profile full-সহ 8 core ও 16 GB (শুধু ClamAV-এর signature প্রায় 1.5 GB জায়গা নেয়)। - Web tier-এর জন্য একটি DNS name এবং অবিশ্বস্ত content-এর জন্য আরেকটি। আলাদা host হতে হবে: SCORM package ও upload করা HTML content origin-এ চলে, যাতে কখনো LMS-এর cookie পড়তে না পারে।
- Local test-এর জন্য
lvh.meও*.localhost127.0.0.1-এ resolve হয়;docker/.env.exampleএটিই ব্যবহার করে। Stack-এরproxyservice local certificate authority-সহ https-এ দুটিই পরিবেশন করে, তাই অন্য কিছু ইনস্টল করতে হয় না (দেখুন “TLS”)। - Host-এ 80 ও 443 port খালি রাখুন (
QUIRE_PROXY_HTTP_PORTওQUIRE_PROXY_HTTPS_PORTদিয়ে বদলানো যায়)।
প্রথমবার চালানো
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 initdocker/scripts/init-env.sh docker/.env-এ সব secret তৈরি করে এবং docker/.env.example থেকে file লেখে (database password, signing ও master key, content launch key pair); পাশাপাশি audit checkpoint signing key রাখে docker/secrets/audit-signing-key.pem-এ, যা Compose secret হিসেবে worker-এ mount করে। শুধু sh, awk ও openssl দরকার; বিদ্যমান docker/.env overwrite করতে এটি অস্বীকার করে। দুটি file-ই host-এর বাইরে copy করে রাখুন: QUIRE_MASTER_KEY ছাড়া restore করা database তার credential decrypt করতে পারে না। হাতে file পূরণ করতে চাইলে cp docker/.env.example docker/.env চালান; প্রতিটি secret তৈরির নির্দেশ file-এ আছে।
দুটি origin-ই https হতে হবে: production-এ content service plain http প্রত্যাখ্যান করে এবং দুটির registrable domain এক হতে পারবে না। proxy service দুটির TLS termination করে (দেখুন “TLS”); init-env.sh http:// origin প্রত্যাখ্যান করে।
Stack নির্দিষ্ট ক্রমে চলে এবং প্রতিটি ধাপ আগেরটি শেষ হওয়া পর্যন্ত অপেক্ষা করে:
postgreshealthy হয়। প্রথম startup-এ এর init script (docker/postgres/init/90-passwords.sh) চারটি role password সেট করে।migratecontrol database ও প্রতিটি নির্দিষ্ট tenant database-এ সব migration চালায় এবং job queue bootstrap করে; এগুলো মিলছে কি না পরীক্ষা করে, তারপর শেষ হয় (docs/ops/upgrade.md)। প্রতিটি startup-এ migration চলে এবং idempotent, তাই upgrade মানে নতুন image ও restart।init(apps/web/src/first-run.ts) application database-কেQUIRE_DATABASE_ID-এর অধীনে নথিভুক্ত করে এবংQUIRE_SETUP_ADMIN_EMAILসেট করা থাকলে প্রথম organisation ও তার administrator তৈরি করে। Sign-in address ও তৈরি করা password একবারইdocker compose logs init-এ ছাপা হয়।web,content,worker,scheduler,collabওcentrifugoচালু হয়।proxyচালু হয়, যখনwebওcontentসুস্থ হয়।
https://demo.-এর পরে আপনার application domain লিখে খুলুন (সঠিক sign-in address init log-এ ছাপা হয়), তারপর sign in করুন। Local install-এ আগে proxy-র certificate authority-কে trust করুন (দেখুন “TLS”)। তৈরি করা password /account/security-এ বদলান।
প্রয়োজনীয় secret ছাড়া শুরু করা process startup প্রত্যাখ্যান করে এবং log-এ অনুপস্থিত setting-এর নাম জানায়। কোনো কিছু আংশিক configuration নিয়ে চালু হয় না।
সেবা ও profile
| সেবা | Profile | কাজ |
|---|---|---|
| postgres | সবসময় | Database (PostgreSQL 18 ও pgvector, docker/postgres.Dockerfile থেকে তৈরি), প্রথম boot থেকেই WAL archive হয় |
| migrate, init | সবসময় | একবার চলে: migration, তারপর প্রথম setup |
| web | সবসময় | LMS, QUIRE_HTTP_PORT-এ (8080) |
| content | সবসময় | অবিশ্বস্ত content origin, QUIRE_CONTENT_PORT-এ (8081) |
| worker | সবসময় | Background job: email, report, file processing, webhook |
| scheduler | সবসময় | পুনরাবৃত্ত কাজ: 64টি runtime schedule নিবন্ধন করে worker-কে দেয়; একবারে একজন leader |
| collab | সবসময় | যৌথ সম্পাদনার websocket, QUIRE_COLLAB_HTTP_PORT-এ (1234) |
| centrifugo | সবসময় | Realtime fan-out, QUIRE_REALTIME_PORT-এ (8000) |
| proxy | সবসময় | Caddy, 80 ও 443 port-এর TLS front door (দেখুন “TLS”) |
| valkey | cache |
Cache ও rate limit |
| clamav | scan |
Upload-এ malware scan |
| gotenberg | preview |
Office থেকে PDF preview, certificate rendering |
| imgproxy | images |
Image resize ও conversion |
| transcoder | video |
Video rendition-এর জন্য শুধু LGPL-যুক্ত ffmpeg-সহ worker image |
| seaweedfs | storage |
এই host-এ S3-compatible object storage |
| otelcol | observability |
OpenTelemetry collector |
| mailpit | devmail |
Quire পরীক্ষা করার জন্য সব outgoing mail ধরে |
| backup | backup |
একবারের base backup; দেখুন backup-restore.md |
| backup-scheduler, backup-offsite | backup |
প্রতি QUIRE_BACKUP_INTERVAL_HOURS-এ base backup এবং সাপ্তাহিক যাচাই drill-সহ host-এর বাইরে encrypted copy |
| h5p | h5p |
আপনার দেওয়া H5P LTI 1.3 tool image QUIRE_H5P_IMAGE-এ, QUIRE_H5P_PORT-এ (8090); দেখুন “H5P provider যুক্ত করা” |
--profile full backup ও h5p বাদে সব ঐচ্ছিক service চালায়। একটি service চালাতে docker compose -f docker/compose.yaml --profile scan up -d ব্যবহার করুন। ঐচ্ছিক service ছাড়াও Quire চলে এবং কী নেই তা জানায়: scanner না থাকলে upload scan ছাড়াই সংরক্ষিত হয় এবং administrator-কে জানানো হয়; Gotenberg না থাকলে file preview-এর বদলে download করা যায়; transcoder না থাকলে video মূল file হিসেবেই চলে।
প্রতিটি third-party image ও এর license-এর শর্ত docker/third-party-containers.yaml-এ তালিকাভুক্ত।
H5P provider যুক্ত করা
Quire H5P runtime বা sidecar embed বা ship করে না (ADR 0019)। H5P ব্যবহার করলে নিজস্ব hosted subscription নিন অথবা Quire থেকে আলাদা নিজস্ব self-hosted H5P instance পরিচালনা করুন। Provider-কে LTI 1.3 external tool হিসেবে নিবন্ধন করে tool activity হিসেবে course-এ এর content যোগ করুন। Quire LTI Assignment and Grade Services (AGS) দিয়ে grade ও activity/grading progress আদানপ্রদান করে। Provider xAPI statement-ও পাঠালে Quire-এর xAPI statement store-এর জন্য আলাদাভাবে configure করুন; AGS grade/progress বিনিময়ে xAPI statement পাঠানো হয় না। Moodle import-এ H5P activity-র জন্য LTI tool connection প্রয়োজন বলে report হয়। H5P runtime, authoring, content bank ও attempt history-এর দায় provider-এর।
এই host-এ নিজস্ব self-hosted instance চালাতে QUIRE_H5P_IMAGE-এ এর image দিয়ে h5p profile চালু করুন। Compose এটি QUIRE_H5P_PORT-এ (8090) প্রকাশ করে এবং data h5p-data volume-এ রাখে; image ও এর সঙ্গে আসা দায় আপনার।
Setting
প্রতিটি process docker/.env পড়ে। Template docker/.env.example-এ প্রতিটি setting ও default-এর তালিকা আছে। বিভাগগুলো:
ঠিকানা
| Setting | অর্থ |
|---|---|
QUIRE_APP_ORIGIN |
LMS-এর public address, যেমন https://learn.example.com |
QUIRE_CONTENT_ORIGIN |
content origin, অন্য host-এ |
QUIRE_PLATFORM_DOMAINS |
প্রতিষ্ঠানের domain, comma দিয়ে আলাদা |
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-এর জন্য অন্য guide দেখুন |
QUIRE_TRUSTED_PROXY_CIDRS |
যেসব proxy-র X-Forwarded-For বিশ্বাস করা হয় |
Secret
| Setting | অর্থ |
|---|---|
QUIRE_SECRET_KEY |
Session ও token sign করে। 64টি hex character |
QUIRE_MASTER_KEY |
SSO ও webhook secret-এর মতো সংরক্ষিত credential wrap করে। 32 byte, base64। Web tier ও worker-এ একই মান লাগবে। Rotation: key-rotation.md |
QUIRE_MASTER_KEY_VERSION |
Master key-এর version label; unset হলে v1। Rotation করলে এটি বাড়ান |
QUIRE_MASTER_KEY_RETIRED |
আগে seal করা তথ্য পড়তে লাগতে পারে এমন পুরোনো master key, যেমন v1=<base64>। Unresolved কিছু না রেখে rotation শেষ হলে সরান |
QUIRE_COLLAB_SIGNING_KEY |
Editing token sign করতে web ও collab-এর মধ্যে ভাগ করা key |
QUIRE_BACKUP_SIGNING_KEY |
Course backup sign করে (ঐচ্ছিক) |
এই host ছাড়া অন্য কোথাও QUIRE_MASTER_KEY-এর copy রাখুন। এটি ছাড়া restore করা database তার credential decrypt করতে পারে না।
Database
| Setting | অর্থ |
|---|---|
POSTGRES_PASSWORD |
Superuser, container ও backup ব্যবহার করে |
QUIRE_DB_APP_PASSWORD, QUIRE_DB_MIGRATOR_PASSWORD, QUIRE_DB_REPORT_PASSWORD, QUIRE_DB_AUDIT_PASSWORD |
Role password, প্রথম startup-এ সেট হয় |
DATABASE_URL |
Application role। এর প্রতিটি query-তে row-level security প্রযোজ্য |
DATABASE_MIGRATOR_URL, QUIRE_MIGRATION_URL |
migrate ও init-এর migrator role |
QUIRE_SUPERUSER_URL |
শুধু প্রথমবার ব্যবহৃত হয় |
QUIRE_REPORT_DATABASE_URL |
Report ও report builder-এর read-only report role |
QUIRE_AUDIT_DATABASE_URL |
Audit console ও SIEM export-এর audit role |
QUIRE_DATABASE_ID |
যেকোনো UUID, install-এর পুরো সময় একই থাকে |
Database volume প্রথম তৈরি হলেই role password প্রয়োগ হয়। পরে বদলাতে ALTER ROLE ব্যবহার করে সংশ্লিষ্ট URL-ও update করুন।
QUIRE_REPORT_DATABASE_URL DATABASE_URL দিয়ে configure করা physical database-এর জন্য ব্যবহৃত হয়। অন্য কোনো নিবন্ধিত physical database হলে web ও worker environment-এ সেটির নিজস্ব quire_report connection URL দিন, তারপর database-এর Reporting environment variable field-এ variable name env:NAME হিসেবে লিখুন। Reference-টি app connection-এর একই database-এ যেতে হবে, সম্ভব হলে তার read replica-তে। Report surface-গুলো tenant-কে তার নিজস্ব database-এর report connection-এ পাঠায়: report builder ও saved report, scheduled delivery, report export, analytics, audit log, REST audit resource এবং assistant-এর audit search। এগুলোর কোনোটিই অন্য database-এর report URL ধার করে না। Database-এ report connection না থাকলে সাধারণ report সেই database-এর নিজস্ব application connection-এ চলে; analytics ও audit read প্রত্যাখ্যান করে তা জানায়, কারণ application role audit trail পড়তে পারে না।
Driver
| Setting | এই release | বিবরণ |
|---|---|---|
QUIRE_STORAGE_DRIVER |
local (default), s3 অথবা azure |
local file files volume-এ রাখে। s3 AWS S3, R2, GCS interoperability ও অন্যান্য S3-compatible storage সমর্থন করে, resumable multipart upload-সহ |
QUIRE_REALTIME_DRIVER |
inprocess (default), sse, centrifugo অথবা durable_objects |
একটি web container-এ inprocess উপযুক্ত; একাধিক হলে centrifugo অথবা sse ব্যবহার করুন |
QUIRE_CACHE_DRIVER |
memory (default), postgres অথবা valkey |
memory প্রতি process-এর নিজস্ব; container জুড়ে rate limit বজায় রাখতে valkey বা postgres ব্যবহার করুন |
QUIRE_VIDEO_DRIVER |
ffmpeg (default) অথবা progressive_mp4 |
অথবা key-সহ hosted provider: Cloudflare Stream, Mux বা Bunny |
QUIRE_IMAGE_DRIVER |
noop (default), imgproxy অথবা cloudflare |
noop প্রতিটি image মূল আকারে পরিবেশন করে। imgproxy-তে images profile ও নিচের setting লাগে; cloudflare Cloudflare Images ব্যবহার করে |
QUIRE_MEETING_PROVIDER |
bbb, zoom, teams, meet, jitsi অথবা in_process |
Live session-এর platform default provider। Unset থাকলে প্রতিষ্ঠান Integrations, Live session provider-এ নিজস্ব account যুক্ত না করা পর্যন্ত live session configure করা নেই বলে জানায়। প্রতিষ্ঠানের নিজস্ব account সবসময় এই মানের ওপর অগ্রাধিকার পায়। প্রতিটি provider-এর নিজস্ব setting (BBB_URL ও BBB_SECRET, ZOOM_*, TEAMS_*, GOOGLE_MEET_* এবং JITSI_* variable) এখানে নাম দেওয়া provider-এর জন্যই শুধু পড়া হয় |
QUIRE_MEETING_REGIONS |
eu, uk, us-এর comma-separated list |
Platform default provider meeting কোথায় process করে। Unset থাকলে আগের মতো region-এ বাঁধা প্রতিষ্ঠানের বিরুদ্ধে পরীক্ষা হয় না। প্রতিষ্ঠানের নিজস্ব account-এর page-এ তার region জানানো হয় |
এই release-এ নেই এমন driver value পেলে web tier startup প্রত্যাখ্যান করে এবং setting-এর নাম জানায়; default দিয়ে নীরবে বদলে দেয় না।
Image
Page চারটি নির্দিষ্ট আকারে image চায় /api/files/{id}/image/{size} দিয়ে। এটি file-এর মতোই access পরীক্ষা করে তারপর image service-এ redirect করে। প্রতিটি প্রতিষ্ঠান প্রতি ঘণ্টায় QUIRE_IMAGE_SPECS_PER_HOUR (default 2000)টি নতুন image ও size-এর জোড়া চাইতে পারে; ওই ঘণ্টায় আগে তৈরি size গণনায় আসে না। একাধিক web container থাকলে valkey বা postgres ব্যবহার করুন QUIRE_CACHE_DRIVER-এর জন্য, যাতে সীমা সব container-এ কার্যকর হয়।
| Setting | Driver | বিবরণ |
|---|---|---|
IMGPROXY_URL |
imgproxy |
Browser থেকে imgproxy-তে যাওয়ার address, যেমন https://images.example.org। images profile এটিকে QUIRE_IMAGES_PORT-এ (8082) প্রকাশ করে |
IMGPROXY_KEY, IMGPROXY_SALT |
imgproxy |
Hex string; imgproxy চালানোর সময় ব্যবহৃত মানের সঙ্গে একই। প্রতিটি তৈরি করতে openssl rand -hex 32 চালান। Quire প্রতিটি image address এগুলো দিয়ে sign করে, তাই Quire না চাইলে imgproxy কিছু render করে না |
QUIRE_IMAGE_SOURCE_ORIGIN |
local storage-সহ imgproxy |
imgproxy কোথা থেকে original আনে। Compose http://web:3000 সেট করে। s3 বা azure storage হলে imgproxy bucket থেকে আনে, তাই এটি ব্যবহৃত হয় না |
CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_IMAGES_TOKEN, CLOUDFLARE_IMAGES_ACCOUNT_HASH |
cloudflare |
Images edit permission-সহ API token এবং Images, Developer resources থেকে account hash। Account-এ flexible variant চালু করুন |
CLOUDFLARE_IMAGES_SIGNING_KEY |
cloudflare |
ঐচ্ছিক। সেট করা থাকলে image private হয় এবং প্রতিটি address sign করা ও মেয়াদযুক্ত হয়। এটি না থাকলে image public এবং QUIRE_SECRET_KEY থেকে তৈরি অনুমান করা যায় না এমন address-এ থাকে |
Cloudflare Images পরিবেশিত প্রতিটি original-এর নিজস্ব copy রাখে। কোনো file delete হলে worker original-এর আগে ওই copy মুছে দেয়।
Queue
Background job একই Postgres database-এ pg-boss ব্যবহার করে, তাই আলাদা queue service চালাতে হয় না বা configuration লাগে না। যে পরিবর্তনের কারণে job তৈরি হয় তার একই transaction-এ এটি queue-তে যায়, ফলে crash হলে হারায় না বা দুবার পাঠানো হয় না। এখানে QUIRE_QUEUE_DRIVER-এর default pgboss; vercel ও cloudflare শুধু হালকা notification ও webhook delivery-কে platform-এর নিজস্ব queue-তে সরায়। Vercel ও Cloudflare guide-এ এগুলো এবং তাদের web tier কীভাবে enqueue করে তা বলা আছে।
নিচের একটি সেট করুন:
QUIRE_EMAIL_PROVIDER_CONFIG: HTTP provider ও credential উল্লেখ করা JSON object, যেমন{"provider":"postmark","token":"..."}। Postmark, Amazon SES, Mailgun, SendGrid ও Resend সমর্থিত।QUIRE_SMTP_URL:smtp://user:password@host:587। শুধু এই target-এ; serverless target SMTP আটকে দেয়।
প্রেরক QUIRE_MAIL_FROM। Quire পরীক্ষা করতে devmail profile চালু করে QUIRE_SMTP_URL=smtp://mailpit:1025 সেট করুন এবং http://localhost:8025-এ mail পড়ুন।
ঐচ্ছিক service
| Setting | 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 |
External search; নইলে Postgres full text |
QUIRE_BREACH_CHECK_PROVIDER=off, QUIRE_BREACH_CHECK_URL |
Password breach check। Default-এ api.pwnedpasswords.com-এর বিরুদ্ধে চালু (hash-এর শুধু পাঁচ character-এর prefix পাঠানো হয়); off বন্ধ করে, URL আপনার host করা range API-তে নির্দেশ করে |
পর্যবেক্ষণ
OTEL_EXPORTER_OTLP_ENDPOINT collector-এর address দেয়, যেখানে প্রতিটি process trace ও metric পাঠায়; observability profile-এ এটি http://otelcol:4318 এবং আপনার backend-এর exporter যোগ করার জায়গা docker/otel-collector.yaml। সেটি থাকলে web tier, worker, scheduler, content ও collab process OTLP/HTTP দিয়ে span পাঠায় (web request, tenant database transaction, worker job ও outbound call) এবং একই endpoint-এ প্রতি মিনিটে metric পাঠায় (OTEL_METRICS_EXPORTER=none এগুলো বন্ধ করে)। OTEL_TRACES_SAMPLER_ARG কত ভাগ trace রাখা হবে ঠিক করে। LOG_LEVEL-এ log standard output-এ যায়; Compose তা rotate করে। Trace-এ কখনো ব্যক্তিগত তথ্য থাকে না।
আঞ্চলিক egress (EU data residency)
QUIRE_REGION=eu জানায় stack ইউরোপীয় ইউনিয়নের প্রতিষ্ঠান পরিবেশন করে। তখন EU অঞ্চলে বাঁধা প্রতিষ্ঠানের হয়ে worker-এর প্রতিটি outbound request allowlist-এ সীমিত থাকে (21-compliance.md section 8.1)। Configured service-গুলো region-এর জন্য যে host ঘোষণা করে (storage endpoint, email provider, hosted video provider, প্রতিষ্ঠানের নিজস্ব storage target, AI provider ও email account), সক্রিয় derogation-এ থাকা service-এর host এবং আপনার QUIRE_EGRESS_ALLOW_HOSTS-এ দেওয়া host—এগুলোই allowlist। অন্য কোনো public host-এ request পাঠানোর আগেই প্রত্যাখ্যাত হয়; প্রত্যাখ্যান প্রতিষ্ঠানের audit trail-এ privacy/egress_refused হিসেবে লেখা হয় এবং Compliance, Data residency-তে দেখায়।
| Setting | মান | প্রভাব |
|---|---|---|
QUIRE_EGRESS_ALLOW_HOSTS |
comma দিয়ে আলাদা hostname-এর তালিকা, অথবা সব subdomain-এর জন্য *.example.org |
EU প্রতিষ্ঠান যে অতিরিক্ত host-এ পৌঁছাতে পারে। Webhook, xAPI ও SIEM endpoint, blog feed এবং Amazon SES host এখানে রাখুন, কারণ প্রতিষ্ঠানের নিজের পছন্দে সেগুলো আসে এবং কোনো service সেগুলো ঘোষণা করে না। Loopback, private address ও web বা clamav-এর মতো এক label-এর name আপনার নিজের network; এগুলো কখনো পরীক্ষা হয় না |
যুক্তরাজ্য ও যুক্তরাষ্ট্রের প্রতিষ্ঠান host list-এ আবদ্ধ নয়; তাদের ক্ষেত্রে service region পরীক্ষা থাকে। Worker-এ তালিকা সেট করুন; allowlist দেখাতে admin page web tier-এ এটি পড়ে, তাই সব service যে docker/.env পড়ে, সেখানেই রাখুন।
Application check স্পষ্ট error ও audit entry দেয়, কিন্তু এটিই নিশ্চয়তা নয়: code ভুল হতে পারে। নিশ্চয়তা network। Compose নিজে এটি enforce করে না। আঞ্চলিক stack-এর জন্য worker ও web service-কে internal: true network-এ রাখুন; বাইরের একমাত্র পথ হবে এমন egress proxy (যেমন Squid বা tinyproxy container), যা QUIRE_EGRESS_ALLOW_HOSTS-এর একই host এবং configure করা service-এর host অনুমোদন করে। ওই service-গুলোর জন্য HTTPS_PROXY সেট করুন। Residency page-এ application ঠিক কোন host অনুমোদন করে তা দেখা যায়, তাই দুই তালিকা তুলনা করা যায়।
স্বাস্থ্য
| Endpoint | অর্থ |
|---|---|
/healthz |
Liveness: process উত্তর দেয়। Compose health check এটি ব্যবহার করে |
/readyz |
Readiness: dependency পৌঁছানো যায় এবং প্রতিটি ঐচ্ছিক service configure আছে কি না জানানো হয়। Load balancer এখানে নির্দেশ করুন |
docker compose -f docker/compose.yaml ps প্রতিটি service-এর health দেখায়।
TLS
proxy service (Caddy, Apache-2.0, docker/caddy/Caddyfile) default stack-এর অংশ। এটি 80 ও 443 port-এ সাড়া দেয় এবং route করে:
| Host বা path | কোথায় যায় |
|---|---|
QUIRE_PROXY_CONTENT_HOST |
content |
QUIRE_PROXY_APP_HOST, প্রতিটি tenant subdomain ও custom domain |
web |
ওই host-গুলোর /_collab/ |
collab (websocket, QUIRE_COLLAB_URL) |
ওই host-গুলোর /_realtime/connection/ |
centrifugo-র client websocket; এর server API কখনো প্রকাশ করা হয় না |
ওই host-গুলোর /_images/ |
imgproxy, images profile-সহ (IMGPROXY_URL) |
init-env.sh দুটি origin থেকে QUIRE_PROXY_APP_HOST, QUIRE_PROXY_CONTENT_HOST, QUIRE_PROXY_HTTPS_PORT, QUIRE_COLLAB_URL ও IMGPROXY_URL তৈরি করে, তাই মানগুলো পরস্পর থেকে বিচ্যুত হয় না। হাতে origin বদলালে এগুলোও একসঙ্গে সম্পাদনা করুন।
Certificate QUIRE_PROXY_TLS অনুযায়ী চলে:
-
internal(default):localhost,*.localhostওlvh.me-এর জন্য Caddy-র নিজস্ব certificate authority। এর root একবার trust করে তারপর browse করুন:docker compose -f docker/compose.yaml cp \ proxy:/data/caddy/pki/authorities/local/root.crt ./quire-local-ca.crtSystem বা browser-এর trust store-এ
quire-local-ca.crtযোগ করুন।curl-এ এটি--cacertদিয়ে দিন। -
Email address: বাস্তব hostname-এর জন্য স্বয়ংক্রিয় ACME certificate (আগে Let’s Encrypt, পরে ZeroSSL)। দুই origin ও প্রতিটি tenant host-এর DNS-কে এখানে নির্দেশ করতে হবে এবং 80 ও 443 port ইন্টারনেট থেকে পৌঁছানো যায় এমন হতে হবে।
Tenant host-এর certificate প্রথমবার আসলে চাওয়া হয়, এবং web যে নাম এই install-এর বলে নিশ্চিত করলেই শুধু (/tls-allowed, Compose network-এ জিজ্ঞাসা করা হয়)। Wildcard certificate বা DNS provider plugin দরকার নেই; কেউ host-এ নাম নির্দেশ করলেও certificate request করাতে পারবে না। Certificate ও local authority caddy-data volume-এ থাকে; internal ব্যবহার করলে বাকি backup-এর সঙ্গে এটিও backup করুন।
Web শুধু proxy থেকে পাওয়া X-Forwarded-For বিশ্বাস করে: proxy-র স্থির address (QUIRE_PROXY_ADDRESS, default 172.29.64.10) স্থির subnet-এ (QUIRE_COMPOSE_SUBNET) থাকে এবং QUIRE_TRUSTED_PROXY_CIDRS সেই address-টি উল্লেখ করে। Subnet host-এর কোনো network-এর সঙ্গে মিলে গেলে দুটোই বদলে docker compose down চালান, তারপর up করুন।
নিজের reverse proxy-র পেছনে
আগে থেকে চালানো load balancer বা proxy ব্যবহার করতে proxy বাদ দিন (docker compose up -d --scale proxy=0) এবং web (8080), content (8081), collab (1234, websocket) ও centrifugo (8000, websocket)-এর সামনে TLS termination করুন। Public address দিন QUIRE_APP_ORIGIN, QUIRE_CONTENT_ORIGIN ও QUIRE_COLLAB_URL-এ (wss://), আর proxy-র address range দিন QUIRE_TRUSTED_PROXY_CIDRS-এ।
সমস্যা সমাধান
init“QUIRE_DATABASE_ID is not a UUID” দিয়ে শেষ হলেuuidgenদিয়ে এটি সেট করুন।web“did not start on compose” দিয়ে restart হলে log-এ মানতে পারে না এমন প্রতিটি setting ও বিকল্প লেখা থাকে।- প্রথম startup-এর পর
.env-এ role password বদলালে কিছু হয় না: init script একবারই চলে।ALTER ROLEব্যবহার করুন। CLAMAV_URLসেট থাকা অবস্থায় scan error-এ upload ব্যর্থ হলে, প্রথম startup-এ ClamAV signature download করছে; কয়েক মিনিট লাগবে।