Environment variables are for what a server needs before it can read its settings (the encryption key, the database on first boot) and for per-server tuning. Everything else is a setting: stored encrypted in PostgreSQL, changed in Settings, and the same on every server at once (see Settings reference).
1. Where to set them
| Running Depotex as | Set them in |
|---|---|
| A service (systemd) | An EnvironmentFile= readable only by the service user, for example /etc/depotex/server.env (mode 0600) |
| Containers | docker run -e NAME=value or --env-file; secrets from your orchestrator's secret store |
| Kubernetes (Helm) | backend.env and frontend.env in your values; secrets in the app secret prime-secrets.sh created. See Install with Helm |
- A value the server can't read (a duration that isn't one, a number out of range) stops it at startup with a message naming the variable, rather than running with a value you didn't mean.
- Durations are Go durations: 30s, 15m, 24h. Sizes are bytes unless the name says otherwise. Schedules are cron expressions (minute hour day month weekday, UTC).
- Many defaults below are defaults only until an administrator saves the matching settings page; the page then wins on every server. The table says so where it applies.
In a cluster, give every server the same values, except the per-server ones (PORT, BIND_ADDR, NODE_DISPLAY_NAME, directories, LOG_LEVEL). Some limits are read from the environment only, so two servers with different values would answer the same request differently: CARGO_MAX_CRATE_SIZE, COMPOSER_MAX_ARCHIVE_SIZE, HUGGINGFACE_REGULAR_MAX_SIZE, PLUGIN_MAX_PACKAGE_SIZE, the VIBE_MAX_* limits, GITLFS_BATCH_MAX_OBJECTS, WEB_UPLOAD_MAX_FILES, DOCKER_DEFAULT_PLATFORM and GROUP_MERGE_MAX_BYTES.
2. Bootstrap
| Variable | Default | Meaning |
|---|---|---|
| CONFIG_ENCRYPTION_KEY | none, required | Encrypts the bootstrap file and every credential stored in the database. Required on every start. Use a long random value (openssl rand -base64 32), the same on every server, and keep it with your backups: without it nothing can be read |
| DATABASE_URL | none | PostgreSQL URL. Needed on a server's first start (and for setup); then saved, encrypted, in the bootstrap file. Add pool_max_conns=N for the pool size and sslmode=verify-full for TLS |
| BOOTSTRAP_FILE_PATH | ./data/bootstrap.enc (/app/data/bootstrap.enc in the image) | Where the server keeps its encrypted bootstrap file (database URL and identity). Per server; keep it on persistent disk |
| PORT | 8080 | The server's HTTP port |
| BIND_ADDR | 127.0.0.1 (0.0.0.0 in the image) | Address the server listens on. The default suits a web app and proxy on the same host |
| FRONTEND_URL | http://localhost:3000 | Where the web app is; also the default allowed CORS origin |
| CORS_ALLOWED_ORIGINS | FRONTEND_URL | Comma-separated origins allowed to call the API from a browser |
| APP_ENV | empty | development prints the log as readable console lines instead of JSON; leave it unset in production |
3. Setup and recovery
| Variable | Default | Meaning |
|---|---|---|
| SETUP_TOKEN | random, new on every start | The setup key the wizard needs. Set it to choose it (several servers sharing one setup, scripts) |
| SETUP_CONFIG_FILE | empty | A setup file for unattended setup; same as --setup-config |
| SETUP_UPLOAD_DIR | ./data/setup-upload | Where a backup uploaded to the wizard's Restore from a backup waits; needs room for the whole file |
| RECOVERY_TOKEN | random | The key of the recovery page |
| LICENSE_BANNER_DAYS | 30 | Super admins see a banner this many days before the license expires (0 turns it off; 0–365) |
4. Reverse proxy and web app
| Variable | Default | Meaning |
|---|---|---|
| TRUSTED_PROXIES | 127.0.0.0/8,::1/128 | Proxies whose X-Forwarded-For / X-Real-IP the server trusts (IPs or CIDRs). List the web app and every proxy and load balancer in front, or everyone shares one address for allowlists, rate limits, lockout and the audit log |
| FRONTEND_BEHIND_PROXY | false | Web app: true when a proxy in front sets X-Forwarded-For, -Host and -Proto, so they're passed on. Then only the proxy may reach the web app's port |
| FRONTEND_API_BODY_LIMIT | 33554432 (32 MiB) | Web app: largest /api request body it forwards; raise it with BROWSE_GUARD_MAX_SBOM, PLUGIN_MAX_PACKAGE_SIZE or BACKUP_UPLOAD_CHUNK_SIZE |
| BACKEND_URL | http://127.0.0.1:8080 | Web app: where the server is |
| CSP_ENFORCE | unset (report only) | Web app: true enforces the Content-Security-Policy; unset, violations are only logged as [csp] lines |
| PORT, HOSTNAME | 3000, 0.0.0.0 (image) | Web app: its port and listen address |
5. Sign-in and sessions
| Variable | Default | Meaning |
|---|---|---|
| AUTH_LOCKOUT_THRESHOLD | 5 | Wrong passwords that lock an account |
| AUTH_LOCKOUT_WINDOW | 15m | How long failures keep counting |
| AUTH_LOCKOUT_DURATION | 15m | How long an account stays locked |
| AUTH_IP_RATE_LIMIT | 20 | Failed sign-ins and unknown tokens per address before it's blocked (until saved in Settings → Security → Rate limits) |
| AUTH_IP_RATE_WINDOW | 15m | Window of that count and block |
| AUTH_PASSWORD_MIN_LENGTH | 12 | Minimum password length (8–64) |
| AUTH_SESSION_LIFETIME | 24h | Longest session without Remember me (until saved in Settings → Security → Sessions) |
| AUTH_REMEMBER_SESSION_LIFETIME | 168h | Longest session with Remember me |
| AUTH_MAX_SESSIONS | 5 | Sessions per person |
| AUTH_REFRESH_LIFETIME, AUTH_REMEMBER_REFRESH_LIFETIME, AUTH_REFRESH_GRACE_PERIOD | built in | Lifetimes of the browser's refresh tokens; leave them unless support asks |
| AUTH_COOKIE_DOMAIN | the host | Domain of the session cookies |
| AUTH_COOKIE_SECURE | true | Session cookies are sent over HTTPS only. false only for a local test over plain HTTP |
| AUTH_PASSWORD_RESET_TTL | 30m | Password reset link lifetime (5m–24h) |
| AUTH_INVITATION_TTL | 168h | Invitation link lifetime (1h–720h) |
| AUTH_LOGIN_HISTORY_RETENTION_DAYS | 90 | Days of login history kept |
| AUTH_CLEANUP_RETENTION_DAYS | built in | Days expired sessions and tokens are kept before cleanup |
| SSO_ENFORCEMENT_OVERRIDE | false | Emergency only: true ignores Require single sign-on on this server so an administrator can sign in with a password while the identity provider is down. Remove it afterwards |
6. Rate limits and quotas
Defaults until saved in Settings → Security → Rate limits (see Rate Limits & Quotas); 0 turns a limit off.
| Variable | Default | Meaning |
|---|---|---|
| RATE_LIMIT_PREAUTH | 10000 | Requests per minute per address before sign-in is checked (flood guard) |
| RATE_LIMIT | 600 | Per minute per person in the browser |
| RATE_LIMIT_ANON | 60 | Per minute per address for anonymous requests |
| RATE_LIMIT_WS | 20 | WebSocket connections per minute per address |
| RATE_LIMIT_SETUP | 30 | Per minute per address in setup and recovery mode (environment only) |
| RATE_LIMIT_BULK | 20000 | Package-manager requests (/repository/) per minute per person, token or anonymous address |
| RATE_LIMIT_DRY_RUN | false | true logs requests over a limit instead of refusing them |
| DOWNLOAD_QUOTAS_ENABLED | false | Daily and monthly download quotas (Pro) |
| DOWNLOAD_QUOTA_USER_GIB_PER_DAY, …_PER_MONTH | 0 (none) | Per signed-in person (GiB) |
| DOWNLOAD_QUOTA_ANON_GIB_PER_DAY, …_PER_MONTH | 0 (none) | Per anonymous address (GiB) |
| DOWNLOAD_QUOTA_WARN_PERCENT | 80 | Warn at this share of a quota (0: never) |
| DOWNLOAD_QUOTA_ENFORCE | true | false: warn only |
| DOWNLOAD_USAGE_RETENTION_DAYS | 90 | Days of download totals kept (1–3650) |
| API_TOKEN_USAGE_FLUSH_INTERVAL | 5s | How long a server batches API token usage before saving it (up to 1m) |
| API_TOKEN_RETENTION_DAYS | 90 | Default retention of the token cleanup job (revoked and expired tokens) |
7. Database, Redis and cluster
| Variable | Default | Meaning |
|---|---|---|
| DB_CONNECT_TIMEOUT | 30s | How long a starting server keeps trying the database |
| DB_SLOW_QUERY_THRESHOLD | 500ms | Queries slower than this are logged as warnings |
| NODE_DISPLAY_NAME | empty | This server's name in Settings → Clustering (cluster mode) |
| CLUSTER_HEARTBEAT_INTERVAL | 10s | How often a server reports it's alive |
| CLUSTER_DEAD_THRESHOLD | 3 | Missed heartbeats before a server is marked dead |
| CLUSTER_LEADER_GRACE | 5 | Missed heartbeats before the leader is replaced (at least CLUSTER_DEAD_THRESHOLD) |
| CLUSTER_UPGRADE_WINDOW | 5m | During a rolling upgrade, how long after a newer server takes over as leader the cluster counts as upgrading |
| CLUSTER_DEAD_NODE_TTL | 24h | When servers that left or died drop off the list |
| CLUSTER_EVENT_RETENTION_DAYS | 7 | Days of cluster events kept |
| READ_CACHE_ENABLED | true | Per-server cache of spaces, repositories, roles and settings; false reads the database every time. See Read cache |
| READ_CACHE_CHECK_INTERVAL | 1s | How often a server checks for changes it may have missed (up to 1m) |
| READ_CACHE_MAX_AGE | 5m | Longest a server uses something it read (1s–1h) |
| READ_CACHE_MAX_ENTRIES | 20000 | Items kept per kind of lookup |
Redis, storage and the license are not environment variables: they're entered in the setup wizard (or setup file), stored encrypted, and changed in Settings or on the recovery page.
8. Logging, audit and metrics
| Variable | Default | Meaning |
|---|---|---|
| LOG_LEVEL | info | debug, info, warn, error, fatal; change it live in Settings → Logging |
| LOG_LEVEL_<PACKAGE> | unset | Level for one area, such as LOG_LEVEL_AUTH=debug |
| LOG_CALLER | false | Add the source file and line to each entry |
| LOG_SAMPLE_RATE | 0 | Log 1 in N entries (0: all) |
| LOG_REDACT_ENABLED | true | Remove secrets from log lines |
| LOG_FILE_ENABLED | true | Write this server's log files |
| LOG_FILE_DIR | ./data/logs | Where (per server; levels, pattern and rotation in Settings → Logging) |
| AUDIT_LOG_RETENTION_DAYS | 90 | Days of audit log kept |
| AUDIT_LOG_RETENTION_SCHEDULE | 20 3 * * * | When old audit entries are deleted |
| METRICS_ADDR | off | A separate listener (host:port, not PORT) serving GET /metrics without authentication: bind it to a private interface. See Monitoring |
| METRICS_TOKEN | off | Also serve /metrics on the main port to Authorization: Bearer <token> (at least 16 characters) |
| SYSTEM_CHECK_INTERVAL | 1h | How often each server runs its system check |
9. Scheduler and retention
| Variable | Default | Meaning |
|---|---|---|
| SCHEDULER_HEARTBEAT_INTERVAL | 30s | Scheduler heartbeat |
| SCHEDULER_LOCK_TTL | 5m | How long a job's lock lasts without renewal |
| SCHEDULER_CHECK_TICKER_INTERVAL | 10s | How often due jobs are looked for |
| SCHEDULER_RETRY_BASE_DELAY, SCHEDULER_RETRY_MAX_DELAY | 30s, 5m | Retry back-off of failed jobs |
| SCHEDULER_UNHEALTHY_THRESHOLD | 3 | Failures in a row before a job is reported unhealthy |
| SCHEDULER_SHUTDOWN_GRACE_PERIOD | 30s | Time running jobs get to finish on shutdown |
| SCHEDULER_RUN_HISTORY_RETENTION_DAYS, SCHEDULER_RUN_HISTORY_MIN_RUNS_PER_JOB | 30, 50 | Job run history kept |
| ALERT_CLEANUP_SCHEDULE | 0 2 * * * | When old alerts are removed |
| ALERT_RETENTION_ACTIVE_DAYS, …_READ_DAYS, …_CLEARED_DAYS, …_SUPERSEDED_DAYS | 30, 7, 1, 3 | Days alerts are kept, by state |
| MAIL_DISPATCH_INTERVAL, MAIL_CLEANUP_SCHEDULE | 10s, 30 4 * * * | Email queue dispatch and cleanup |
| DIRECTORY_SYNC_CHECK_INTERVAL, DIRECTORY_SYNC_RUN_CLEANUP_SCHEDULE | 1m, 40 4 * * * | Directory sync scheduling |
| PAGINATION_DEFAULT_LIMIT, PAGINATION_MAX_LIMIT | 20, 100 | API page sizes |
| PAGINATION_CURSOR_SECRET | unset (cursors not signed) | Key that signs paging cursors so clients can't forge them. Recommended in production; the same on every server |
Most scheduled jobs' times and retention are changed in Settings → Advanced → Scheduled jobs instead (see Scheduled Jobs).
10. Events, policies and automation
| Variable | Default | Meaning |
|---|---|---|
| EVENT_DISPATCH_INTERVAL, EVENT_DISPATCH_BATCH, EVENT_DISPATCH_CONCURRENCY | 5s, 100, 4 | Delivery of durable events |
| EVENT_DELIVERY_LEASE, EVENT_SUBSCRIBER_TIMEOUT | 2m, 30s | How long a delivery is held and may take |
| EVENT_MAX_ATTEMPTS, EVENT_RETRY_BASE_DELAY, EVENT_RETRY_MAX_DELAY | 8, 5s, 1h | Retries of failed deliveries |
| EVENT_OUTBOX_RETENTION_DAYS, EVENT_DEAD_RETENTION_DAYS, EVENT_OUTBOX_CLEANUP_SCHEDULE | 7, 30, 15 4 * * * | Retention of delivered and failed events |
| INDEX_EVENTS_PRUNE_SCHEDULE | 25 * * * * | When search index changes older than a day are pruned |
| POLICY_CACHE_TTL, POLICY_EVAL_BUDGET, POLICY_COST_LIMIT | 10s, 50ms, 10000 | Policy caching and evaluation limits |
| POLICY_DECISION_RETENTION_DAYS, POLICY_DECISION_CLEANUP_SCHEDULE | 30, 45 4 * * * | Policy decision history |
| POLICY_SCAN_SCHEDULE, POLICY_SCAN_MAX_ITEMS | 30 3 * * *, 10000 | Nightly compliance scan |
| AUTOMATION_MAX_DEPTH | 3 | Automated reactions in a row before rules stop running (loop protection) |
| AUTOMATION_CACHE_TTL, AUTOMATION_COST_LIMIT | 10s, 10000 | Rule caching and condition cost |
| AUTOMATION_WEBHOOK_TIMEOUT | 10s | Timeout per webhook call |
| AUTOMATION_WEBHOOK_ALLOW_PRIVATE, AUTOMATION_WEBHOOK_ALLOW_HTTP | false | Allow webhooks to private addresses, or plain http |
| AUTOMATION_RUN_RETENTION_DAYS, AUTOMATION_RUN_CLEANUP_SCHEDULE | 30, 50 4 * * * | Rule run history |
11. Plugins and AI agents
| Variable | Default | Meaning |
|---|---|---|
| PLUGIN_SIGNING_REQUIRED | true | Refuse plugins not signed by a trusted key (false: install them flagged untrusted) |
| PLUGIN_TRUST_STORE_PATH | /etc/app/certs/plugins/ | Directory of Ed25519 public keys trusted for plugin signatures, besides those added in Settings |
| PLUGIN_MAX_PACKAGE_SIZE | 20971520 (20 MiB) | Largest plugin package |
| PLUGIN_MAX_MEMORY, PLUGIN_INSTANCES | 64 MiB, 2 | Memory per plugin instance; instances per plugin per server |
| PLUGIN_MAX_CONCURRENT, PLUGIN_TOOL_CONCURRENCY | half the CPUs, half of that | Plugin calls and MCP tool calls at once per server |
| PLUGIN_EXEC_TIMEOUT, PLUGIN_TOOL_TIMEOUT | 30s, 10s | Time per after-event call, per MCP tool call |
| PLUGIN_PREHOOK_TIMEOUT, PLUGIN_POSTHOOK_TIMEOUT | 5s, 30s | Time per blocking and non-blocking event subscriber |
| PLUGIN_BREAKER_FAILURES, PLUGIN_BREAKER_COOLDOWN | 5, 60s | Failures in a row before a plugin is paused on a server, and for how long |
| PLUGIN_MAX_CALLS_PER_SECOND, PLUGIN_MAX_HOST_CALLS, PLUGIN_CALLER_SHARE_PCT | 100, 1000, 50 | Call limits |
| PLUGIN_DATABASE_URL | the main database | Put plugin schemas on another PostgreSQL database (its role needs CREATEROLE and CREATE) |
| PLUGIN_DB_MAX_QUOTA, PLUGIN_DB_STATEMENT_TIMEOUT, PLUGIN_DB_MAX_CONNECTIONS, PLUGIN_DB_MAX_ROWS | 1 GiB, 5s, 4, 1000 | Caps for plugin databases |
| PLUGIN_KV_MAX_KEYS, PLUGIN_KV_MAX_VALUE, PLUGIN_KV_MAX_TTL | 100000, 256 KiB, 168h | Caps for plugin key-value stores |
| PLUGIN_EGRESS, PLUGIN_EGRESS_PROXY | true, none | Plugin outbound HTTP on or off; an HTTP proxy for it |
| PLUGIN_HTTP_ALLOW_HTTP, PLUGIN_HTTP_ALLOW_PRIVATE | false | Allow plain http and private addresses (development only) |
| PLUGIN_HTTP_TIMEOUT, PLUGIN_HTTP_MAX_RESPONSE | 10s, 2 MiB | Plugin outbound request limits |
| PLUGIN_DATA_CHECK_INTERVAL, PLUGIN_CACHE_TTL | 5m, 10s | Plugin storage checks; how long a server uses its plugin list without Redis |
| MCP_RATE_LIMIT | 120 | MCP requests per minute per credential (until saved in Settings → Security → Rate limits) |
| MCP_KEY_MAX_DAYS, MCP_KEY_DEFAULT_DAYS | 90, 30 | Longest and proposed lifetime of MCP keys |
| PLUGIN_DOWNLOAD_LINK_TTL | 5m | Lifetime of download links AI tools hand out |
12. Repositories and formats
| Variable | Default | Meaning |
|---|---|---|
| REPOSITORY_MAX_ARTIFACT_SIZE | 10 GiB | Largest artifact (1 MiB–1 TiB), until saved in Settings → Repositories |
| SPACE_DEFAULT_QUOTA, SPACE_DEFAULT_QUOTA_WARN_PERCENT | 50 GB, 80 | Quota a new space gets, and its warning threshold |
| REMOTE_CONNECT_TIMEOUT, REMOTE_READ_TIMEOUT, REMOTE_RETRIES | 10s, 60s, 2 | Calls to upstream registries |
| PROXY_STRICT_CHECKSUMS | true | Default of Settings → Security → Proxy checksums |
| ARTIFACT_BLOB_GC_GRACE, ARTIFACT_UPLOAD_TEMP_TTL, ARTIFACT_DOWNLOAD_FLUSH_INTERVAL | 1h, 24h, 5s | Unused content clean-up, abandoned uploads, download counters |
| BLOCKLIST_REFRESH_INTERVAL, BLOCKLIST_EVENT_INTERVAL | 5s, 10m | Block list refresh on other servers; how often repeated refusals raise an event |
| GROUP_MERGE_CONCURRENCY, GROUP_MERGE_MAX_BYTES, GROUP_MERGE_CACHE_BYTES | 16, 256 MiB, 64 MiB | Repository groups merging members' answers |
| WEB_UPLOAD_MAX_FILES, WEB_UPLOAD_TEMP_DIR | 100, system temp | Uploads from the browser |
| DOCKER_GC_GRACE, DOCKER_UPLOAD_TTL, DOCKER_DEFAULT_PLATFORM | 24h, 24h, linux/amd64 | Docker |
| CARGO_MAX_CRATE_SIZE, CARGO_DOCS_MAX_SIZE, CARGO_DOCS_MAX_FILES, CARGO_DOCS_BUILD_LEASE, CARGO_DOCS_BUILD_ATTEMPTS | 10 MiB, 100 MiB, 50000, 10m, 3 | Cargo crates and docs builds |
| TERRAFORM_LINK_TTL | 10m | Terraform download links |
| HUGGINGFACE_REGULAR_MAX_SIZE, HUGGINGFACE_UPLOAD_LINK_TTL, HUGGINGFACE_GC_GRACE | 10 MiB, 2h, 24h | Hugging Face |
| GITLFS_LINK_TTL, GITLFS_BATCH_MAX_OBJECTS | 1h, 1000 | Git LFS |
| COMPOSER_MAX_ARCHIVE_SIZE | 100 MiB | Composer |
| RUBYGEMS_PUBLISH_LOCK_TTL, RUBYGEMS_LOG_CHECK_INTERVAL, RUBYGEMS_SYNC_WAIT, RUBYGEMS_SYNC_TIMEOUT, RUBYGEMS_GROUP_PROXY_INTERVAL, RUBYGEMS_GROUP_HOSTED_WAIT | 2m, 60s, 5s, 10m, 60s, 2s | RubyGems publishing, proxies and groups |
| CONAN_UPLOAD_TTL | 24h | Conan: how long an unfinished upload waits |
| VIBE_* | see Vibe artifacts | Vibe repositories: links, limits, push scan and the package list (Enterprise) |
13. Browse, SBOMs and scans
| Variable | Default | Meaning |
|---|---|---|
| INDEX_DIR | ./data/index | This server's search index (its own disk; rebuilt from the database when missing) |
| BROWSE_GUARD_MAX_METADATA, …_MAX_SBOM, …_MAX_ENVELOPE | 4 MiB, 32 MiB, 16 MiB | Largest metadata, SBOM and signature envelope read from an artifact; over a limit quarantines the version |
| BROWSE_GUARD_MAX_DEPTH, …_MAX_ELEMENTS, …_MAX_RATIO, …_TIMEOUT | 64, 2000000, 100, 10s | Parser limits against hostile files |
| BROWSE_GUARD_MAX_COMPONENTS, BROWSE_GUARD_MAX_DOC | 50000, 1 MiB | Components kept per SBOM; documentation text kept per file |
| IMAGE_SCAN_ENABLED | true | Catalog container images (and proxied conda packages) without an SBOM with Syft (Pro) |
| IMAGE_SCAN_TIMEOUT, IMAGE_SCAN_MAX_BYTES, IMAGE_SCAN_MAX_UNPACKED, IMAGE_SCAN_MAX_LAYERS, IMAGE_SCAN_MAX_PLATFORMS | 10m, 4 GiB, 16 GiB, 128, 4 | Scan limits; larger images are skipped |
| IMAGE_SCAN_TMP_DIR | system temp | Where images are unpacked: needs room for the largest image expanded |
| VULN_ARCHIVE_MAX_BYTES | 2 GiB | Largest offline vulnerability archive (Settings → Vulnerability data) |
14. Backups
| Variable | Default | Meaning |
|---|---|---|
| BACKUP_SCHEDULE, BACKUP_CLEANUP_SCHEDULE, BACKUP_TEST_RESTORE_SCHEDULE | 0 2 * * *, 0 3 * * *, 0 4 * * 0 | Default schedules (changed in Settings → Scheduler) |
| BACKUP_RETENTION_DAYS | 7 | Days a backup is kept |
| BACKUP_MAX_DURATION | 6h | Longest a backup may run |
| BACKUP_FILES_MAX_BYTES | 10 GiB | Most platform files (avatars, branding, plugin packages) one backup copies |
| BACKUP_PG_DUMP, BACKUP_PG_RESTORE | on the PATH (18 in the image) | The PostgreSQL tools to use |
| BACKUP_TEMP_DIR | system temp | Where the dump is staged; needs room for it |
| BACKUP_RESTORE_KEEP_PRIOR | 24h | How long the database a restore replaced is kept |
| BACKUP_UPLOAD_CHUNK_SIZE, BACKUP_UPLOAD_EXPIRY | 16 MiB, 24h | Uploads of backup files |
See Backups for what each does.