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.
सभी SnapOtter एनवायरनमेंट वेरिएबल्स डिफ़ॉल्ट के साथ। auth, स्टोरेज, AI मॉडल, एनालिटिक्स, और अधिक कॉन्फ़िगर करें।
25970c776f7c
human
d47e121c7d0f
2
Configuration
सभी कॉन्फ़िगरेशन एनवायरनमेंट वेरिएबल्स के माध्यम से किया जाता है। हर वेरिएबल का एक उचित डिफ़ॉल्ट होता है, इसलिए SnapOtter उनमें से किसी को सेट किए बिना बॉक्स से बाहर काम करता है।
Environment variables
Server
Variable
Default
Description
PORT
1349
सर्वर जिस पोर्ट पर सुनता है।
RATE_LIMIT_PER_MIN
1000
प्रति IP प्रति मिनट अधिकतम अनुरोध। रेट लिमिटिंग अक्षम करने के लिए 0 पर सेट करें।
CORS_ORIGIN
(empty)
CORS के लिए अल्पविराम-पृथक अनुमत मूल, या केवल-समान-मूल के लिए खाली।
X-Forwarded-For के ज़रिए क्लाइंट IP कौन से पीयर सेट कर सकते हैं। डिफ़ॉल्ट केवल किसी निजी नेटवर्क के पीयर पर भरोसा करता है, इसलिए Docker नेटवर्क या LAN पर मौजूद रिवर्स प्रॉक्सी भरोसेमंद माना जाता है, जबकि किसी सार्वजनिक क्लाइंट का जाली हेडर नहीं। true तभी सेट करें जब आपके नियंत्रण वाला कोई प्रॉक्सी सार्वजनिक पते पर आगे लगा हो।
Authentication
नीचे दिए गए दोनों बूलियन केवल true और false स्वीकार करते हैं। इसके अलावा कुछ और, जैसे 1 या yes या on, सत्यापन में विफल हो जाता है और सर्वर सुनना शुरू करने से पहले ही बाहर निकल जाता है।
Variable
Default
Description
AUTH_ENABLED
true
लॉगिन अनिवार्य करें। बिना किसी अकाउंट के चलाने के लिए false पर सेट करें, जो हर अनुरोध को admin अधिकार देता है, इसलिए इसे किसी भरोसेमंद नेटवर्क तक ही सीमित रखें।
DEFAULT_USERNAME
admin
प्रारंभिक admin अकाउंट के लिए उपयोगकर्ता नाम। केवल पहली बार चलने पर उपयोग किया जाता है।
DEFAULT_PASSWORD
admin
प्रारंभिक admin अकाउंट के लिए पासवर्ड। पहली बार लॉगिन के बाद इसे बदलें।
MAX_USERS
0 (unlimited)
पंजीकृत उपयोगकर्ता अकाउंट की अधिकतम संख्या। असीमित के लिए 0 पर सेट करें।
SESSION_DURATION_HOURS
168
घंटों में लॉगिन सत्र जीवनकाल (डिफ़ॉल्ट 7 दिन है)।
SKIP_MUST_CHANGE_PASSWORD
false
पहली बार लॉगिन पर बाध्य पासवर्ड-परिवर्तन प्रॉम्प्ट को छोड़ने के लिए true पर सेट करें।
Storage
Variable
Default
Description
STORAGE_MODE
local
local या s3। S3 और MinIO के लिए s3_storage फ़ीचर वाले लाइसेंस के साथ नीचे दिए गए S3_* वेरिएबल्स की भी आवश्यकता होती है।
PostgreSQL कनेक्शन स्ट्रिंग। Compose स्टैक इसे अपनी postgres सेवा की ओर इंगित करता है; embedded मोड पाने के लिए इसे (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 object storage
ये केवल तभी पढ़े जाते हैं जब STORAGE_MODE=s3 हो। तीन आवश्यक वेरिएबल्स में से कोई भी छूट जाए तो स्टार्टअप विफल हो जाता है और जो वेरिएबल आपने छोड़ा उसका नाम बताता है।
Variable
Default
Description
S3_BUCKET
(empty)
वह बकेट जो अपलोड और आउटपुट रखता है। आवश्यक।
S3_ACCESS_KEY_ID
(empty)
एक्सेस की। आवश्यक। कंटेनर में आप इसके बजाय इसे S3_ACCESS_KEY_ID_FILE के माध्यम से माउंट कर सकते हैं।
MinIO, R2, Backblaze, और अन्य S3-संगत स्टोर के लिए कस्टम एंडपॉइंट। खाली का अर्थ है AWS।
S3_FORCE_PATH_STYLE
false
MinIO और ऐसी किसी भी अन्य चीज़ के लिए true पर सेट करें जो वर्चुअल-होस्ट एड्रेसिंग के बजाय endpoint/bucket/key चाहती है।
S3_PREFIX
(empty)
की प्रीफ़िक्स, ताकि एक ही बकेट कई इंस्टेंस रख सके।
Encryption at rest
Variable
Default
Description
DATA_ENCRYPTION_KEY
(empty)
64 हेक्स वर्ण (32 बाइट)। डेटाबेस में संग्रहीत संवेदनशील सेटिंग्स को एन्क्रिप्ट करता है। जो कुछ भी 64 हेक्स वर्ण नहीं है उसे स्टार्टअप पर अस्वीकार कर दिया जाता है।
DATA_ENCRYPTION_KEY_PREVIOUS
(empty)
वह की जिससे आप रोटेट होकर दूर जा रहे हैं, वही फ़ॉर्मैट। रोटेशन के दौरान दोनों सेट करें ताकि मौजूदा पंक्तियाँ अब भी डिक्रिप्ट हों, फिर इसे हटा दें।
Embedded mode
इमेज को बिना किसी DATABASE_URL और बिना किसी REDIS_URL के चलाएँ और यह कंटेनर के अंदर अपना स्वयं का PostgreSQL 17 और Redis शुरू करता है, जो लूपबैक से बंधा हुआ है, सारा डेटा /data वॉल्यूम पर। यह त्वरित शुरुआत, होमलैब, और 1.x से अपग्रेड के लिए एकल-कमांड docker run अनुभव को बहाल करता है। यह एक सुविधा पथ है, न कि एक प्रोडक्शन परिनियोजन: प्रोडक्शन के लिए, अलग PostgreSQL और Redis के साथ 3-कंटेनर Compose स्टैक चलाएँ। Embedded मोड को कंटेनर को रूट के रूप में चलाने की आवश्यकता होती है और यह मनमाने-UID रनटाइम (OpenShift, Kubernetes runAsNonRoot) के साथ असंगत है; वहाँ Compose का उपयोग करें।
Variable
Default
Description
EMBEDDED
auto
तब स्वतः-सक्षम होता है जब DATABASE_URL और REDIS_URL दोनों अनसेट हों। इसे अक्षम करने के लिए 0 पर सेट करें (तब ऐप तेज़ी से विफल हो जाता है यदि कोई बाहरी DATABASE_URL/REDIS_URL सेट नहीं है, बजाय चुपचाप एक इन-कंटेनर डेटाबेस शुरू करने के)।
REDIS_MAXMEMORY
512mb
एम्बेडेड Redis के लिए मेमोरी कैप (केवल embedded मोड)। Raspberry Pi जैसे मेमोरी-सीमित होस्ट पर इसे कम करें।
1.x से अपग्रेड करना: अपनी पुरानी snapotter.db को वॉल्यूम में /data/snapotter.db पर रखें और embedded मोड इसे पहली बार बूट होने पर एम्बेडेड PostgreSQL में आयात करता है। आयात एक बार चलता है; बाद के बूट इसे छोड़ देते हैं।
टेलीमेट्री नोट: embedded मोड किसी भी अन्य कॉन्फ़िगरेशन की तरह इमेज के एनालिटिक्स डिफ़ॉल्ट को विरासत में लेता है। प्रकाशित इमेज एनालिटिक्स चालू के साथ शिप होती है; इसे अक्षम करने के लिए --build-arg SNAPOTTER_ANALYTICS=off के साथ बिल्ड करें, या इन-ऐप admin ऑप्ट-आउट का उपयोग करें।
Processing limits
Variable
Default
Description
MAX_UPLOAD_SIZE_MB
0 (unlimited)
मेगाबाइट में प्रति अपलोड अधिकतम फ़ाइल आकार। असीमित के लिए 0 पर सेट करें। प्रकाशित इमेज 0 के साथ शिप होती है; सोर्स से बिल्ड 100 से शुरू होता है।
MAX_BATCH_SIZE
0 (unlimited)
एकल बैच अनुरोध में फ़ाइलों की अधिकतम संख्या। असीमित के लिए 0 पर सेट करें। प्रकाशित इमेज 0 के साथ शिप होती है; सोर्स से बिल्ड 100 से शुरू होता है।
CONCURRENT_JOBS
0 (auto)
समानांतर में चलने वाले बैच जॉब की संख्या। उपलब्ध CPU कोर के आधार पर स्वतः-पहचान के लिए 0 पर सेट करें।
MAX_MEGAPIXELS
0 (unlimited)
मेगापिक्सेल में अनुमत अधिकतम इमेज रिज़ॉल्यूशन। असीमित के लिए 0 पर सेट करें।
MAX_WORKER_THREADS
0 (auto)
इमेज प्रोसेसिंग के लिए अधिकतम वर्कर थ्रेड। उपलब्ध CPU कोर के आधार पर स्वतः-पहचान के लिए 0 पर सेट करें।
PROCESSING_TIMEOUT_S
0 (no limit)
सेकंड में प्रति अनुरोध अधिकतम प्रोसेसिंग समय। बिना टाइमआउट के लिए 0 पर सेट करें।
MAX_PIPELINE_STEPS
20
एक पाइपलाइन में अधिकतम चरणों की संख्या। बिना सीमा के लिए 0 पर सेट करें।
MAX_CANVAS_PIXELS
0 (no limit)
आउटपुट इमेज के लिए पिक्सेल में अधिकतम कैनवास आकार। बिना सीमा के लिए 0 पर सेट करें।
MAX_SVG_SIZE_MB
50
सैनिटाइज़ करने से पहले स्वीकार किया जाने वाला सबसे बड़ा SVG, मेगाबाइट में। यहाँ 0 आसपास की पंक्तियों से अलग व्यवहार करता है। यह पार्स-पूर्व आकार सीमा को बढ़ाने के बजाय पूरी तरह हटा देता है, इसलिए इसे सेट ही रहने दें।
MAX_PDF_PAGES
0 (unlimited)
PDF-to-image रूपांतरण के लिए PDF पृष्ठों की अधिकतम संख्या। असीमित के लिए 0 पर सेट करें।
Cleanup
Variable
Default
Description
FILE_MAX_AGE_HOURS
72
बिना सहेजे प्रोसेसिंग परिणाम (कच्चे अपलोड और टूल आउटपुट) स्वचालित हटाने से पहले कितने समय तक रखे जाते हैं। जिन फ़ाइलों को आप स्पष्ट रूप से Files लाइब्रेरी में सहेजते हैं वे प्रभावित नहीं होतीं और तब तक बनी रहती हैं जब तक आप उन्हें हटा नहीं देते।
CLEANUP_INTERVAL_MINUTES
60
क्लीनअप जॉब कितनी बार चलता है।
Appearance
Variable
Default
Description
DEFAULT_THEME
light
नए सत्रों के लिए डिफ़ॉल्ट थीम। light, dark, या system।
DEFAULT_LOCALE
en
डिफ़ॉल्ट इंटरफ़ेस भाषा।
DEFAULT_TOOL_VIEW
sidebar
डिफ़ॉल्ट टूल लेआउट। sidebar या fullscreen।
Docker permissions
Variable
Default
Description
PUID
999
कंटेनर प्रक्रिया को इस UID के रूप में चलाएँ। बाइंड माउंट के लिए अपने होस्ट उपयोगकर्ता से मिलान करने के लिए सेट करें (id -u)।
PGID
999
कंटेनर प्रक्रिया को इस GID के रूप में चलाएँ। बाइंड माउंट के लिए अपने होस्ट समूह से मिलान करने के लिए सेट करें (id -g)।
Docker example
services:SnapOtter:image:snapotter/snapotter:latestports:- "1349:1349"volumes:- SnapOtter-data:/data- SnapOtter-workspace:/tmp/workspaceenvironment:- 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=12depends_on:postgres:condition:service_healthyredis:condition:service_healthyrestart:unless-stoppedpostgres:image:postgres:17-alpineenvironment:POSTGRES_USER:snapotterPOSTGRES_PASSWORD:snapotter # गैर-स्थानीय तैनाती के लिए इसे बदलेंPOSTGRES_DB:snapottervolumes:- SnapOtter-pgdata:/var/lib/postgresql/datarestart:unless-stoppedhealthcheck:test:["CMD-SHELL","pg_isready -U snapotter -d snapotter"]interval:10stimeout:5sretries:12redis:image:redis:8-alpinecommand:["redis-server","--maxmemory-policy","noeviction","--appendonly","yes"]volumes:- SnapOtter-redisdata:/datarestart:unless-stoppedhealthcheck:test:["CMD","redis-cli","ping"]interval:10stimeout:5sretries:12volumes:SnapOtter-data:SnapOtter-workspace:SnapOtter-pgdata:SnapOtter-redisdata:
Volumes
Docker Compose स्टैक चार वॉल्यूम का उपयोग करता है:
/data (app) - AI मॉडल, Python venv, और उपयोगकर्ता फ़ाइलें। अपलोड की गई फ़ाइलों और इंस्टॉल किए गए AI बंडलों को पुनरारंभ के दौरान रखने के लिए इसे माउंट करें।
/tmp/workspace (app) - प्रोसेस की जा रही फ़ाइलों के लिए अस्थायी स्टोरेज। यह क्षणिक हो सकता है, लेकिन इसे माउंट करने से कंटेनर की लिखने योग्य लेयर भरने से बचती है।
SnapOtter-pgdata (postgres) - PostgreSQL डेटा डायरेक्टरी। यह सभी रिलेशनल डेटा (users, settings, pipelines, jobs, audit log) रखती है। pg_dump या वॉल्यूम स्नैपशॉट के माध्यम से बैकअप लें।
SnapOtter-redisdata (redis) - टिकाऊ जॉब क्यू के लिए Redis append-only फ़ाइल।