* docs: clarify file retention vs saved-library persistence
FILE_MAX_AGE_HOURS only affects unsaved processing results (raw uploads
and tool outputs). Files saved to the Files library persist until the
user deletes them. Spell that out in the configuration table and the
getting-started Files section.
* chore(demo): drop removed per-user analytics from the mock API
#336 deleted the per-user analytics consent system (the DB columns, the
PUT /api/v1/user/analytics endpoint, and the consent UI in apps/web). The
demo mock still simulated them: a PUT handler, the analyticsEnabled /
analyticsConsentShownAt state fields, and analytics fields on the session
user. Nothing reads them anymore, so remove them. The current
GET /api/v1/config/analytics mock stays (that endpoint still exists).
* fix(gitignore): anchor demo ignore to root so apps/demo stays trackable
A bare 'demo' pattern matched any dir named demo, including the tracked
apps/demo workspace. New files under apps/demo were silently ignored and
lint-staged choked re-adding it. Root demo/ (the intended target) no
longer exists; anchor the rule to /demo. Build artifacts under apps/demo
stay ignored via the global dist/ and .turbo/ rules.
All SnapOtter environment variables with defaults. Configure auth, storage, AI models, analytics, and more.
Configuration
All configuration is done through environment variables. Every variable has a sensible default, so SnapOtter works out of the box without setting any of them.
Environment variables
Server
Variable
Default
Description
PORT
1349
Port the server listens on.
RATE_LIMIT_PER_MIN
0 (disabled)
Maximum requests per minute per IP. Set to 0 to disable rate limiting.
CORS_ORIGIN
(empty)
Comma-separated allowed origins for CORS, or empty for same-origin only.
LOG_LEVEL
info
Log verbosity. One of: fatal, error, warn, info, debug, trace.
TRUST_PROXY
true
Trust X-Forwarded-For headers from a reverse proxy. Set to false if not behind a proxy.
Authentication
Variable
Default
Description
AUTH_ENABLED
false
Set to true to require login. The Docker image defaults to true.
DEFAULT_USERNAME
admin
Username for the initial admin account. Only used on first run.
DEFAULT_PASSWORD
admin
Password for the initial admin account. Change this after first login.
MAX_USERS
0 (unlimited)
Maximum number of registered user accounts. Set to 0 for unlimited.
SESSION_DURATION_HOURS
168
Login session lifetime in hours (default is 7 days).
SKIP_MUST_CHANGE_PASSWORD
-
Set to any non-empty value to bypass the forced password-change prompt on first login
Storage
Variable
Default
Description
STORAGE_MODE
local
local or s3. Only local storage is currently implemented.
Redis connection string (used for BullMQ job queues).
WORKSPACE_PATH
./tmp/workspace
Directory for temporary files during processing. Cleaned up automatically.
FILES_STORAGE_PATH
./data/files
Directory for persistent user files (uploaded images, saved results).
Processing limits
Variable
Default
Description
MAX_UPLOAD_SIZE_MB
0 (unlimited)
Maximum file size per upload in megabytes. Set to 0 for unlimited.
MAX_BATCH_SIZE
0 (unlimited)
Maximum number of files in a single batch request. Set to 0 for unlimited.
CONCURRENT_JOBS
0 (auto)
Number of batch jobs that run in parallel. Set to 0 to auto-detect based on available CPU cores.
MAX_MEGAPIXELS
0 (unlimited)
Maximum image resolution allowed in megapixels. Set to 0 for unlimited.
MAX_WORKER_THREADS
0 (auto)
Maximum worker threads for image processing. Set to 0 to auto-detect based on available CPU cores.
PROCESSING_TIMEOUT_S
0 (no limit)
Maximum processing time per request in seconds. Set to 0 for no timeout.
MAX_PIPELINE_STEPS
0 (no limit)
Maximum number of steps in a pipeline. Set to 0 for no limit.
MAX_CANVAS_PIXELS
0 (no limit)
Maximum canvas size in pixels for output images. Set to 0 for no limit.
MAX_SVG_SIZE_MB
0 (unlimited)
Maximum SVG file size in megabytes. Set to 0 for unlimited.
MAX_SPLIT_GRID
100
Maximum grid dimension for the image split tool.
MAX_PDF_PAGES
0 (unlimited)
Maximum number of PDF pages for PDF-to-image conversion. Set to 0 for unlimited.
Cleanup
Variable
Default
Description
FILE_MAX_AGE_HOURS
72
How long unsaved processing results (raw uploads and tool outputs) are kept before automatic deletion. Files you explicitly save to the Files library are not affected and persist until you delete them.
CLEANUP_INTERVAL_MINUTES
60
How often the cleanup job runs.
Appearance
Variable
Default
Description
DEFAULT_THEME
light
Default theme for new sessions. light or dark.
DEFAULT_LOCALE
en
Default interface language.
DEFAULT_TOOL_VIEW
sidebar
Default tool layout. sidebar or fullscreen.
Docker permissions
Variable
Default
Description
PUID
999
Run the container process as this UID. Set to match your host user for bind mounts (id -u).
PGID
999
Run the container process as this GID. Set to match your host group for bind mounts (id -g).
/data (app) - AI models, Python venv, and user files. Mount this to keep uploaded files and installed AI bundles across restarts.
/tmp/workspace (app) - Temporary storage for files being processed. This can be ephemeral, but mounting it avoids filling up the container's writable layer.
SnapOtter-pgdata (postgres) - PostgreSQL data directory. This holds all relational data (users, settings, pipelines, jobs, audit log). Back up via pg_dump or volume snapshot.
SnapOtter-redisdata (redis) - Redis append-only file for durable job queues.