mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
A release-readiness QA pass over the whole product. The commits split into defects a user would hit and gates that were reporting green while measuring nothing. ## Fixes that change behaviour Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so request.ip came from a client-set header and a forged X-Forwarded-For got past the login limiter. The default is now a private-network trust list. A transient Postgres outage stranded in-flight jobs, leaving finished output on disk with no row pointing at it. A reconciler now resolves those rows and adopts the bytes rather than dropping the work. A Redis connection that moved to a new address wedged every read-blocked consumer, so completions stopped signalling while health still answered 200. Socket timeouts plus subscriber pings recover it. Installing more than one AI bundle left the shared venv multi-versioned and silently broke three tools. The installer now reconciles distributions to one version each. Converting an image to JXL at quality 1 through 4 returned a 500, because libjxl 0.7 rejects the distance those values compute. The quality is floored at what the encoder honours. A missing ffmpeg was also reported to the user as a corrupt upload; it now says the engine is unavailable. RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at 0.22.2, and the release scan was split so it can fail on an unfixed critical instead of hiding it behind ignore-unfixed. ## Gates that could not fail Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs build; coverage discarded its whole report on any failing test; the lint gate skipped root tests, scripts, and two workspaces; and several generated matrices counted a host missing ffmpeg as a passing tool. Each now measures what it claims. Full evidence and the outstanding release items are tracked locally and are not part of this branch.
188 lines
15 KiB
Markdown
188 lines
15 KiB
Markdown
---
|
|
description: "جميع متغيّرات بيئة SnapOtter مع قيمها الافتراضية. اضبط المصادقة والتخزين ونماذج الذكاء الاصطناعي والتحليلات وغير ذلك."
|
|
i18n_source_hash: 25970c776f7c
|
|
i18n_provenance: human
|
|
i18n_output_hash: c5d2e7561a15
|
|
i18n_hash_version: 2
|
|
---
|
|
|
|
# الإعداد {#configuration}
|
|
|
|
يتم كل الإعداد عبر متغيّرات البيئة. لكل متغيّر قيمة افتراضية معقولة، لذا يعمل SnapOtter جاهزًا للاستخدام دون ضبط أي منها.
|
|
|
|
## متغيّرات البيئة {#environment-variables}
|
|
|
|
### الخادم {#server}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `PORT` | `1349` | المنفذ الذي يستمع عليه الخادم. |
|
|
| `RATE_LIMIT_PER_MIN` | `1000` | الحد الأقصى للطلبات في الدقيقة لكل IP. اضبطه على 0 لتعطيل تحديد المعدل. |
|
|
| `CORS_ORIGIN` | (فارغ) | المصادر المسموح بها لـ CORS مفصولة بفواصل، أو فارغ للمصدر نفسه فقط. |
|
|
| `LOG_LEVEL` | `info` | مستوى تفصيل السجل. أحد: `fatal` أو `error` أو `warn` أو `info` أو `debug` أو `trace`. |
|
|
| `TRUST_PROXY` | `loopback,linklocal,uniquelocal` | أي النظائر يُسمح لها بتعيين عنوان IP الخاص بالعميل عبر `X-Forwarded-For`. القيمة الافتراضية تصدّق النظير الموجود على شبكة خاصة فقط، لذا يُوثق بوكيل عكسي على شبكة Docker أو على شبكة محلية، ولا يُوثق بترويسة مزوّرة من عميل على شبكة عامة. اضبطه على `true` فقط عندما يقف أمامه وكيل تتحكم به على عنوان عام. |
|
|
|
|
### المصادقة {#authentication}
|
|
|
|
لا يقبل المتغيّران المنطقيان أدناه سوى `true` و`false`. أي قيمة أخرى، مثل `1` أو `yes` أو `on`، تفشل في التحقق ويخرج الخادم قبل أن يبدأ الاستماع.
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `AUTH_ENABLED` | `true` | يتطلب تسجيل الدخول. اضبطه على `false` للتشغيل بلا أي حسابات إطلاقًا، وهو ما يمنح كل طلب صلاحيات المسؤول، لذا اقصر ذلك على شبكة موثوقة. |
|
|
| `DEFAULT_USERNAME` | `admin` | اسم المستخدم لحساب المسؤول الأولي. يُستخدم فقط عند التشغيل الأول. |
|
|
| `DEFAULT_PASSWORD` | `admin` | كلمة المرور لحساب المسؤول الأولي. غيّرها بعد أول تسجيل دخول. |
|
|
| `MAX_USERS` | `0` (غير محدود) | الحد الأقصى لعدد حسابات المستخدمين المسجَّلين. اضبطه على 0 لغير محدود. |
|
|
| `SESSION_DURATION_HOURS` | `168` | مدة حياة جلسة تسجيل الدخول بالساعات (الافتراضي 7 أيام). |
|
|
| `SKIP_MUST_CHANGE_PASSWORD` | `false` | اضبطه على `true` لتخطّي مطالبة تغيير كلمة المرور الإجبارية عند أول تسجيل دخول. |
|
|
|
|
### التخزين {#storage}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `STORAGE_MODE` | `local` | `local` أو `s3`. يحتاج S3 وMinIO إلى ترخيص يتضمن ميزة s3_storage، إضافةً إلى متغيّرات `S3_*` أدناه. |
|
|
| `DATABASE_URL` | `postgres://snapotter:snapotter@localhost:5432/snapotter` | سلسلة اتصال PostgreSQL. توجّهها حزمة Compose إلى خدمة `postgres` الخاصة بها؛ اتركها غير مضبوطة (مع `REDIS_URL`) للحصول على الوضع المدمج. |
|
|
| `REDIS_URL` | `redis://localhost:6379` | سلسلة اتصال Redis (تُستخدم لطوابير مهام BullMQ). توجّهها Compose إلى خدمة `redis` الخاصة بها. |
|
|
| `WORKSPACE_PATH` | `./tmp/workspace` | مجلد الملفات المؤقتة أثناء المعالجة. يُنظَّف تلقائيًا. تضبطه الصورة على `/tmp/workspace`. |
|
|
| `FILES_STORAGE_PATH` | `./data/files` | مجلد ملفات المستخدم الدائمة (الصور المرفوعة، والنتائج المحفوظة). تضبطه الصورة على `/data/files`. |
|
|
|
|
### تخزين كائنات S3 {#s3-object-storage}
|
|
|
|
لا تُقرأ هذه المتغيّرات إلا عندما يكون `STORAGE_MODE=s3`. وإن أغفلت أيًّا من الثلاثة المطلوبة فشل الإقلاع مع ذكر اسم المتغيّر الذي تركته.
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `S3_BUCKET` | (فارغ) | الحاوية (bucket) التي تحتفظ بالملفات المرفوعة والمخرجات. مطلوب. |
|
|
| `S3_ACCESS_KEY_ID` | (فارغ) | مفتاح الوصول. مطلوب. داخل حاوية Docker يمكنك تحميله كملف بدلًا من ذلك عبر `S3_ACCESS_KEY_ID_FILE`. |
|
|
| `S3_SECRET_ACCESS_KEY` | (فارغ) | المفتاح السري. مطلوب. الاصطلاح نفسه للملفات: `S3_SECRET_ACCESS_KEY_FILE`. |
|
|
| `S3_REGION` | `us-east-1` | منطقة الحاوية (bucket). |
|
|
| `S3_ENDPOINT` | (فارغ) | نقطة نهاية مخصّصة لـ MinIO وR2 وBackblaze وغيرها من المخازن المتوافقة مع S3. الفراغ يعني AWS. |
|
|
| `S3_FORCE_PATH_STYLE` | `false` | اضبطه على `true` لـ MinIO وكل ما يتوقع `endpoint/bucket/key` بدل العنونة بالمضيف الافتراضي. |
|
|
| `S3_PREFIX` | (فارغ) | بادئة المفاتيح، لتستوعب حاوية (bucket) واحدة عدة نسخ. |
|
|
|
|
### تشفير البيانات المخزّنة {#encryption-at-rest}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `DATA_ENCRYPTION_KEY` | (فارغ) | 64 خانة ست عشرية (32 بايت). يشفّر الإعدادات الحساسة المخزّنة في قاعدة البيانات. وأي قيمة ليست 64 خانة ست عشرية تُرفض عند الإقلاع. |
|
|
| `DATA_ENCRYPTION_KEY_PREVIOUS` | (فارغ) | المفتاح الذي تنتقل منه أثناء التدوير، بالصيغة نفسها. اضبط الاثنين خلال التدوير حتى تبقى الصفوف الموجودة قابلة لفك التشفير، ثم احذف هذا. |
|
|
|
|
### الوضع المدمج {#embedded-mode}
|
|
|
|
شغّل الصورة دون `DATABASE_URL` ودون `REDIS_URL` فتبدأ PostgreSQL 17 وRedis خاصتين بها داخل الحاوية، مقيَّدتين بالحلقة المحلية، مع كل البيانات على وحدة تخزين `/data`. يستعيد هذا تجربة `docker run` بأمر واحد للبدء السريع والمعمل المنزلي والترقيات من الإصدار 1.x. إنه مسار ملائم، لا نشر إنتاجي: للإنتاج، شغّل حزمة Compose من 3 حاويات مع PostgreSQL وRedis منفصلين. يتطلب الوضع المدمج تشغيل الحاوية بصلاحية الجذر وهو غير متوافق مع أنظمة التشغيل بمعرّف مستخدم اعتباطي (OpenShift، وKubernetes `runAsNonRoot`)؛ استخدم Compose هناك.
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `EMBEDDED` | `auto` | يُفعَّل تلقائيًا عندما يكون كل من `DATABASE_URL` و`REDIS_URL` غير مضبوطين. اضبطه على `0` لتعطيله (عندئذٍ يفشل التطبيق سريعًا إن لم يُضبط `DATABASE_URL`/`REDIS_URL` خارجي، بدل بدء قاعدة بيانات داخل الحاوية بصمت). |
|
|
| `REDIS_MAXMEMORY` | `512mb` | سقف الذاكرة لـ Redis المدمج (الوضع المدمج فقط). اخفضه على المضيفين محدودي الذاكرة مثل Raspberry Pi. |
|
|
|
|
الترقية من الإصدار 1.x: ضع ملف `snapotter.db` القديم في `/data/snapotter.db` داخل وحدة التخزين ويستورده الوضع المدمج إلى PostgreSQL المدمجة عند الإقلاع الأول. يجري الاستيراد مرة واحدة؛ تتخطّاه عمليات الإقلاع اللاحقة.
|
|
|
|
ملاحظة عن القياس عن بُعد: يرث الوضع المدمج الإعداد الافتراضي للتحليلات في الصورة مثل أي إعداد آخر. تُشحَن الصورة المنشورة مع تفعيل التحليلات؛ ابنِ بـ `--build-arg SNAPOTTER_ANALYTICS=off`، أو استخدم إلغاء الاشتراك للمسؤول داخل التطبيق، لتعطيلها.
|
|
|
|
### حدود المعالجة {#processing-limits}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `MAX_UPLOAD_SIZE_MB` | `0` (غير محدود) | الحد الأقصى لحجم الملف لكل عملية رفع بالميغابايت. اضبطه على 0 لغير محدود. تُشحَن الصورة المنشورة بالقيمة `0`، أما البناء من المصدر فيبدأ بالقيمة 100. |
|
|
| `MAX_BATCH_SIZE` | `0` (غير محدود) | الحد الأقصى لعدد الملفات في طلب دفعي واحد. اضبطه على 0 لغير محدود. تُشحَن الصورة المنشورة بالقيمة `0`، أما البناء من المصدر فيبدأ بالقيمة 100. |
|
|
| `CONCURRENT_JOBS` | `0` (تلقائي) | عدد المهام الدفعية التي تعمل بالتوازي. اضبطه على 0 للاكتشاف التلقائي بناءً على أنوية CPU المتاحة. |
|
|
| `MAX_MEGAPIXELS` | `0` (غير محدود) | الحد الأقصى لدقة الصورة المسموح بها بالميغابكسل. اضبطه على 0 لغير محدود. |
|
|
| `MAX_WORKER_THREADS` | `0` (تلقائي) | الحد الأقصى لخيوط العامل لمعالجة الصور. اضبطه على 0 للاكتشاف التلقائي بناءً على أنوية CPU المتاحة. |
|
|
| `PROCESSING_TIMEOUT_S` | `0` (بلا حد) | الحد الأقصى لوقت المعالجة لكل طلب بالثواني. اضبطه على 0 لبلا مهلة. |
|
|
| `MAX_PIPELINE_STEPS` | `20` | الحد الأقصى لعدد الخطوات في خط الأنابيب. اضبطه على 0 لبلا حد. |
|
|
| `MAX_CANVAS_PIXELS` | `0` (بلا حد) | الحد الأقصى لحجم اللوحة بالبكسل لصور الإخراج. اضبطه على 0 لبلا حد. |
|
|
| `MAX_SVG_SIZE_MB` | `50` | أكبر ملف SVG مقبول قبل التعقيم، بالميغابايت. تختلف `0` هنا عن الصفوف المجاورة: فهي تزيل حد الحجم السابق للتحليل تمامًا بدل رفعه، لذا اترك هذا المتغيّر مضبوطًا. |
|
|
| `MAX_PDF_PAGES` | `0` (غير محدود) | الحد الأقصى لعدد صفحات PDF لتحويل PDF إلى صورة. اضبطه على 0 لغير محدود. |
|
|
|
|
### التنظيف {#cleanup}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `FILE_MAX_AGE_HOURS` | `72` | مدة الاحتفاظ بنتائج المعالجة غير المحفوظة (عمليات الرفع الخام ومُخرَجات الأدوات) قبل الحذف التلقائي. الملفات التي تحفظها صراحةً في مكتبة الملفات لا تتأثر وتبقى حتى تحذفها. |
|
|
| `CLEANUP_INTERVAL_MINUTES` | `60` | عدد مرات تشغيل مهمة التنظيف. |
|
|
|
|
### المظهر {#appearance}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `DEFAULT_THEME` | `light` | السمة الافتراضية للجلسات الجديدة. `light` أو `dark` أو `system`. |
|
|
| `DEFAULT_LOCALE` | `en` | لغة الواجهة الافتراضية. |
|
|
| `DEFAULT_TOOL_VIEW` | `sidebar` | تخطيط الأداة الافتراضي. `sidebar` أو `fullscreen`. |
|
|
|
|
### أذونات Docker {#docker-permissions}
|
|
|
|
| المتغيّر | الافتراضي | الوصف |
|
|
|---|---|---|
|
|
| `PUID` | `999` | شغّل عملية الحاوية بهذا المعرّف UID. اضبطه ليطابق مستخدم مضيفك للتثبيتات المرتبطة (`id -u`). |
|
|
| `PGID` | `999` | شغّل عملية الحاوية بهذا المعرّف GID. اضبطه ليطابق مجموعة مضيفك للتثبيتات المرتبطة (`id -g`). |
|
|
|
|
## مثال Docker {#docker-example}
|
|
|
|
```yaml
|
|
services:
|
|
SnapOtter:
|
|
image: snapotter/snapotter:latest
|
|
ports:
|
|
- "1349:1349"
|
|
volumes:
|
|
- SnapOtter-data:/data
|
|
- SnapOtter-workspace:/tmp/workspace
|
|
environment:
|
|
- AUTH_ENABLED=true
|
|
- DEFAULT_USERNAME=admin
|
|
- DEFAULT_PASSWORD=changeme
|
|
- DATABASE_URL=postgres://snapotter:snapotter@postgres:5432/snapotter
|
|
- REDIS_URL=redis://redis:6379
|
|
- MAX_UPLOAD_SIZE_MB=200
|
|
- CONCURRENT_JOBS=4
|
|
- FILE_MAX_AGE_HOURS=12
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
environment:
|
|
POSTGRES_USER: snapotter
|
|
POSTGRES_PASSWORD: snapotter # قم بتغيير هذا لعمليات النشر غير المحلية
|
|
POSTGRES_DB: snapotter
|
|
volumes:
|
|
- SnapOtter-pgdata:/var/lib/postgresql/data
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U snapotter -d snapotter"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 12
|
|
|
|
redis:
|
|
image: redis:8-alpine
|
|
command: ["redis-server", "--maxmemory-policy", "noeviction", "--appendonly", "yes"]
|
|
volumes:
|
|
- SnapOtter-redisdata:/data
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 12
|
|
|
|
volumes:
|
|
SnapOtter-data:
|
|
SnapOtter-workspace:
|
|
SnapOtter-pgdata:
|
|
SnapOtter-redisdata:
|
|
```
|
|
|
|
## وحدات التخزين {#volumes}
|
|
|
|
تستخدم حزمة Docker Compose أربع وحدات تخزين:
|
|
|
|
- `/data` (التطبيق) - نماذج الذكاء الاصطناعي، وبيئة Python الافتراضية، وملفات المستخدم. ثبّتها للحفاظ على الملفات المرفوعة وحزم الذكاء الاصطناعي المثبَّتة عبر عمليات إعادة التشغيل.
|
|
- `/tmp/workspace` (التطبيق) - تخزين مؤقت للملفات قيد المعالجة. يمكن أن يكون عابرًا، لكن تثبيته يتجنّب ملء الطبقة القابلة للكتابة في الحاوية.
|
|
- `SnapOtter-pgdata` (postgres) - مجلد بيانات PostgreSQL. يحفظ كل البيانات العلائقية (المستخدمون، والإعدادات، وخطوط الأنابيب، والمهام، وسجل التدقيق). انسخه احتياطيًا عبر `pg_dump` أو لقطة وحدة تخزين.
|
|
- `SnapOtter-redisdata` (redis) - ملف Redis للإلحاق فقط لطوابير مهام دائمة.
|