| `TRUST_PROXY` | `loopback,linklocal,uniquelocal` | أي النظائر يُسمح لها بتعيين عنوان IP الخاص بالعميل عبر `X-Forwarded-For`. القيمة الافتراضية تصدّق النظير الموجود على شبكة خاصة فقط، لذا يُوثق بوكيل عكسي على شبكة Docker أو على شبكة محلية، ولا يُوثق بترويسة مزوّرة من عميل على شبكة عامة. اضبطه على `true` فقط عندما يقف أمامه وكيل تتحكم به على عنوان عام. |
| `AUTH_ENABLED` | `true` | يتطلب تسجيل الدخول. اضبطه على `false` للتشغيل بلا أي حسابات إطلاقًا، وهو ما يمنح كل طلب صلاحيات المسؤول، لذا اقصر ذلك على شبكة موثوقة. |
| `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_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` | (فارغ) | المفتاح الذي تنتقل منه أثناء التدوير، بالصيغة نفسها. اضبط الاثنين خلال التدوير حتى تبقى الصفوف الموجودة قابلة لفك التشفير، ثم احذف هذا. |
شغّل الصورة دون `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`، أو استخدم إلغاء الاشتراك للمسؤول داخل التطبيق، لتعطيلها.
| `MAX_UPLOAD_SIZE_MB` | `0` (غير محدود) | الحد الأقصى لحجم الملف لكل عملية رفع بالميغابايت. اضبطه على 0 لغير محدود. تُشحَن الصورة المنشورة بالقيمة `0`، أما البناء من المصدر فيبدأ بالقيمة 100. |
| `MAX_BATCH_SIZE` | `0` (غير محدود) | الحد الأقصى لعدد الملفات في طلب دفعي واحد. اضبطه على 0 لغير محدود. تُشحَن الصورة المنشورة بالقيمة `0`، أما البناء من المصدر فيبدأ بالقيمة 100. |
| `MAX_SVG_SIZE_MB` | `50` | أكبر ملف SVG مقبول قبل التعقيم، بالميغابايت. تختلف `0` هنا عن الصفوف المجاورة: فهي تزيل حد الحجم السابق للتحليل تمامًا بدل رفعه، لذا اترك هذا المتغيّر مضبوطًا. |
| `MAX_PDF_PAGES` | `0` (غير محدود) | الحد الأقصى لعدد صفحات PDF لتحويل PDF إلى صورة. اضبطه على 0 لغير محدود. |
### التنظيف {#cleanup}
| المتغيّر | الافتراضي | الوصف |
|---|---|---|
| `FILE_MAX_AGE_HOURS` | `72` | مدة الاحتفاظ بنتائج المعالجة غير المحفوظة (عمليات الرفع الخام ومُخرَجات الأدوات) قبل الحذف التلقائي. الملفات التي تحفظها صراحةً في مكتبة الملفات لا تتأثر وتبقى حتى تحذفها. |
| `CLEANUP_INTERVAL_MINUTES` | `60` | عدد مرات تشغيل مهمة التنظيف. |
-`/data` (التطبيق) - نماذج الذكاء الاصطناعي، وبيئة Python الافتراضية، وملفات المستخدم. ثبّتها للحفاظ على الملفات المرفوعة وحزم الذكاء الاصطناعي المثبَّتة عبر عمليات إعادة التشغيل.
-`/tmp/workspace` (التطبيق) - تخزين مؤقت للملفات قيد المعالجة. يمكن أن يكون عابرًا، لكن تثبيته يتجنّب ملء الطبقة القابلة للكتابة في الحاوية.
-`SnapOtter-pgdata` (postgres) - مجلد بيانات PostgreSQL. يحفظ كل البيانات العلائقية (المستخدمون، والإعدادات، وخطوط الأنابيب، والمهام، وسجل التدقيق). انسخه احتياطيًا عبر `pg_dump` أو لقطة وحدة تخزين.
-`SnapOtter-redisdata` (redis) - ملف Redis للإلحاق فقط لطوابير مهام دائمة.