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 {#environment-variables}
### Server {#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. |
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.
| `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. |
| `STORAGE_MODE` | `local` | `local` atau `s3`. S3 dan MinIO memerlukan lisensi dengan fitur s3_storage plus variabel `S3_*` di bawah. |
| `DATABASE_URL` | `postgres://snapotter:snapotter@localhost:5432/snapotter` | 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 {#s3-object-storage}
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_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 {#encryption-at-rest}
| 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. |
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.
| `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 {#cleanup}
| 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. |
-`/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.