Skip to main content

Environment Variables

This page lists every environment variable the application, its workers, and its build read, with the default that applies when the variable is unset. Variables marked required have no usable default. Variables marked build-time are baked into the Next.js build and take effect only after the prod image is rebuilt, not after a restart.

The testplanit/.env.example file in the repository carries the same variables with commented examples. Setup pages describe how each area fits together; this page is the reference.

Core​

VariableDefaultDescription
DATABASE_URLrequiredPostgreSQL connection string, including ?schema=public.
NEXTAUTH_URLrequiredThe public URL of the application. Also forms the OAuth callback URL that issue-tracker integrations register with their providers: ${NEXTAUTH_URL}/api/integrations/oauth/<provider>/callback.
NEXTAUTH_SECRETrequiredSession signing secret. Generate with openssl rand -base64 32.
ENCRYPTION_KEYrequiredKey for encrypting stored secrets such as integration credentials and two-factor seeds. Generate with openssl rand -hex 32. Changing it makes existing encrypted values unreadable.
VALKEY_URLrequiredValkey or Redis connection string, used for job queues, caches, rate limits, and real-time notifications.
INTERNAL_APP_URLsee descriptionAddress the server uses to call its own routes, such as when opening a shared report. Defaults to the address the server listens on (HOSTNAME:PORT in the Docker image), falling back to NEXTAUTH_URL. Set it only if neither is reachable from the server.

Database​

See External Database Deployment and Horizontal Read Scaling.

VariableDefaultDescription
DIRECT_DATABASE_URLDATABASE_URLA connection that bypasses a transaction-mode pooler such as pgbouncer. Schema sync, index creation, and audit-trigger setup use it. Required when DATABASE_URL points at a pooler.
DATABASE_POOL_MAX20Client-side connection pool size per process. One pool per replica; keep the total under the server's max_connections.
DATABASE_POOL_CONNECTION_TIMEOUT_MS10000How long a query waits for a free pool slot before failing. 0 waits without limit.
DATABASE_POOL_IDLE_TIMEOUT_MS10000How long an unused connection stays open before it is closed.
DATABASE_STATEMENT_TIMEOUT_MSunsetServer-side per-statement deadline. Set it on the web process only; workers run long statements legitimately.
DATABASE_REPLICA_URLSunsetComma-separated read-replica connection strings. Reads spread across them; writes and transactions stay on DATABASE_URL.
DATABASE_PRIMARY_STICKY_MS5000After a write, how long a user's reads stay on the primary so they see their own changes. 0 disables.
AUDIT_TRIGGER_BOOTSTRAPonSet to off to skip installing the audit triggers at startup, for example when the database role cannot run DDL.
AUDIT_TRIGGER_BOOTSTRAP_FATALunsetSet to 1 to abort startup when the audit triggers cannot be installed. Recommended on the worker tier. The default logs the failure and continues.
CREDENTIAL_ENCRYPTION_BOOTSTRAPunsetSet to off to skip the startup pass that encrypts code repository credentials saved before they were encrypted at rest.

Valkey and Job Queues​

VariableDefaultDescription
VALKEY_SENTINELSunsetComma-separated host:port list. When set, the app connects through Sentinel instead of VALKEY_URL directly; the password in VALKEY_URL still authenticates to the master.
VALKEY_SENTINEL_MASTERmymasterSentinel master name.
VALKEY_SENTINEL_PASSWORDunsetPassword for the Sentinel nodes themselves.
BULLMQ_PREFIXbullKey prefix for all job queues. Worker-group deployments set bull-<group> so each group works on its own keyspace. Letters, digits, _ and - only. The app and the workers serving it must use the same value.
SKIP_VALKEY_CONNECTIONunsetSet to true to skip connecting to Valkey. Used during builds.

See Search Configuration.

VariableDefaultDescription
ELASTICSEARCH_NODEunsetElasticsearch URL. Leave unset to disable search-backed features; keyword features fall back to the database where they can.

File Storage​

See File Storage.

VariableDefaultDescription
AWS_ACCESS_KEY_IDsee noteAccess key for S3 or S3-compatible storage (such as the bundled RustFS). Required for S3-compatible storage; optional on AWS.
AWS_SECRET_ACCESS_KEYsee noteSecret key for S3 or S3-compatible storage (such as the bundled RustFS). Required for S3-compatible storage; optional on AWS.
AWS_REGIONrequiredBucket region. AWS_BUCKET_REGION is accepted as a legacy alias.
AWS_BUCKET_NAMErequiredBucket name.
AWS_ENDPOINT_URLunsetStorage endpoint the server talks to. Leave unset for AWS S3; set to the storage service URL for S3-compatible storage (http://minio:9000 for the bundled RustFS).
AWS_PUBLIC_ENDPOINT_URLunsetBrowser-reachable storage URL for presigned links when S3-compatible storage sits behind a proxy. When unset on a hosted instance, files are served through the application instead.
MINIO_INTERNAL_ENDPOINTunsetBuild-time. An extra internal storage host to allow in the image optimizer.
UPLOAD_MAX_MB10Build-time. Per-file upload ceiling for attachments and inline images. Raise the bundled nginx limit to match.
IS_HOSTEDfalseRead it as "storage is not publicly readable". With no AWS_PUBLIC_ENDPOINT_URL this switches uploads to proxy mode and serves files through /api/storage. Required for a private S3 bucket, despite the name — see File Storage.
SELF_HOSTEDunsetBuild-time. Set to true for self-hosted images to turn off the Next.js image optimizer, so one image runs on any host without a baked-in domain allowlist.
BASE_DOMAINunsetBuild-time. Multi-tenant base domain; *.BASE_DOMAIN storage URLs are allowed in the image optimizer.
NEXT_PUBLIC_APP_URL, APP_URLunsetBuild-time. Fallback public URL for the image optimizer allowlist when AWS_PUBLIC_ENDPOINT_URL is unset.
Credentials are optional on AWS

Leave both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY unset and the AWS SDK falls back to its default provider chain — an EC2 instance role, EKS IRSA, an ECS task role, SSO, or the shared config file — so no long-lived keys sit on disk. Set both to use static credentials.

Setting only one is treated as setting neither. RustFS and other S3-compatible services accept static keys only, so those deployments must always set both.

Authentication​

Single sign-on with SAML and OAuth2 providers is configured in Administration → Authentication, not with environment variables. The variables below cover the built-in social providers and the secrets behind tokens.

VariableDefaultDescription
PASSWORDLESS_DEVICE_BOUNDtrueMagic-link sign-in completes only in the browser that requested it. Set to false for a plain clickable link.
SIGNIN_ADMIN_CONTACTtrueShows the "Trouble signing in?" line on the sign-in page, linked to the first active admin's email. Set to false to remove it and hide the address.
API_TOKEN_SECRETNEXTAUTH_SECRETHMAC secret for hashing API tokens. Changing it invalidates every existing token.
TWO_FACTOR_ENCRYPTION_KEYNEXTAUTH_SECRETLegacy key used only to read two-factor secrets written before ENCRYPTION_KEY took over.
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRETunsetEnables the Google sign-in button when both are set.
AZURE_AD_CLIENT_ID, AZURE_AD_CLIENT_SECRETunsetEnables the Microsoft Entra ID sign-in button when both are set.
AZURE_AD_TENANT_IDcommonEntra ID tenant for the button above.
APPLE_CLIENT_ID, APPLE_TEAM_ID, APPLE_KEY_ID, APPLE_PRIVATE_KEYunsetEnables the Apple sign-in button when all four are set. Newlines in the private key may be written as \n.
JIRA_CLIENT_ID, JIRA_CLIENT_SECRET, JIRA_REDIRECT_URIunsetLegacy global Jira OAuth credentials, consulted only when an integration has none of its own. New installs configure these per integration in the admin UI.
DISABLE_SCIM_RATE_LIMITfalseSet to true to disable the per-token SCIM request limit. Development only.

Email​

VariableDefaultDescription
EMAIL_SERVER_HOSTunsetSMTP host. Email features are off while unset.
EMAIL_SERVER_PORT587SMTP port.
EMAIL_SERVER_USER, EMAIL_SERVER_PASSWORDunsetSMTP credentials.
EMAIL_FROMunsetSender address for all outgoing mail.

API Rate Limiting​

See API Tokens.

VariableDefaultDescription
TIERprofessionalPreset hourly limit on authenticated API requests per instance: essentials 1,000, team 5,000, professional 10,000, dedicated 25,000.
API_RATE_LIMITunsetExplicit hourly limit. Overrides TIER.
DISABLE_API_RATE_LIMITfalseSet to true to turn rate limiting off. Use for load testing — Do not use in Production.
VariableDefaultDescription
ALLOWED_PRIVATE_HOSTSunsetComma-separated private or internal hostnames that outbound requests may reach: LLM endpoints, self-hosted git and issue trackers, and URL-based test generation. Private addresses are otherwise blocked.
WEBHOOK_OUTBOUND_ALLOW_HTTPfalseSet to true to let outbound webhooks target plain http:// URLs. Exists for test harnesses; never set it in production.
LINK_PREVIEW_MODEsafeWhat unauthenticated link previews show. safe shows the record kind only; names also shows the record and project name.
CRAWL_SCREENSHOTSfalseSet to true to capture a screenshot per page during URL-based test generation and offer it to vision-capable models. The official workers image enables this.
CHROMIUM_EXECUTABLE_PATHunsetChromium binary used for screenshots. The official workers image sets it.

Real-Time Notifications​

See SSE Notifications.

VariableDefaultDescription
SSE_PER_TENANT_CAP1000Open notification streams allowed per tenant.
SSE_PER_USER_CAP4Open notification streams allowed per user.
SSE_ISSUES_PER_TENANT_CAP1000Open issue-sync streams allowed per tenant.
SSE_ISSUES_PER_USER_CAP8Open issue-sync streams allowed per user.

Workers​

See Background Processes. Each variable sets how many jobs the named worker processes at once.

VariableDefaultWorker
TESTMO_IMPORT_CONCURRENCY1Testmo import
SYNC_CONCURRENCY2Issue sync
EMAIL_CONCURRENCY3Email
NOTIFICATION_CONCURRENCY5Notifications
FORECAST_CONCURRENCY5Forecast
ELASTICSEARCH_REINDEX_CONCURRENCY2Search reindex
AUDIT_LOG_CONCURRENCY10Audit log
BUDGET_ALERT_CONCURRENCY2AI budget alerts
AUTO_TAG_CONCURRENCY3Auto-tag
DERIVE_CASE_STEPS_CONCURRENCY2Derive case steps
WEBHOOK_DISPATCH_CONCURRENCY5Webhook dispatch
EXECUTION_DISPATCH_CONCURRENCY3Automated execution dispatch
IMPACT_ANALYSIS_CONCURRENCY1Impact Analysis

The repo cache, copy/move, duplicate scan, Magic Select, and step scan workers always process one job at a time. The matching *_CONCURRENCY variables for them only change the value shown on the Job Queues page.

Memory ceilings, applied by the process manager in the workers image. Each worker restarts when its resident size passes its ceiling, and its Node heap defaults to 75% of that ceiling, so setting a ceiling alone is enough. Set a *_MAX_OLD_SPACE_MB value only to choose the heap yourself.

WORKER_* raises every worker whose default ceiling is 512M. Workers with higher defaults keep them. A worker-specific variable takes precedence over WORKER_*, and a heap set in WORKER_MAX_OLD_SPACE_MB is ignored for a worker whose own ceiling is set. A heap must be smaller than its ceiling; one that is not is ignored, and the 75% default applies.

VariableDefaultDescription
WORKER_MAX_MEMORY_RESTART512MRestart each 512M-tier worker above this resident size.
WORKER_MAX_OLD_SPACE_MB75% of the ceilingNode heap for each 512M-tier worker.
TESTMO_IMPORT_MAX_MEMORY_RESTART4GRestart the Testmo import worker above this resident size.
TESTMO_IMPORT_MAX_OLD_SPACE_MB75% of the ceilingNode heap for the Testmo import worker.
ELASTICSEARCH_REINDEX_MAX_MEMORY_RESTART2GRestart the reindex worker above this resident size.
ELASTICSEARCH_REINDEX_MAX_OLD_SPACE_MB75% of the ceilingNode heap for the reindex worker.
REPO_CACHE_MAX_MEMORY_RESTART512MRestart the repo cache worker above this resident size. Raise it for very large repositories.
REPO_CACHE_MAX_OLD_SPACE_MB75% of the ceilingNode heap for the repo cache worker.

Testmo Import​

See Import from Testmo. Chunk sizes are rows per batch write.

VariableDefault
TESTMO_IMPORT_TRANSACTION_TIMEOUT_MS900000 (15 minutes)
TESTMO_AUTOMATION_TRANSACTION_TIMEOUT_MS2700000 (45 minutes)
TESTMO_REPOSITORY_CASE_CHUNK_SIZE500
TESTMO_TEST_RUN_CASE_CHUNK_SIZE500
TESTMO_TEST_RUN_RESULT_CHUNK_SIZE2000
TESTMO_ISSUE_RELATIONSHIP_CHUNK_SIZE1000
TESTMO_AUTOMATION_CASE_CHUNK_SIZE500
TESTMO_AUTOMATION_RUN_CHUNK_SIZE500
TESTMO_AUTOMATION_RUN_TEST_CHUNK_SIZE2000
TESTMO_AUTOMATION_RUN_FIELD_CHUNK_SIZE500
TESTMO_AUTOMATION_RUN_LINK_CHUNK_SIZE500
TESTMO_AUTOMATION_RUN_TEST_FIELD_CHUNK_SIZE500
TESTMO_AUTOMATION_RUN_TAG_CHUNK_SIZE500

Parameterized Test Runs​

VariableDefaultDescription
PARAMETERIZED_RUN_HARD_CAP5000Run creation refuses more total iterations than this.
PARAMETERIZED_RUN_SOFT_CAP1000Above this many iterations, creation asks for confirmation.
PARAMETERIZED_RUN_ASYNC_CAP500Above this many iterations, the run is built by a background job.

Frozen Reports​

See Live and Frozen Data.

VariableDefaultDescription
REPORT_SNAPSHOT_MAX_ROWS10000Most rows a frozen report keeps. A larger report can still be frozen after a warning, keeping the first rows.

Magic Select​

See Magic Select.

VariableDefaultDescription
MAGIC_SELECT_TRUNCATE_CASE_NAME80Characters of each case name sent to the model.
MAGIC_SELECT_TRUNCATE_TEXT_LONG100Characters of each long text field sent to the model.
MAGIC_SELECT_TRUNCATE_OTHER_FIELD100Characters of other fields sent to the model.
MAGIC_SELECT_TRUNCATE_ISSUE_DESC250Characters of each linked issue description sent to the model.
MAGIC_SELECT_SEARCH_THRESHOLD250Case count above which search pre-filters the candidates.
MAGIC_SELECT_MIN_KEYWORD_LENGTH3Shortest keyword used for search pre-filtering.
MAGIC_SELECT_MIN_SEARCH_SCORE50.0Lowest search score kept as a candidate.
MAGIC_SELECT_MAX_SEARCH_RESULTS2000Most candidates taken from search.

Impact Analysis​

See Test Impact Analysis.

VariableDefaultDescription
IMPACT_DIFF_TOKEN_BUDGET12000Tokens of diff sent to the model per analysis.
IMPACT_TRUNCATE_PATCH_CHARS4000Characters of each file's patch kept in the prompt.
IMPACT_MAX_PATCH_FILES40Files whose patch text is included; the rest are summarized by path.
IMPACT_MAX_DIFF_FILES500Most changed files read from the provider.
IMPACT_TRUNCATE_CASE_NAME80Characters of each case name sent to the model.
IMPACT_TRUNCATE_TEXT_LONG100Characters of each long text field sent to the model.
IMPACT_TRUNCATE_OTHER_FIELD100Characters of other fields sent to the model.
IMPACT_AI_FULL_REPO_THRESHOLD250Case count up to which every case is an AI candidate.
IMPACT_MAX_AI_CANDIDATES150Most cases the model ranks, strongest signal first. Cases a pin or another signal already settles are not sent.
IMPACT_AI_SAMPLE_SIZE50Most folder neighbours added under the cap in large repositories.
IMPACT_MIN_SEARCH_SCORE5Lowest keyword-search score kept.
IMPACT_SEARCH_RELATIVE_CUTOFF0.1Keyword hits scoring under this fraction of the top hit are dropped (0 to 1).
IMPACT_MAX_SEARCH_RESULTS500Most keyword-search hits kept.
IMPACT_BM25_SATURATION20Search score at which the keyword signal reaches its cap.
IMPACT_MIN_SCORE20Lowest score a case needs to appear at all. Pinned cases always appear.
IMPACT_AFFECTED_THRESHOLD50Score at which a case moves from the related to the affected tier.
IMPACT_HISTORY_LOOKBACK_DAYS365How far back earlier analyses count as history.
IMPACT_HISTORY_MAX_ANALYSES25Most earlier analyses consulted.
IMPACT_MAX_ANCHOR_FETCHES50Pinned files fetched at the base commit to relocate line and symbol pins.
IMPACT_THINKING_BUDGET1024Thinking tokens allowed to models that support it.
IMPACT_LINKED_EXPANSIONtrueAlso select cases linked to strongly selected cases.
IMPACT_REUSE_HOURS24Reuse a completed analysis of the same commits within this window.
IMPACT_ISSUE_MAX_COMMIT_FETCHES25Commits naming a ticket whose own file list is read per analysis.
IMPACT_ISSUE_SCAN_LOOKBACK_DAYS90How far back the ticket scan reads commits on each cache refresh.
IMPACT_ISSUE_SCAN_MAX_COMMITS300Most commits the ticket scan reads.
IMPACT_ISSUE_SCAN_MAX_COMMIT_FETCHES100Ticket commits whose file list the scan reads per refresh.
IMPACT_ISSUE_SCAN_MAX_FILES_PER_COMMIT50A ticket commit touching more files than this is skipped.
IMPACT_ISSUE_SCAN_FULL_MAX_COMMITS20000Commits a manual full-history ticket scan reads from the repository per run; running it again continues from where the last run stopped.
IMPACT_ISSUE_SCAN_FULL_MAX_COMMIT_FETCHES2000Matched commits whose file lists a full-history scan reads.
IMPACT_ISSUE_IMPORT_MAX_LOOKUPS100Tracker lookups a refresh-time ticket scan may make to import unknown tickets.
IMPACT_ISSUE_IMPORT_FULL_MAX_LOOKUPS5000Tracker lookups a full-history ticket scan may make to import unknown tickets.
IMPACT_ISSUE_SCAN_SYMBOL_PINStrueTicket scans read each commit's diff and pin the changed functions or classes; false pins whole files only (cheaper on providers without a server-side diff).

Multi-Tenant Deployments​

See Multi-Tenant Workers.

VariableDefaultDescription
MULTI_TENANT_MODEfalseSet to true to serve several tenants from one worker process, each with its own database.
INSTANCE_TENANT_IDdefaultPins an application pod to one tenant.
TENANT_CONFIG_FILE/config/tenants.jsonJSON file of tenant configurations. Re-read when it changes.
TENANT_CONFIGSunsetJSON object of tenant configurations keyed by tenant id, with databaseUrl, replicaUrls, elasticsearchNode, elasticsearchIndex, and baseUrl. Overrides the file.
TENANT_<ID>_DATABASE_URLunsetPer-tenant database, as an alternative to the file or JSON. Companions: TENANT_<ID>_DATABASE_REPLICA_URLS, TENANT_<ID>_ELASTICSEARCH_NODE, TENANT_<ID>_ELASTICSEARCH_INDEX, TENANT_<ID>_BASE_URL.
TENANT_SECRETS_NAMESPACEpod namespaceKubernetes namespace holding per-tenant secrets.
TENANT_SECRET_NAME_TEMPLATEtpi-{tenant}-envName of each tenant's Kubernetes secret; {tenant} is replaced by the tenant id.
TENANT_SECRETS_CACHE_TTL_MS600000How long a tenant secret is cached before it is read again.
KUBERNETES_SERVICE_HOST, KUBERNETES_SERVICE_PORTkubernetes.default.svc, 443API server used to read tenant secrets. Kubernetes sets these in every pod.

Trial Instances​

VariableDefaultDescription
IS_TRIAL_INSTANCEfalseMarks a time-limited trial.
TRIAL_END_DATEunsetWhen the trial ends.
FEEDBACK_SURVEY_URLunsetSurvey link shown to trial users.
NEXT_PUBLIC_CONTACT_EMAIL[email protected]Contact shown when a trial has expired.
NEXT_PUBLIC_WEBSITE_URLhttps://testplanit.comWebsite link shown when a trial has expired.

Build-Time Variables​

These are read while the application is built. The release pipeline sets the version variables; operators building their own image may set the others.

VariableDefaultDescription
NEXT_PUBLIC_APP_VERSION, NEXT_PUBLIC_GIT_COMMIT, NEXT_PUBLIC_GIT_BRANCH, NEXT_PUBLIC_GIT_TAG, NEXT_PUBLIC_BUILD_DATEgeneratedVersion information shown in the application. Written by the build script.
NEXT_PUBLIC_FORCE_RTLunsetSet to true to render every locale right-to-left, for checking the mirrored layout.
DOCKER_BUILDunsetSet to true inside the image build to skip the local build cache.
CIunsetSet by CI runners; also skips the local build cache.
SELF_HOSTED, BASE_DOMAIN, UPLOAD_MAX_MB, MINIO_INTERNAL_ENDPOINT, NEXT_PUBLIC_APP_URLsee File StorageStorage and image optimizer settings that are also build-time.

Seeding, Development, and Testing​

VariableDefaultDescription
ADMIN_EMAIL, ADMIN_NAME, ADMIN_PASSWORDunsetThe first administrator account, created when the database is seeded.
TEST_REGULAR_USER_PASSWORDunsetPassword for the seeded non-admin user in test environments.
TEST_EMAIL_DOMAINexample.comDomain for generated E2E test user addresses.
E2E_PRODunsetSet to on to run E2E tests against a production build. See E2E Testing.
RUN_DB_INTEGRATIONunsetSet to 1 to run the live-database integration tests.
TEST_VALKEY_URLunsetValkey used by tests that need a real instance.
DEBUG_FORECASTunsetAny value turns on verbose forecast logging.

Docker Compose​

The DOCKER_*_PORT variables, POSTGRES_*, and resource limits are consumed by the compose files rather than the application. See Docker Setup.