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.
Semua variabel lingkungan SnapOtter dengan default-nya. Konfigurasi auth, penyimpanan, model AI, analitik, dan lainnya.
25970c776f7c
human
9c349ff65524
2
Konfigurasi
Semua konfigurasi dilakukan melalui variabel lingkungan. Setiap variabel memiliki default yang masuk akal, jadi SnapOtter bekerja langsung tanpa mengatur satu pun dari mereka.
Variabel lingkungan
Server
Variabel
Default
Deskripsi
PORT
1349
Port tempat server mendengarkan.
RATE_LIMIT_PER_MIN
1000
Permintaan maksimum per menit per IP. Setel ke 0 untuk menonaktifkan pembatasan laju.
CORS_ORIGIN
(kosong)
Origin yang diizinkan dipisahkan koma untuk CORS, atau kosong untuk hanya same-origin.
LOG_LEVEL
info
Verbositas log. Salah satu dari: fatal, error, warn, info, debug, trace.
TRUST_PROXY
loopback,linklocal,uniquelocal
Peer mana yang boleh menetapkan IP klien lewat X-Forwarded-For. Nilai default hanya memercayai peer di jaringan privat, jadi reverse proxy di jaringan Docker atau di LAN dipercaya sedangkan header palsu dari klien publik tidak. Setel true hanya jika di depan ada proxy yang Anda kendalikan pada alamat publik.
Autentikasi
Dua boolean di bawah ini hanya menerima true dan false. Apa pun selain itu, 1 atau yes atau on, gagal validasi dan server keluar sebelum mulai mendengarkan.
Variabel
Default
Deskripsi
AUTH_ENABLED
true
Wajibkan login. Setel ke false untuk berjalan tanpa akun sama sekali, yang memberi setiap permintaan hak admin, jadi batasi itu pada jaringan tepercaya.
DEFAULT_USERNAME
admin
Nama pengguna untuk akun admin awal. Hanya digunakan pada run pertama.
DEFAULT_PASSWORD
admin
Kata sandi untuk akun admin awal. Ubah ini setelah login pertama.
MAX_USERS
0 (tak terbatas)
Jumlah maksimum akun pengguna terdaftar. Setel ke 0 untuk tak terbatas.
SESSION_DURATION_HOURS
168
Masa hidup sesi login dalam jam (default adalah 7 hari).
SKIP_MUST_CHANGE_PASSWORD
false
Setel ke true untuk melewati prompt ganti-kata-sandi paksa pada login pertama.
Penyimpanan
Variabel
Default
Deskripsi
STORAGE_MODE
local
local atau s3. S3 dan MinIO memerlukan lisensi dengan fitur s3_storage plus variabel S3_* di bawah.
String koneksi PostgreSQL. Stack Compose mengarahkan ini ke layanan postgres miliknya; biarkan tidak diatur (bersama REDIS_URL) untuk mendapatkan mode tertanam.
REDIS_URL
redis://localhost:6379
String koneksi Redis (digunakan untuk antrean job BullMQ). Compose mengarahkan ini ke layanan redis miliknya.
WORKSPACE_PATH
./tmp/workspace
Direktori untuk file sementara selama pemrosesan. Dibersihkan secara otomatis. Image menyetelnya ke /tmp/workspace.
FILES_STORAGE_PATH
./data/files
Direktori untuk file pengguna persisten (gambar yang diunggah, hasil yang disimpan). Image menyetelnya ke /data/files.
Penyimpanan objek S3
Hanya dibaca saat STORAGE_MODE=s3. Lewatkan salah satu dari tiga yang wajib dan startup gagal dengan menyebut nama variabel yang Anda tinggalkan.
Variabel
Default
Deskripsi
S3_BUCKET
(kosong)
Bucket yang menyimpan unggahan dan keluaran. Wajib.
S3_ACCESS_KEY_ID
(kosong)
Access key. Wajib. Di dalam kontainer Anda bisa memasangnya sebagai file, lewat S3_ACCESS_KEY_ID_FILE.
S3_SECRET_ACCESS_KEY
(kosong)
Secret key. Wajib. Konvensi file yang sama: S3_SECRET_ACCESS_KEY_FILE.
S3_REGION
us-east-1
Region bucket.
S3_ENDPOINT
(kosong)
Endpoint kustom untuk MinIO, R2, Backblaze, dan penyimpanan lain yang kompatibel dengan S3. Kosong berarti AWS.
S3_FORCE_PATH_STYLE
false
Setel ke true untuk MinIO dan apa pun yang menginginkan endpoint/bucket/key alih-alih pengalamatan virtual-host.
S3_PREFIX
(kosong)
Prefiks key, sehingga satu bucket bisa menampung beberapa instans.
Enkripsi saat disimpan
Variabel
Default
Deskripsi
DATA_ENCRYPTION_KEY
(kosong)
64 karakter heksadesimal (32 byte). Mengenkripsi pengaturan sensitif yang disimpan di basis data. Apa pun yang bukan 64 karakter heksadesimal ditolak saat startup.
DATA_ENCRYPTION_KEY_PREVIOUS
(kosong)
Kunci yang sedang Anda tinggalkan dalam rotasi, format yang sama. Setel keduanya selama rotasi agar baris yang ada tetap bisa didekripsi, lalu hapus yang ini.
Mode tertanam
Jalankan image tanpa DATABASE_URL dan tanpa REDIS_URL dan ia memulai PostgreSQL 17 dan Redis-nya sendiri di dalam kontainer, terikat ke loopback, dengan semua data pada volume /data. Ini memulihkan pengalaman docker run satu perintah untuk quick start, homelab, dan upgrade dari 1.x. Ini adalah jalur kenyamanan, bukan deployment produksi: untuk produksi, jalankan stack Compose 3 kontainer dengan PostgreSQL dan Redis terpisah. Mode tertanam memerlukan menjalankan kontainer sebagai root dan tidak kompatibel dengan runtime UID arbitrer (OpenShift, Kubernetes runAsNonRoot); gunakan Compose di sana.
Variabel
Default
Deskripsi
EMBEDDED
auto
Diaktifkan otomatis saat DATABASE_URL dan REDIS_URL keduanya tidak diatur. Setel ke 0 untuk menonaktifkannya (aplikasi kemudian gagal cepat jika tidak ada DATABASE_URL/REDIS_URL eksternal yang diatur, alih-alih diam-diam memulai basis data dalam kontainer).
REDIS_MAXMEMORY
512mb
Batas memori untuk Redis tertanam (hanya mode tertanam). Turunkan pada host dengan memori terbatas seperti Raspberry Pi.
Upgrade dari 1.x: letakkan snapotter.db lama Anda di /data/snapotter.db dalam volume dan mode tertanam mengimpornya ke PostgreSQL tertanam pada boot pertama. Impor berjalan sekali; boot berikutnya melewatinya.
Catatan telemetri: mode tertanam mewarisi default analitik image seperti konfigurasi lainnya. Image yang diterbitkan dikirim dengan analitik aktif; build dengan --build-arg SNAPOTTER_ANALYTICS=off, atau gunakan opt-out admin dalam aplikasi, untuk menonaktifkannya.
Batas pemrosesan
Variabel
Default
Deskripsi
MAX_UPLOAD_SIZE_MB
0 (tak terbatas)
Ukuran file maksimum per unggahan dalam megabyte. Setel ke 0 untuk tak terbatas. Image yang diterbitkan dikirim dengan 0; build dari sumber dimulai pada 100.
MAX_BATCH_SIZE
0 (tak terbatas)
Jumlah maksimum file dalam satu permintaan batch. Setel ke 0 untuk tak terbatas. Image yang diterbitkan dikirim dengan 0; build dari sumber dimulai pada 100.
CONCURRENT_JOBS
0 (otomatis)
Jumlah job batch yang berjalan secara paralel. Setel ke 0 untuk deteksi otomatis berdasarkan inti CPU yang tersedia.
MAX_MEGAPIXELS
0 (tak terbatas)
Resolusi gambar maksimum yang diizinkan dalam megapiksel. Setel ke 0 untuk tak terbatas.
MAX_WORKER_THREADS
0 (otomatis)
Thread worker maksimum untuk pemrosesan gambar. Setel ke 0 untuk deteksi otomatis berdasarkan inti CPU yang tersedia.
PROCESSING_TIMEOUT_S
0 (tanpa batas)
Waktu pemrosesan maksimum per permintaan dalam detik. Setel ke 0 untuk tanpa timeout.
MAX_PIPELINE_STEPS
20
Jumlah maksimum langkah dalam sebuah pipeline. Setel ke 0 untuk tanpa batas.
MAX_CANVAS_PIXELS
0 (tanpa batas)
Ukuran kanvas maksimum dalam piksel untuk gambar keluaran. Setel ke 0 untuk tanpa batas.
MAX_SVG_SIZE_MB
50
SVG terbesar yang diterima sebelum disanitasi, dalam megabyte. 0 berperilaku berbeda di sini dibanding baris-baris di sekitarnya. Ia menghapus batas ukuran pra-parse sepenuhnya alih-alih menaikkannya, jadi biarkan yang satu ini tetap disetel.
MAX_PDF_PAGES
0 (tak terbatas)
Jumlah maksimum halaman PDF untuk konversi PDF-ke-image. Setel ke 0 untuk tak terbatas.
Pembersihan
Variabel
Default
Deskripsi
FILE_MAX_AGE_HOURS
72
Berapa lama hasil pemrosesan yang tidak disimpan (unggahan mentah dan keluaran tool) disimpan sebelum penghapusan otomatis. File yang Anda simpan secara eksplisit ke pustaka Files tidak terpengaruh dan bertahan hingga Anda menghapusnya.
CLEANUP_INTERVAL_MINUTES
60
Seberapa sering job pembersihan berjalan.
Tampilan
Variabel
Default
Deskripsi
DEFAULT_THEME
light
Tema default untuk sesi baru. light, dark, atau system.
DEFAULT_LOCALE
en
Bahasa antarmuka default.
DEFAULT_TOOL_VIEW
sidebar
Tata letak tool default. sidebar atau fullscreen.
Izin Docker
Variabel
Default
Deskripsi
PUID
999
Jalankan proses kontainer sebagai UID ini. Setel agar cocok dengan pengguna host Anda untuk bind mount (id -u).
PGID
999
Jalankan proses kontainer sebagai GID ini. Setel agar cocok dengan grup host Anda untuk bind mount (id -g).
/data (app) - Model AI, venv Python, dan file pengguna. Pasang ini untuk menyimpan file yang diunggah dan bundel AI yang terpasang di seluruh restart.
/tmp/workspace (app) - Penyimpanan sementara untuk file yang sedang diproses. Ini bisa efemeral, tetapi memasangnya menghindari pengisian lapisan writable kontainer.
SnapOtter-pgdata (postgres) - Direktori data PostgreSQL. Ini menyimpan semua data relasional (pengguna, pengaturan, pipeline, job, log audit). Cadangkan melalui pg_dump atau snapshot volume.
SnapOtter-redisdata (redis) - File append-only Redis untuk antrean job yang tahan lama.