Operations
Environment Variables Reference
Complete reference for QuoteNode environment variables across production, development, Docker Compose, backup workers, and frontend dev tooling.
Environment Variables Reference
This page consolidates the environment variables currently used by the QuoteNode project.
The main source of truth is the application repository templates:
infra/.env.prod.exampleinfra/.env.dev.exampleinfra/.env.dev-sidinfra/docker-compose.*.yml
Use this page as an operator-oriented catalog. For a minimal getting-started setup, see the Installation Guide. For deployment topology, see Deployment Options.
How to read this reference
- Prod means a variable belongs in a production
.envfile. - Dev means local development or demo stacks.
- Compose means Docker Compose host-side wiring rather than the application itself.
- Empty defaults usually mean “set this explicitly when you need the feature”.
Compose and local stack variables
These variables shape the local Docker Compose environment and frontend dev proxy wiring.
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
COMPOSE_PROJECT_NAME |
Dev / Compose | Prevents container-name collisions between multiple local stacks. | quotenode-dev, quotenode-dev-sid |
POSTGRES_PORT |
Dev / Compose | Host port mapped to PostgreSQL. | 5433, 5434 |
PG_JIT |
Dev / Compose | PostgreSQL JIT compilation. Off by default — it rarely helps this OLTP workload. Set to on to enable. |
off |
MAILPIT_PORT |
Dev / Compose | Host port for Mailpit UI. | 8025, 8026 |
BACKEND_PORT |
Dev / Compose | Host port for backend API. | 8091, 8092 |
FRONTEND_PORT |
Dev / Compose | Host port for frontend app. | 5174, 5175 |
VITE_PUBLIC_API_BASE |
Dev / Frontend | Browser-visible API base URL used by the Vite frontend in local stacks. | http://localhost:8091, http://localhost:8092 |
APP_VERSION |
Prod / Dev / Compose | Docker image tag selected by Compose. | latest, v0.9.0-alpha, v1.0.0 |
APP_CHANNEL |
Prod / Dev / Compose | Product release channel embedded into build metadata and UI labels. | alpha, stable |
VITE_RELEASE_CHECK_ENABLED |
Prod / Dev / Frontend | Enables the admin-only upstream release availability check. | true, false |
VITE_RELEASE_MANIFEST_URL |
Prod / Dev / Frontend | Public JSON manifest URL used for upstream release checks. | https://quotenode.dev/releases/latest.json |
PROXY_MODE |
Prod / Dev / Compose | Chooses whether Caddy runs inside the stack (internal) or an external reverse proxy is used (external). |
internal, external |
DOMAIN |
Prod / Compose | Public domain used by Caddy and public URLs when internal proxy mode is enabled. | quotenode.example.com |
SECURITY_TRUSTED_PROXIES |
Prod / Dev / Compose | Usually empty — the client IP is auto-detected behind internal proxies (private/loopback ranges) and CDNs such as Cloudflare (via CF-Connecting-IP). Forwarded headers from a direct (non-internal) peer are ignored. Set only for an unusual proxy whose transport peer is a public address. |
empty, 203.0.113.5/32 |
Operator note: QuoteNode keeps runtime refresh checks (/app-version.json) separate from upstream release checks (https://quotenode.dev/releases/latest.json). The upstream notice is admin-only, never forces a reload, and can be disabled with VITE_RELEASE_CHECK_ENABLED=false.
Database and core runtime
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
DB_URL |
Prod / Dev | JDBC connection string for PostgreSQL. | jdbc:postgresql://postgres:5432/quotenode |
DB_USERNAME |
Prod / Dev | Database user. | quotenode, app |
DB_PASSWORD |
Prod / Dev | Database password. | random 32+ chars in prod |
DB_NAME |
Prod / Dev / Compose | Database name used by app and Compose. | quotenode, app |
DB_AUTO_MIGRATE |
Prod / Dev | Automatic PostgreSQL major-version migration on startup (used by stack-up.sh). Off by default; when true, an older data volume is backed up and migrated before the stack starts. |
false |
SPRING_PROFILES_ACTIVE |
Prod / Dev | Activates the Spring profile. | prod, dev |
CORS_ALLOWED_ORIGINS |
Prod / Dev | Allowed browser origins for the API. Avoid * in production. |
https://yourdomain.com |
LOG_LEVEL |
Prod / Dev | Baseline application log verbosity. | ERROR, INFO, DEBUG |
Docker log rotation and support diagnostics
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
DOCKER_LOG_MAX_SIZE |
Prod / Compose | Maximum size of a single container log file before rotation. | 10m |
DOCKER_LOG_MAX_FILE |
Prod / Compose | Number of rotated container log files to retain. | 5 |
SUPPORT_LOGS_BUFFER_SIZE |
Prod | Size of the in-app support log preview buffer. | 4000 |
SUPPORT_LOGS_PREVIEW_RATE_LIMIT_PER_MINUTE |
Prod | Rate limit for support log preview requests. | 30 |
SUPPORT_LOGS_LOG_LEVEL_DEFAULT_TTL_MINUTES |
Prod | Auto-revert timeout for temporary log-level changes. | 15 |
SUPPORT_LOGS_LOG_LEVEL_MAX_TTL_MINUTES |
Prod | Maximum allowed temporary log-level escalation window. | 30 |
SUPPORT_LOGS_LOG_LEVEL_ALLOWED_SCOPES |
Prod | Package scopes that may be temporarily escalated for diagnostics. | dev.quotenode,... |
Auth and session security
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
DB_ENCRYPTION_KEY |
Prod / Dev | Main application-layer encryption key for sensitive data. | 64 hex chars in prod |
TIMING_TOKEN_SECRET |
Prod / Dev | HMAC secret for timing-token based bot protection. | 32+ random chars |
PUBLIC_LINK_PASSWORD_SESSION_SECRET |
Prod / Dev | Session secret for password-protected public offer links. | 32+ random chars |
AUTH_PASSWORD_MIN_LENGTH |
Prod / Dev | Minimum password length policy. | 12 in prod, 8 in dev |
AUTH_PASSWORD_COMPLEXITY_LEVEL |
Prod / Dev | Password complexity tier enforced by auth policy. | 2 in prod, 1 in dev |
AUTH_SESSION_IDLE_TIMEOUT_MIN |
Prod / Dev | Idle timeout for authenticated sessions. | 30, 480 |
SECURITY_SESSION_ABSOLUTE_TIMEOUT_H |
Prod / Dev | Absolute maximum session lifetime. | 12, 24 |
SECURITY_MAX_FAILED_LOGINS_SOFT |
Prod / Dev | Failed login threshold for soft warnings. | 5, 10 |
SECURITY_MAX_FAILED_LOGINS_TEMP_LOCK |
Prod / Dev | Failed login threshold for temporary lockout. | 10, 20 |
SECURITY_MAX_FAILED_LOGINS_HARD_LOCK |
Prod / Dev | Failed login threshold for hard lockout. | 20, 50 |
SECURITY_TEMP_LOCK_MINUTES |
Prod / Dev | Duration of temporary lockout. | 30, 5 |
FEATURE_2FA_ENABLED |
Prod / Dev | Master switch for two-factor authentication flows. | true, false |
SECURITY_REQUIRE_2FA_ROLES |
Prod / Dev | Roles that must enroll in 2FA. | ADMIN |
SECURITY_BOT_DETECTION_ENABLED |
Prod / Dev | Enables the bot-detection layer. | true, false |
SECURITY_BOT_SCORE_WARN_THRESHOLD |
Prod / Dev | Bot score threshold for warning-only action. | 30 |
SECURITY_BOT_SCORE_BLOCK_THRESHOLD |
Prod / Dev | Bot score threshold for blocking action. | 70 |
SECURITY_IP_WHITELIST |
Prod / Dev | Operator-enforced IP allow-list (comma-separated literal IP/CIDR). When enabled, the whitelist gates the full admin surface — login, the 2FA challenge and every authenticated admin route — leaving only health/infra and customer-facing public endpoints reachable. When set it is authoritative over the in-app tenant whitelist and read-only in the UI; an operator list is enforced at startup with no auto-rollback, so confirm your own address is covered. Empty = the tenant setting (if any) applies. Resolves clients via SECURITY_TRUSTED_PROXIES. |
empty, 203.0.113.10,198.51.100.0/24 |
SECURITY_IP_WHITELIST_FORCE_DISABLE |
Runtime override | Emergency operator override that disables stored IP whitelist enforcement (checked before any whitelist parsing, so it also recovers from an invalid stored list — and, since the whitelist now gates login, restores the ability to sign in). Restart required; ENV-only, never toggled from the UI. Disables only the IP whitelist — not GeoIP, bot detection or rate limiting. | false |
SECURITY_IP_WHITELIST_CONFIRMATION_WINDOW_SECONDS |
Prod / Dev | How long an in-app whitelist enable/narrow stays pending re-confirmation before it auto-rolls back to the previous list (lockout safety). The editing session confirms automatically when its current address is covered. | 120 |
CRM, files, imports, and product media
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
CRM_DEDUP_NAME_SIMILARITY_THRESHOLD |
Prod / Dev | pg_trgm similarity threshold for duplicate-company warnings. | 0.8 |
CRM_DEDUP_EMAIL_DOMAIN_WARN |
Prod / Dev | Warn when business email domains match existing records. | true |
CRM_ATTACHMENT_MAX_SIZE_MB |
Prod / Dev | Maximum CRM attachment size. | 25, 10 |
CRM_ATTACHMENT_ALLOWED_TYPES |
Prod / Dev | Allowed CRM attachment extensions. | pdf,doc,docx,... |
CSV_IMPORT_MAX_ROWS |
Prod / Dev | Row limit for CRM CSV imports. | 5000 |
APP_PRODUCT_IMPORT_MAX_ROWS |
Prod / Dev | Row limit for product (CSV/XLSX) imports. | 50000 |
STORAGE_PATH |
Prod / Dev | Root directory for uploaded files. | /data/uploads, ./data/uploads |
PIM_MEDIA_MAX_SIZE_MB |
Prod / Dev | Maximum size for a single product image. | 3, 5 |
PIM_MEDIA_MAX_PER_PRODUCT |
Prod / Dev | Maximum media items attached to one product. | 5, 10 |
PIM_MEDIA_THUMBNAIL_WIDTH |
Prod / Dev | Thumbnail width used during image processing. | 300 |
PIM_MEDIA_ALLOWED_TYPES |
Prod / Dev | Allowed product media extensions. | jpg,jpeg,png,webp,svg |
PIM_MEDIA_MAX_MEGAPIXELS |
Prod / Dev | Reject images whose pixel dimensions exceed this many megapixels, checked from the header before any full decode (memory-safety guard against decompression bombs). | 40 |
PIM_MEDIA_OPTIMIZE_ENABLED |
Prod / Dev | Downscale and re-encode the stored original image on upload. Set to false to keep originals verbatim. |
true |
PIM_MEDIA_OPTIMIZE_MAX_DIMENSION |
Prod / Dev | Longest-side cap in pixels for the stored original when optimization is enabled (offers always use a 300px thumbnail regardless). | 2560 |
PIM_MEDIA_OPTIMIZE_QUALITY |
Prod / Dev | JPEG re-encode quality (0.0–1.0) applied during image optimization. |
0.85 |
IMPORT_ZIP_MAX_SIZE_MB |
Prod / Dev | Maximum ZIP size for batch image import. | 100 |
IMPORT_ZIP_MAX_IMAGES |
Prod / Dev | Maximum image count inside a ZIP import. | 1000 |
IMPORT_IMAGE_MAX_SIZE_MB |
Prod / Dev | Maximum size of one imported image inside ZIP batches. | 5 |
IMPORT_IMAGE_FUZZY_THRESHOLD |
Prod / Dev | Threshold for fuzzy filename-to-product matching. | 0.82 |
MULTIPART_MAX_FILE_SIZE |
Prod / Dev | Global ceiling for any single uploaded file. This is the upload envelope — per-feature limits above (imports, product media, attachments) are enforced separately and are tighter. Sized for the largest legitimate upload, an image ZIP archive. | 200MB |
MULTIPART_MAX_REQUEST_SIZE |
Prod / Dev | Global ceiling for a whole multipart request, e.g. a multi-file image upload. | 220MB |
MULTIPART_FILE_SIZE_THRESHOLD |
Prod / Dev | Uploads larger than this spill to a temp file instead of memory, keeping large uploads off the JVM heap. | 2MB |
Shipping, FX, and offer defaults
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
SHIPPING_DEFAULT_VOLUMETRIC_DIVISOR |
Prod / Dev | Volumetric-weight divisor used by shipping calculations. | 4000 |
SHIPPING_OVERRIDE_REQUIRES_REASON |
Prod / Dev | Requires a justification when shipping cost is overridden manually. | true |
FX_PROVIDER |
Prod / Dev | FX rate source. | NBP, MOCK, ECB, CUSTOM |
FX_PROVIDER_URL |
Prod / Dev | Custom provider URL override. | empty unless CUSTOM |
FX_REFRESH_INTERVAL_MIN |
Prod / Dev | Automatic FX refresh cadence. | 60, 0 |
FX_DEFAULT_MARGIN_PERCENT |
Prod / Dev | Default percentage margin applied on top of provider rates. | 0 |
FX_DEVIATION_WARN_PERCENT |
Prod / Dev | Warn threshold for manually adjusted FX rates. | 3 |
FX_DEVIATION_BLOCK_PERCENT |
Prod / Dev | Block threshold for manually adjusted FX rates. | 8 |
OFFER_NUMBER_PREFIX |
Prod / Dev | Prefix used when numbering offers. | OF |
Email, public links, and notifications
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
SMTP_HOST |
Prod / Dev | SMTP hostname used for offer sending and notifications. | provider hostname, localhost |
SMTP_PORT |
Prod / Dev | SMTP port. | 587, 1025, 1026 |
SMTP_USERNAME |
Prod / Dev | SMTP auth username. | provider account |
SMTP_PASSWORD |
Prod / Dev | SMTP auth password. | provider secret |
SMTP_AUTH |
Prod / Dev | Enables SMTP authentication. | true, false |
SMTP_STARTTLS |
Prod / Dev | Enables STARTTLS negotiation. | true, false |
PUBLIC_LINK_TOKEN_BYTES |
Prod / Dev | Entropy used for generated public-link tokens. | 32 |
PUBLIC_LINK_DEFAULT_EXPIRY_DAYS |
Prod / Dev | Default validity window for public links. | 0 for no expiry |
PUBLIC_RATE_LIMIT_OPEN_PER_HOUR |
Prod / Dev | Hourly limit for opening public offer endpoints. | 60, 999 |
PUBLIC_RATE_LIMIT_ACTION_PER_HOUR |
Prod / Dev | Hourly limit for public actions such as accept/reject. | 5, 999 |
TRACKING_IP_ANONYMIZE |
Prod / Dev | Enables IP anonymization for tracking data. | false |
TRACKING_IP_ANONYMIZE_AFTER_DAYS |
Prod / Dev | Delayed anonymization period for tracking IPs. | 0 |
TRACKING_RETENTION_DAYS |
Prod / Dev | Retention window for public-link tracking data. | 365 |
CLIENT_CONFIRM_EMAIL_ENABLED |
Prod / Dev | Sends a confirmation email to the client after acceptance. | false |
NOTIFICATIONS_ENABLED |
Prod / Dev | Enables the notifications subsystem. | true |
NOTIFICATIONS_EMAIL_ENABLED |
Prod / Dev | Enables email delivery for notifications. | true, false |
NOTIFICATIONS_PUBLIC_PREFERENCES_URL |
Prod | Public URL for notification preference management. | https://yourdomain.com/notifications/preferences |
NOTIFICATIONS_PREFERENCE_TOKEN_TTL_DAYS |
Prod | Token validity for notification-preference links. | 30 |
NOTIFICATIONS_OFFER_EXPIRY_WARN_DAYS |
Prod / Dev | Days-before-expiry reminder schedule for offers. | 7,2 |
NOTIFICATIONS_LICENSE_EXPIRY_WARN_DAYS |
Prod / Dev | Days-before-expiry reminder schedule for licenses. | 30,14,7,1 |
REMINDERS_JOB_INTERVAL_MINUTES |
Prod / Dev | Polling cadence for reminder jobs. | 5 |
PDF generation
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
PDF_ENABLED |
Prod / Dev | Enables PDF generation flows. | true, false |
PDF_GOTENBERG_URL |
Prod / Dev | Internal URL of the Gotenberg service. | http://gotenberg:3000 |
PDF_SYNC_TIMEOUT_MS |
Prod / Dev | Timeout for synchronous PDF requests. | 10000, 5000 |
PDF_SYNC_MAX_ITEMS |
Prod / Dev | Maximum offer-item count still handled synchronously. | 50 |
PDF_STORAGE_PATH |
Prod / Dev | Filesystem path where generated PDFs are stored. | /data/pdfs, ./data/pdfs |
PDF_RETENTION_DAYS |
Prod / Dev | Retention period for generated PDFs. | 365 |
PDF_RETRY_BACKOFF_SECONDS |
Prod / Dev | Retry schedule for async PDF jobs. | 30,120,600 |
PDF_WORKER_CONCURRENCY |
Prod / Dev | Worker concurrency for PDF processing. | 2 |
PDF_WORKER_POLL_INTERVAL_MS |
Prod / Dev | Polling interval for PDF jobs. | 2000 |
Licensing, reports, and maintenance
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
LICENSE_SKIP_SIGNATURE_CHECK |
Prod / Dev | Bypasses license signature validation. Never enable in production. | false, true |
LICENSE_EXPIRY_CHECK_INTERVAL_H |
Prod / Dev | Reload cadence for license-expiry checks. | 24 |
REPORTS_DEFAULT_PERIOD_DAYS |
Prod / Dev | Default reporting date range. | 30 |
REPORTS_EXPORT_MAX_ROWS |
Prod / Dev | Row cap for report exports. | 10000 |
Backups, GeoIP, and privacy operations
| Variable | Scope | Purpose | Typical value |
|---|---|---|---|
BACKUP_ENABLED |
Prod / Dev | Enables scheduled backups. | true, false |
BACKUP_CRON |
Prod / Dev | Cron schedule for automated backups. | 0 0 2 * * * |
BACKUP_RETENTION_DAILY |
Prod / Dev | Number of daily backups to retain. | 7 |
BACKUP_RETENTION_WEEKLY |
Prod / Dev | Number of weekly backups to retain. | 4 |
BACKUP_RETENTION_MONTHLY |
Prod / Dev | Number of monthly backups to retain. | 12 |
BACKUP_LOCAL_DIR |
Runtime / Compose | Local directory used by backup scripts and backup-worker containers. | /app/data/backups |
BACKUP_ARCHIVE_ENCRYPTION_MODE |
Prod / Dev | Archive encryption model: AGE_RECIPIENT (recommended) or NONE. |
AGE_RECIPIENT |
BACKUP_AGE_RECIPIENT |
Prod / Dev | Public age recipient (age1...) for encrypted archives. |
age1... |
BACKUP_DATABASE_PAYLOAD_MODE |
Prod / Dev | Database payload: APP_ENCRYPTED (default) or PII_DECRYPTED. |
APP_ENCRYPTED |
JOBS_MODE |
Prod / Dev / Compose | Which scheduled jobs the in-JVM scheduler runs: all (web + backups in one container), web (web only — pair with a backup-only worker), backup-only (dedicated backup worker). |
all |
BACKUP_RUNTIME_PROFILE |
Prod / Dev | Runtime profile label recorded in backup logs/manifests: WORKER, WEB_MAINTENANCE, ONE_SHOT, OFFLINE_MAINTENANCE. Pair WEB_MAINTENANCE with JOBS_MODE=all (no separate worker); pair WORKER with JOBS_MODE=web + a backup-only worker. |
WORKER |
BACKUP_VERIFY_MODE |
Prod / Dev | Post-backup verification: off, archive, sandbox. |
off |
BACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP |
Prod / Dev | Allow explicit unencrypted local backup opt-in. | false |
BACKUP_RCLONE_REMOTE |
Prod / Dev | rclone destination for offsite backups. | s3:bucket/path |
BACKUP_OFFLINE_NOTICE_SECONDS |
Prod | Grace period before offline maintenance stops services. | 300 |
BACKUP_MAINTENANCE_PAGE_ENABLED |
Prod | Serve static maintenance page during offline backup. | false |
BACKUP_DOWNLOAD_GRANT_TTL_SECONDS |
Prod / Dev | TTL for one-time backup download grants. | 120 |
GEOIP_ENABLED |
Prod / Dev | Country-enforcement switch only (also the break-glass switch). The database loads and auto-updates independently — see GEOIP_AUTO_UPDATE. |
false |
GEOIP_DB_PATH |
Prod / Dev | Path to the GeoIP database (auto-fetched on startup; keyless DB-IP by default, MaxMind via MAXMIND_*). |
/app/data/geoip/... |
SECURITY_GEOIP_ALLOWED_COUNTRIES |
Prod / Dev | ISO country allowlist for GeoIP checks. | empty or PL,DE,CZ |
MAXMIND_ACCOUNT_ID |
Prod | MaxMind account for GeoLite downloads. | account ID |
MAXMIND_LICENSE_KEY |
Prod | MaxMind license key. | secret |
GEOIP_EDITION_ID |
Prod | MaxMind edition identifier. | GeoLite2-Country |
GDPR_ANONYMIZE_AUTO_AFTER_DAYS |
Prod / Dev | Automatic anonymization horizon for privacy workflows. | 0 |
Practical guidance
- Start from the production template for real deployments and from the development template for local work.
- Treat
DB_ENCRYPTION_KEY,TIMING_TOKEN_SECRET,PUBLIC_LINK_PASSWORD_SESSION_SECRET, and SMTP credentials as secrets that must be backed up securely. - Keep Compose-only ports and frontend variables out of production
.envfiles unless your deployment model explicitly needs them. - If you need only the smallest viable production setup, the Installation Guide is intentionally shorter than this reference.