Open Inventory docs

Environment variable reference

Application settings, defaults, secrets, dependencies and build-time configuration for self-hosted Open Inventory.

This reference covers all 155 entries in the application's .env.example, plus relevant runtime and compatibility settings. It was checked against the repository configuration and readers on 1 November 2026. Older deployed images may not support every setting, including the recently added branding options.

These variables belong to your Open Inventory application, not to this documentation website. See Configure your instance for a short introduction and the example environment file for a starting point.

Reading this reference

  • Default means the behavior when the variable is absent, not necessarily the value supplied by .env.example or a deployment template. Differences are called out below.
  • Required means required by the production startup script. Conditional means required only for the named feature. Other settings are optional.
  • Secret marks credentials or sensitive configuration. Do not commit their real values or expose them through NEXT_PUBLIC_ variables. An unmarked value may still contain private infrastructure information.
  • Unless a section says Build, Compose or Tool, settings are Runtime settings. Restart the application process after changing them; recreate containers to load a changed container environment. Some settings are initialized only at startup.
  • Use true or false for booleans. Numeric timeouts are milliseconds unless the name or table explicitly says seconds, minutes, hours or days. Limits described as clamped are restricted to the stated range.
  • An empty string is not universally equivalent to an absent variable: numeric readers can interpret it as zero. Omit optional numeric overrides to retain their defaults, or provide an explicit valid number.

Load settings and apply changes

For local development, put values in .env.local in the application repository root and restart npm run dev. Next.js prioritizes the process environment, then environment-specific local files, .env.local, environment-specific files and .env. .env.local is excluded in test mode.

For Docker Compose, .env supplies values for Compose interpolation. It does not automatically pass every variable into the container. Verify that the application service forwards the setting under environment, or add a mapping:

services:
  app:
    environment:
      APP_NAME: ${APP_NAME:-}
      APP_LOGO_URL: ${APP_LOGO_URL:-}

The root Compose service is named app; the Dokploy and Coolify templates use inventory. The templates forward different subsets of settings. In particular, a setting described here may require an additional mapping in an older or custom deployment definition.

After runtime changes, recreate the application using the same Compose files used to deploy it. For the repository's local port override:

docker compose -f docker-compose.yml -f docker-compose.local.yml up -d --force-recreate app

In Dokploy or Coolify, save the environment and Compose mappings, then redeploy. docker restart alone does not change the container's environment. Build-time map settings require a new application build; see Maps.

Keep bcrypt hashes in single quotes in Compose .env files so their dollar signs are preserved. Base64 is an encoding, not encryption.

Core application and branding

All settings in this table are Runtime.

VariableDefaultFormat / requirementPurpose and notes
DATABASE_URLNone in productionPostgreSQL URL; Required, SecretUsed by the app and migrations. Accepts postgres: or postgresql:. Development fallback: postgresql://inventory:inventory@localhost:5432/inventory; do not use these example credentials in production.
AUTH_SECRETNone in productionRandom string, at least 32 characters; Required, SecretAuth.js session secret and fallback for some signed application tokens. Known example placeholders are rejected. Keep consistent across replicas.
AUTH_URLNone in productionAbsolute public URL; RequiredCanonical application address, for example https://inventory.example.com. Production startup requires HTTPS except for localhost. Also supplies default origins/hosts for several integrations.
AUTH_TRUST_HOSTDeployment templates set trueBooleanAuth.js host/proxy handling. Use a reverse proxy that controls forwarded host headers.
WEBSITE_URLRepository website linkHTTP(S) URLDestination of public website links from the application. The shell falls back to https://github.com/Utzel-Butzel/open-inventory-website.
APP_NAMEBuilt-in translated nameNon-empty textDisplay name in navigation, sign-in and browser metadata; applies to every organization. Whitespace-only values use the built-in name.
APP_LOGO_URLBuilt-in logoPublic HTTP(S) image URLNavigation and sign-in logo. URLs containing credentials are rejected; invalid or unavailable images use the built-in icon. Use HTTPS on HTTPS installations. Does not change the favicon.
NODE_ENVproduction in the containerproduction, development or testRuntime mode. Keep production for deployed containers.
PORT3000 in the containerPort numberPort of the standalone application server inside the container. If changed, update routing and healthchecks too.
HOSTNAME0.0.0.0 in the containerBind addressAddress on which the standalone server listens.
NEXT_TELEMETRY_DISABLED1 in the Dockerfile1 disables telemetryUsed during build and runtime to disable Next.js telemetry.

Branding examples · Production startup validation

Password login and bootstrap

Runtime. Bootstrap configuration creates the first database-backed administrator only while no users exist; it is not a password-reset mechanism for existing users. Prefer database-managed users after initialization.

VariableDefaultFormat / requirementPurpose and notes
AUTH_PASSWORD_ENABLEDtrueBooleanEnables password sign-in, including the native password-to-token endpoint. Configure and test another login method before disabling it.
BOOTSTRAP_ADMIN_EMAILSIMPLE_AUTH_EMAIL, then admin@inventory.localEmail addressFirst administrator's email, normalized to lowercase.
BOOTSTRAP_ADMIN_NAMESIMPLE_AUTH_NAME, then Inventory adminTextFirst administrator's display name.
BOOTSTRAP_ADMIN_PASSWORD_HASHSIMPLE_AUTH_PASSWORD_HASH, then unsetBcrypt hash; Conditional, SecretInitial administrator credential. Generate with npm run auth:hash -- "your password". Do not combine with BOOTSTRAP_ADMIN_PASSWORD.
BOOTSTRAP_ADMIN_PASSWORDUnsetAt least 12 characters; Conditional, SecretOne-time plaintext bootstrap input. Production accepts it only with BOOTSTRAP_ADMIN_PASSWORD_ONCE=true; startup hashes it before loading the app.
BOOTSTRAP_ADMIN_PASSWORD_ONCEfalseBooleanEnables one-time plaintext handling. After creating the admin, remove both plaintext bootstrap settings from the deployment and change the password in the app.
SIMPLE_AUTH_EMAILadmin@inventory.localEmail addressLegacy fallback for bootstrap email.
SIMPLE_AUTH_NAMEInventory adminTextLegacy fallback for bootstrap display name.
SIMPLE_AUTH_PASSWORD_HASHUnsetBcrypt hash; SecretLegacy fallback when the bootstrap hash is absent.
SIMPLE_AUTH_PASSWORDUnsetText; Secret; development onlyLegacy plaintext input. The production startup script rejects it.
NATIVE_TOKEN_TTL_DAYS30Integer, 1–365 daysLifetime of newly issued native login tokens. Invalid values fall back to 30.

The production entrypoint removes plaintext bootstrap values from the app process after hashing; it cannot remove them from the saved deployment environment. Remove them there yourself after initialization.

External sign-in

Runtime. These providers require pre-existing active application users and organization memberships; they do not replace application authorization. Supply a complete provider configuration. Partial configurations fail production startup. See Sign-in and access and the detailed provider guide.

Auth0

Register https://inventory.example.com/api/auth/callback/auth0, replacing the origin with your instance.

VariableDefaultFormat / requirementPurpose and notes
AUTH0_CLIENT_IDUnsetClient ID; ConditionalRequired to enable Auth0.
AUTH0_CLIENT_SECRETUnsetCredential; Conditional, SecretRequired to enable Auth0.
AUTH0_DOMAINUnsetTenant hostnameRequired unless an explicit issuer URL is supplied. Used to construct the HTTPS issuer.
AUTH0_ISSUER_BASE_URLDerived from AUTH0_DOMAINIssuer URLExplicit issuer override; takes precedence over the domain.

Generic OpenID Connect

Register /api/auth/callback/<provider-id> on your application origin. The provider must supply a verified email matching the existing user.

VariableDefaultFormat / requirementPurpose and notes
AUTH_OIDC_PROVIDER_IDoidc1–32 lowercase letters, digits or hyphens; starts with a letterCallback identifier. auth0, credentials, demo and local are reserved. Do not use supabase when the dedicated Supabase provider is also enabled.
AUTH_OIDC_PROVIDER_NAMEOpenID ConnectText, at most 64 charactersSign-in button label.
AUTH_OIDC_ISSUERUnsetIssuer URL; ConditionalRequired with client ID and secret. HTTPS except for localhost; no query or fragment.
AUTH_OIDC_CLIENT_IDUnsetClient ID; ConditionalOAuth client registered with the issuer.
AUTH_OIDC_CLIENT_SECRETUnsetCredential; Conditional, SecretOAuth client secret.
AUTH_OIDC_SCOPESopenid email profileSpace-separated scopesOIDC scopes requested during sign-in.

Dedicated Supabase OAuth

This is separate from generic OIDC and supports self-hosted gateways. Register /api/auth/callback/supabase with client_secret_basic. Supply all four connection values together.

VariableDefaultFormat / requirementPurpose and notes
AUTH_SUPABASE_URLUnsetHTTPS origin; ConditionalSupabase origin without path, query, fragment or credentials. HTTP is permitted only on localhost.
AUTH_SUPABASE_ANON_KEYUnsetSupabase anon API key; ConditionalGateway API key. This is not the OAuth client secret or a service-role key.
AUTH_SUPABASE_CLIENT_IDUnsetClient ID; ConditionalRegistered OAuth client.
AUTH_SUPABASE_CLIENT_SECRETUnsetCredential; Conditional, SecretRegistered OAuth secret.
AUTH_SUPABASE_PROVIDER_NAMESupabaseText, at most 64 charactersSign-in button label.

Organizations and public demo

Runtime. These settings affect the deployment, not just one organization's preferences.

VariableDefaultFormat / requirementPurpose and notes
SUPERADMIN_EMAILSUnsetComma-separated email addressesDeployment superadmins can administer all organizations. Use the accounts' lowercase email addresses.
USERS_CAN_CREATE_ORGANIZATIONSfalseBooleanAllows regular signed-in users to create organizations. Superadmins retain that capability independently.
DEMO_ACCESS_ENABLEDfalseBooleanEnables public demo sign-in; production startup reconciles the dedicated read-only demo organization.
DEMO_ORGANIZATION_SLUGdemoLowercase URL slugDemo organization's URL segment; must match the seeded organization.
DEMO_USER_EMAILdemo@inventory.invalidEmail addressDedicated demo account; must match the seeded account.

Disabling demo access hides the entry point; it does not delete demo data. Follow the demo deployment guide for removal.

Storage and upload limits

Runtime. Paths are resolved inside the app process/container. Mount persistent storage where the process can write; the standard container uses UID/GID 1001.

VariableDefaultFormat / requirementPurpose and notes
STORAGE_PROVIDERlocallocal or openinarySelects upload storage.
STORAGE_LOCAL_PATHdata/uploads under the working directoryFilesystem pathLocal uploads. The root Compose file fixes this to /app/data/uploads; changing .env alone does not override that mapping.
IMAGE_VARIANT_CACHE_PATH.variants under the local storage pathFilesystem pathCache of resized images. Add an environment mapping if your deployment template does not forward it.
MAX_UPLOAD_MB25Number, clamped to 1–100 MiBGeneral file-upload limit. Despite the suffix, units are multiples of 1024² bytes.
MAX_USDZ_UPLOAD_MB100Number, clamped to 10–500 MiBObject Capture USDZ upload limit; these models require local storage.
MAX_ROOM_SCAN_UPLOAD_MB100Number, clamped to 10–500 MiBCombined room-scan upload budget for world map, USDZ and guide images.
OPENINARY_BASE_URLUnsetService URL; ConditionalRequired when using Openinary.
OPENINARY_API_KEYUnsetCredential; Conditional, SecretRequired when using Openinary.

Raising an application limit does not change reverse-proxy limits or endpoint-specific checks. The Next.js Server Actions body limit is configured separately in code.

Maps

Build. All three map variables are public client-bundle settings. Set them before next build; the Dockerfile accepts them as build arguments. Changing the runtime environment of a prebuilt image does not update maps. Never place private credentials in these variables.

VariableDefaultFormat / requirementPurpose and notes
NEXT_PUBLIC_MAPBOX_ACCESS_TOKENUnsetPublic Mapbox tokenWhen present, Mapbox streets/satellite tiles take precedence over the fallback URLs.
NEXT_PUBLIC_MAP_STYLE_URLhttps://tiles.openfreemap.org/styles/libertyMapLibre-compatible style URLStreet/room map fallback when no Mapbox token is configured.
NEXT_PUBLIC_SATELLITE_TILE_URLhttps://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}Raster tile URL templateSatellite fallback when no Mapbox token is configured.

For a source-based Docker deployment, set the values in .env and rebuild with the same Compose files used for installation, adding --build to up -d. For an image-based platform template, publish/use an image built with the intended values.

AI providers, models and timeouts

Runtime. AI is optional; setting a model does not configure credentials or grant access to that model. IDs below are application defaults, not a guarantee of provider availability for your account. Credentials stay on the server.

Saved organization settings under Settings → AI take precedence over the environment defaults for inventory analysis, research and output language. Changing those Env defaults does not overwrite saved organization settings.

VariableDefaultFormat / requirementPurpose and notes
OPENAI_API_KEYUnsetCredential; Conditional, SecretEnables OpenAI/OpenAI-compatible analysis, extraction, research, translation and OpenAI cover generation.
OPENAI_BASE_URLSDK's OpenAI endpointAPI base URLOptional compatible endpoint. It must implement the APIs needed by the selected feature, including web-search support for research where used.
OPENAI_SCAN_EXTRACTION_MODELgpt-5.6-lunaModel IDStructured document/scan extraction.
OPENAI_VISION_MODELgpt-4.1-miniModel IDInventory image analysis default; also used by recognition-related requests.
OPENAI_RESEARCH_MODELgpt-5.6-terraModel IDWeb-grounded inventory research default.
OPENAI_TRANSLATION_MODELgpt-5.6-terraModel IDContent translation.
OPENAI_ROOM_VISION_MODELgpt-5.6-terraModel IDMulti-photo room analysis.
OPENAI_BULK_COUNT_MODELOrganization's analysis modelModel IDOptional model override for estimating bin contents from multiple photos.
AI_OUTPUT_LANGUAGEEnglishLanguage nameDefault generated-content language; distinct from the interface language.
OPENAI_RESEARCH_TIMEOUT_MS90000Integer, clamped to 10000–110000 msResearch provider request timeout.
OPENAI_TRANSLATION_TIMEOUT_MS120000Integer, clamped to 10000–300000 msTranslation provider request timeout; also affects the minimum job lease.
OPENAI_ROOM_VISION_TIMEOUT_MS55000Integer, clamped to 15000–58000 msRoom-photo analysis request timeout.
OPENAI_ROOM_CONSOLIDATION_TIMEOUT_MS95000Integer, clamped to 30000–110000 msRoom-analysis consolidation request timeout.
OPENAI_RECOGNITION_TIMEOUT_MS35000Integer, clamped to 5000–50000 msPer-request recognition timeout. Recognition provider calls disable automatic SDK retries.
AI_RECOGNITION_MAX_CATALOG_ITEMS2000Integer, clamped to 1–5000Bounds the recognition candidate catalog.

Cover-image generation

VariableDefaultFormat / requirementPurpose and notes
IMAGE_EDIT_PROVIDERopenaiopenai or googleProvider used by the single-model fallback when IMAGE_EDIT_MODELS is absent.
OPENAI_IMAGE_EDIT_MODELgpt-image-2.5-sunburstModel IDOpenAI single-model fallback. Requires OPENAI_API_KEY.
GOOGLE_AI_API_KEYFalls back to GOOGLE_API_KEYCredential; Conditional, SecretEnables Google cover generation.
GOOGLE_API_KEYUnsetCredential; SecretCompatibility fallback for the Google credential; prefer GOOGLE_AI_API_KEY.
GOOGLE_IMAGE_EDIT_MODELgemini-2.5-flash-imageModel IDGoogle single-model fallback.
IMAGE_EDIT_MODELSSingle model from provider settingsComma-separated provider:model entriesAllowlist shown to users. Valid providers are openai and google; entries are available only when that provider has credentials. The example Env file explicitly supplies a larger catalog.
IMAGE_EDIT_DEFAULT_MODELFirst available configured modelprovider:model entryPreferred model from the allowlist. If unavailable, the first available entry is used. The example file explicitly chooses openai:gpt-image-2.5-sunburst.

Example of a restricted catalog:

IMAGE_EDIT_MODELS=openai:gpt-image-1,google:gemini-2.5-flash-image
IMAGE_EDIT_DEFAULT_MODEL=openai:gpt-image-1

Per-identity request limits are separate from provider billing limits. Integers from 0 to 1,000,000 are accepted. Zero disables the operation. A malformed explicit value also disables it.

For analysis, research, recognition and counting, precedence is: operation-specific value → AI_RATE_LIMIT_PER_MINUTE → built-in operation default. Blank overrides are skipped. The example file and root Compose template explicitly set the legacy limit to 10, so research inherits 10, rather than its built-in default of 5, unless overridden.

VariableDefault when absentFormatOperation
AI_RATE_LIMIT_PER_MINUTEPer-operation defaults belowInteger / minuteLegacy fallback shared by four operations; example/template value is 10.
AI_ANALYSIS_RATE_LIMIT_PER_MINUTELegacy value, otherwise 10Integer / minuteImage analysis.
AI_RESEARCH_RATE_LIMIT_PER_MINUTELegacy value, otherwise 5Integer / minuteWeb research.
AI_RECOGNITION_RATE_LIMIT_PER_MINUTELegacy value, otherwise 10Integer / minuteItem recognition.
AI_COUNT_RATE_LIMIT_PER_MINUTELegacy value, otherwise 10Integer / minutePhoto counting.
AI_TRANSLATION_RATE_LIMIT_PER_MINUTE30Integer / minuteContent translation; no legacy fallback.
AI_IMAGE_RATE_LIMIT_PER_HOUR60Integer / hourCover generation; no legacy fallback.

Rate-limit policy source

Replicate photo counting

Runtime. A Replicate key is required for hosted counting models. Models must be pinned as owner/model:version, where the version is a 64-character hexadecimal identifier; an unversioned model path is rejected. The four built-in pins are listed separately below.

VariableDefaultFormat / requirementPurpose and notes
REPLICATE_API_TOKENUnsetCredential; Conditional, SecretHosted counting provider token.
REPLICATE_COUNT_DEFAULT_MODELgrounding-dinogrounding-dino, yolo-world, sam-2 or sam-3Initial counting model selection. Unknown values fall back to Grounding DINO.
REPLICATE_GROUNDING_DINO_MODELBuilt-in Grounding DINO pinPinned model referenceOverride for Grounding DINO.
REPLICATE_YOLO_WORLD_MODELBuilt-in YOLO World pinPinned model referenceOverride for YOLO World.
REPLICATE_SAM2_MODELBuilt-in SAM 2 pinPinned model referenceOverride for SAM 2.
REPLICATE_COUNT_MODELBuilt-in SAM 3 pinPinned model referenceSAM 3 override; this is not the default-model selector.
REPLICATE_COUNT_DEADLINE_SECONDS300Number, clamped to 30–600 secondsLifetime/deadline of the asynchronous prediction.
REPLICATE_COUNT_JOB_SECRETAUTH_SECRETAt least 32 characters if set; SecretOptional independent signing secret for asynchronous job tokens.
REPLICATE_COUNT_CONFIDENCE0.5Number, clamped to 0–1Confidence threshold.
REPLICATE_COUNT_MAX_MASKS100Number, rounded and clamped to 1–100Maximum returned masks.

Built-in pins at the time of this reference:

REPLICATE_GROUNDING_DINO_MODEL=adirik/grounding-dino:efd10a8ddc57ea28773327e881ce95e20cc1d734c589f7dd01d2036921ed78aa
REPLICATE_YOLO_WORLD_MODEL=ultralytics/yolov8s-worldv2:5e89b91b497fa7329dc88dbf820923190236ef7bc5a9b4aa1b7192b206656650
REPLICATE_SAM2_MODEL=meta/sam-2:fe97b453a6455861e3bac769b441ca1f1086110da7466dbb65cf1eecfd60dc83
REPLICATE_COUNT_MODEL=yodagg/sam3-image-seg:29c8e52db92a11c64f8939244d6b3a047ce2af24412b7971309008b9a61e2f6e

Experimental local 3D estimation

Runtime. This feature requires a separate Python/GPU installation and model weights; the standard app image does not include them. Setting the flag alone is insufficient. See the 3D runtime setup.

In the table, ROOT means the resolved BULK_3D_DATA_PATH, not a separate variable to set.

VariableDefaultFormat / requirementPurpose and notes
BULK_3D_ENABLEDfalseExact string true enables itEnables the experimental feature when its runtime is available.
BULK_3D_DATA_PATH~/.local/share/open-inventory/bulk-3dFilesystem pathRuntime/data root; keep it outside the source checkout. The default uses the process user's home directory.
BULK_3D_PYTHONROOT/runtime/bin/pythonExecutable pathPython interpreter with the required dependencies.
BULK_3D_SOURCE_PATHROOT/map-anythingDirectory pathMapAnything source checkout.
BULK_3D_WEIGHTS_PATHROOT/weights/model.safetensorsFile pathModel weights.
BULK_3D_MODEL_CONFIG_PATHROOT/weights/config.jsonFile pathModel configuration.

Translation worker

Runtime. Durable jobs are stored in PostgreSQL and processed by the application worker. Disable it only if another running worker is responsible for those jobs.

VariableDefaultFormatPurpose and notes
TRANSLATION_WORKER_ENABLEDtrueBooleanStarts the translation worker in the Node.js process.
TRANSLATION_WORKER_POLL_MS2000Integer, clamped to 500–60000 msQueue polling interval.
TRANSLATION_WORKER_CONCURRENCY1Integer, clamped to 1–8Concurrent jobs per app process.
TRANSLATION_JOB_LEASE_SECONDS180Number, clamped to 30–1800 secondsRequested lease; the effective lease is at least the provider timeout plus 30 seconds.
TRANSLATION_JOB_MAX_ATTEMPTS5Integer, clamped to 1–10Maximum attempts before giving up.

Notifications

Runtime. The in-app inbox works independently of external delivery. Configuring an external channel does not opt users into it; preferences still apply.

Worker and encryption

VariableDefaultFormat / requirementPurpose and notes
NOTIFICATION_WORKER_ENABLEDtrueBooleanRuns the built-in notification cycle.
NOTIFICATION_WORKER_POLL_MS900000Integer, clamped to 60000–86400000 msPolling interval; default is 15 minutes.
NOTIFICATION_CRON_SECRETUnsetBearer secret; Conditional, SecretRequired when an external scheduler calls POST /api/v1/notifications/run.
NOTIFICATION_ENCRYPTION_KEYUnsetIndependent 32-byte key; Conditional, SecretEncrypts stored Web Push subscription details. Use base64url or 64 hexadecimal characters; required for push.

Email

Email requires SMTP_HOST and NOTIFICATION_EMAIL_FROM. Supply credentials if your mail server requires authentication.

VariableDefaultFormat / requirementPurpose and notes
SMTP_HOSTUnsetHostname; ConditionalSMTP server.
SMTP_PORT587Port numberSMTP connection port.
SMTP_SECUREfalseBooleanImmediate TLS, commonly used with port 465. false is used for STARTTLS-capable connections such as port 587.
SMTP_USERUnsetUsername; ConditionalEnables SMTP authentication when provided.
SMTP_PASSWORDUnsetCredential; Conditional, SecretSMTP password.
NOTIFICATION_EMAIL_FROMUnsetSender email/header; ConditionalFor example Inventory <inventory@example.com>.

Web Push

All three VAPID values and NOTIFICATION_ENCRYPTION_KEY are required. Generate the VAPID pair with npx web-push generate-vapid-keys.

VariableDefaultFormat / requirementPurpose and notes
WEB_PUSH_PUBLIC_KEYUnsetVAPID public key; ConditionalSent to browsers for subscription. Public by design.
WEB_PUSH_PRIVATE_KEYUnsetVAPID private key; Conditional, SecretServer-side push signing.
WEB_PUSH_SUBJECTUnsetVAPID contact URI; ConditionalUse your own mailto: or HTTPS contact. .env.example supplies the placeholder mailto:admin@example.com; the code has no default.

Team delivery targets

VariableDefaultFormat / requirementPurpose and notes
NOTIFICATION_SLACK_WEBHOOK_URLUnsetIncoming webhook URL; SecretDeployment-wide Slack notification target.
NOTIFICATION_TEAMS_WEBHOOK_URLUnsetIncoming webhook URL; SecretDeployment-wide Teams notification target.
NOTIFICATION_WEBHOOK_URLUnsetEndpoint URL; SecretDeployment-wide generic notification target.
NOTIFICATION_WEBHOOK_SIGNING_SECRETUnsetHMAC secret; SecretOptional signing secret for generic notification delivery.

These notification targets are separate from the outgoing event-webhook system below.

Outgoing event webhooks

Runtime. Configure subscriptions in Settings → Webhooks. Their signing secrets are encrypted at rest. The database-backed worker can run on multiple app replicas.

VariableDefaultFormat / requirementPurpose and notes
WEBHOOK_ENCRYPTION_KEYUnsetExactly 32 random bytes as base64url or 64 hex characters; Conditional, SecretRequired to encrypt/decrypt webhook signing secrets. Use a key distinct from auth and notification keys.
WEBHOOK_WORKER_ENABLEDtrueBooleanStarts the delivery worker.
WEBHOOK_WORKER_POLL_MS2000Integer, clamped to 500–60000 msQueue polling interval.
WEBHOOK_WORKER_CONCURRENCY4Integer, clamped to 1–20Concurrent deliveries per worker process.
WEBHOOK_DELIVERY_TIMEOUT_MS10000Integer, clamped to 1000–60000 msTimeout per delivery attempt.
WEBHOOK_MAX_ATTEMPTS8Integer, clamped to 1–20Maximum delivery attempts.
WEBHOOK_RETENTION_DAYS30Integer, clamped to 1–365 daysRetention for terminal delivery history and payload snapshots.
WEBHOOK_ALLOW_PRIVATE_NETWORKSfalseBooleanAllows intentionally trusted private-network targets when enabled. Keep disabled for ordinary public targets.
WEBHOOK_CRON_SECRETUnsetBearer secret; Conditional, SecretRequired for an external scheduler calling POST /api/v1/webhooks/run.

WooCommerce and connection encryption

Runtime. Configure actual store connections and credentials under Settings → WooCommerce.

VariableDefaultFormat / requirementPurpose and notes
INTEGRATION_ENCRYPTION_KEYUnsetExactly 32 random bytes as base64url or 64 hex characters; Conditional, SecretRequired for storing encrypted integration credentials. Use a distinct key.
INTEGRATION_ALLOW_PRIVATE_NETWORKSfalseBooleanAllows a deliberately trusted private-network shop. HTTPS is still required.
WP_URLUnsetURL; template-only inputListed in .env.example and forwarded by some templates, but not read by the current WooCommerce connection implementation. Does not create a store connection.
WC_KEYUnsetCredential; Secret; template-only inputNot read by the current connection implementation; enter the consumer key in the application's connection settings.
WC_SECRETUnsetCredential; Secret; template-only inputNot read by the current connection implementation; enter the consumer secret in the application's connection settings.

The distinction above reflects the current WooCommerce implementation; the mere presence of a variable in a Compose template does not make it an active feature setting.

MCP endpoint

Runtime. Enable the optional endpoint at POST /mcp. It accepts Inventory API bearer tokens scoped to their issuing organization, not browser sessions or X-Organization-ID overrides.

For client setup, tool schemas, write confirmation, retries and troubleshooting, see the MCP integration guide.

VariableDefaultFormat / requirementPurpose and notes
MCP_ENABLEDfalseBooleanEnables the endpoint.
MCP_ALLOWED_HOSTSHost from AUTH_URLComma-separated host[:port] valuesAccepted request hosts. Use hostnames, not full URLs.
MCP_ALLOWED_ORIGINSNo browser origins allowedComma-separated exact originsBrowser clients must match this list. Server-to-server requests without an Origin header are permitted by the origin check.
MCP_REQUEST_RATE_LIMIT_PER_MINUTE240Integer, 1–10000Overall request limit. Invalid values use the default.
MCP_READ_RATE_LIMIT_PER_MINUTE120Integer, 1–10000Read-operation limit. Invalid values use the default.
MCP_WRITE_RATE_LIMIT_PER_MINUTE30Integer, 1–10000Write-operation limit. Invalid values use the default.
MCP_AUDIT_HASH_SECRETAUTH_SECRETIndependent random secret; SecretHMAC key for audit argument fingerprints; use at least 32 random bytes when configuring it separately.

Unlike AI limits, an MCP limit of zero does not disable an operation: it falls back to the default. Use endpoint configuration and token permissions to restrict access.

QZ Tray signing

Runtime. Supply both a certificate and private key to enable signing. File paths take precedence over Base64 values for each item. Mount files where the app user can read them. This configuration does not install QZ Tray or configure the printer on the user's computer.

VariableDefaultFormat / requirementPurpose and notes
QZ_CERTIFICATE_PATHUnsetPath to PEM certificateCertificate to present to QZ Tray.
QZ_PRIVATE_KEY_PATHUnsetPath to PEM private key; Secret materialServer-side signing key.
QZ_CERTIFICATE_BASE64UnsetBase64-encoded PEM certificateAlternative to the certificate file.
QZ_PRIVATE_KEY_BASE64UnsetBase64-encoded PEM private key; SecretAlternative to the private-key file.

The certificate must be trusted on the printing computer. Without signing, QZ's approval prompts remain part of the workflow. See Labels and printing.

Docker Compose and platform inputs

Compose/platform, not general application readers. These variables configure database credentials, port publishing or platform-generated values. The full root Compose file and platform templates remain authoritative for the selected installation method.

VariableDefaultFormat / requirementPurpose and notes
POSTGRES_PASSWORDNoneStrong URL-safe password; Required for bundled PostgreSQL, SecretUsed by PostgreSQL and interpolated into DATABASE_URL. Changing it in .env does not change an existing database user's password.
APP_PORT3000Host port numberUsed by the installer and docker-compose.local.yml; binds 127.0.0.1:APP_PORT to container port 3000. Does not change the app's internal port.
SERVICE_PASSWORD_POSTGRESGenerated by CoolifyCredential; SecretCoolify template's PostgreSQL password.
SERVICE_PASSWORD_64_AUTHGenerated by CoolifyCredential; SecretCoolify template's source for AUTH_SECRET.
SERVICE_PASSWORD_64_ADMINGenerated by CoolifyCredential; SecretCoolify template's initial administrator password. Remove bootstrap inputs after initialization.
SERVICE_FQDN_INVENTORYSupplied by CoolifyHostnameUsed by the bundled template to form the application's HTTPS URL.
SERVICE_URL_INVENTORY_3000Supplied by CoolifyService URLPlatform service-routing value.

POSTGRES_DB and POSTGRES_USER are set in the database service itself; the root template fixes both to inventory. The Dokploy import template generates its own password/secret inputs and maps them into the application environment.

Optional SSH database tunnel

Tool. These settings are consumed by npm run db:tunnel on the machine opening the tunnel, not by the production app. Restart the tunnel after changes. The helper loads .env.tunnel.local, .env.local and .env in that order without replacing already set process values.

Use exactly one remote target: host, Docker container or Docker Swarm service. The local listener must remain on loopback.

VariableDefaultFormat / requirementPurpose and notes
DB_TUNNEL_SSH_HOSTUnsetHostname or SSH config alias; ConditionalRequired to open a tunnel.
DB_TUNNEL_SSH_USERSSH default/configUsernameOptional remote SSH user.
DB_TUNNEL_SSH_PORT22Integer, 1–65535SSH server port.
DB_TUNNEL_IDENTITY_FILESSH default/configFile pathOptional SSH identity file; ~/ is expanded.
DB_TUNNEL_SSH_JUMPUnsetHostname or SSH aliasOptional jump host passed through SSH's -J option.
DB_TUNNEL_LOCAL_HOST127.0.0.1127.0.0.1, localhost or ::1Local bind address.
DB_TUNNEL_LOCAL_PORT15432Integer, 1–65535Local database port.
DB_TUNNEL_REMOTE_HOSTUnsetHostname/addressDatabase host as seen by the SSH server; alternative to Docker lookup.
DB_TUNNEL_DOCKER_CONTAINERUnsetContainer name/IDLookup target for an unexposed database container.
DB_TUNNEL_DOCKER_SERVICEUnsetSwarm service nameLookup target for a database service, for example on Dokploy.
DB_TUNNEL_REMOTE_PORT5432Integer, 1–65535Database listener port on the remote target.
DB_TUNNEL_DATABASE_USERinventoryDatabase usernameUsed in the helper's connection instructions.
DB_TUNNEL_DATABASE_NAMEinventoryDatabase nameUsed in the helper's connection instructions.

Point the local app's DATABASE_URL at the forwarded host/port when using the tunnel. Tunnel settings alone do not change the application's database connection.

Compatibility settings and scope

VariableDefaultStatus
NEXTAUTH_SECRETUnsetLegacy fallback used in session compatibility handling. Secret. Use AUTH_SECRET for new deployments; production startup still requires AUTH_SECRET.
NEXTAUTH_URLUnsetLegacy fallback in session handling. Use AUTH_URL; production startup still requires AUTH_URL.

This page does not catalog test-only SMOKE_* inputs, benchmark controls, native mobile build credentials or Next.js internal variables such as NEXT_PHASE and NEXT_RUNTIME. They are not production application configuration.

Secrets and verification

Generate a new value separately for each encryption purpose. For variables requiring 32 random bytes as 64 hexadecimal characters:

openssl rand -hex 32

Preserve encryption keys together with protected deployment backups. Replacing WEBHOOK_ENCRYPTION_KEY, INTEGRATION_ENCRYPTION_KEY or NOTIFICATION_ENCRYPTION_KEY without a migration/re-enrollment plan can make existing encrypted data unreadable. Changing signing secrets can invalidate sessions or pending signed jobs.

After applying changes, check /api/health and the feature you configured. A healthy database/storage check does not verify SMTP credentials, model access, OAuth callbacks or a remote logo. Review application logs for validation errors without publishing environment dumps or rendered Compose secrets.

When updating this reference, compare .env.example, the relevant code readers and the deployment mappings. Keep example values distinct from built-in defaults, and verify newly added settings against the version you deploy.

On this page