Skip to content

Environment configuration

Canonical backend template: apps/backend/.env.example. Copy to .env locally; never commit real secrets.

MySQL-backed tests (Playwright, manual API smoke): copy apps/backend/.env.test.example.env.test, then from apps/backend run npm run db:test:prepare and npm run start:test. That uses database test_nipos and seeds owner@test.nipos.local / cashier@test.nipos.local (password 123123). Playwright loads .env.test automatically via apps/vendor-web/e2e/load-backend-test-env.cjs.

VariablePurpose
PORTHTTP port (default 3000)
CORS_ORIGINComma-separated browser origins (e.g. http://localhost:5173)
NODE_ENVproduction disables detailed validation messages (ValidationPipe)
VariablePurpose
SWAGGER_ENABLEDfalse disables OpenAPI + Swagger UI
SWAGGER_PATHPath segment for UI (default docs); JSON at {path}-json
VariablePurpose
APP_URLPublic site URL; aligns POS/admin image paths with Laravel asset(...) expectations (see comment in .env.example)
IMAGE_APP_URLOptional. Public origin for Nest-uploaded storage keys that use the nest/ prefix (e.g. gallery_files.file_key like nest/vendor/{id}/…). Full URLs are built with IMAGE_APP_URL when set; otherwise APP_URL is used.
PUBLIC_STORAGE_ROOTOptional absolute path to the physical public/storage directory used for polymorphic gallery uploads (gallery_files rows; vendor flows use public/storage/vendor-gallery/..., served at /public/storage/*). Defaults to {cwd}/public/storage when unset. Production: point outside the deploy directory (PM2) or rely on Docker Compose named volumes — see Deployment and static SPAsUpload persistence.
VENDOR_IMPORT_STORAGE_ROOTOptional absolute path for temporary Clover/product import files. Defaults to {cwd}/storage/vendor-imports. Use a persistent path in production alongside PUBLIC_STORAGE_ROOT.
VariablePurpose
DB_ENABLEDfalse skips DB (e.g. CI tests)
DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_DATABASEMySQL connection
DB_SYNCHRONIZEDev-only; use migrations in production
DB_LOGGINGSQL logging
TABLE_PREFIX, TABLE_FIELD_PREFIXLegacy schema compatibility
VariablePurpose
JWT_ACCESS_SECRET, JWT_REFRESH_SECRETSigning keys
JWT_ACCESS_EXPIRES, JWT_REFRESH_EXPIRESe.g. 15m, 7d

Auth seeds (DB_ENABLED=false or local demos)

Section titled “Auth seeds (DB_ENABLED=false or local demos)”
VariablePurpose
AUTH_SEED_*Demo customer user
AUTH_VENDOR_*Vendor owner/employee seeds, role JSON, zone topic, store active flags
AUTH_ADMIN_*Admin + staff seeds, AUTH_ADMIN_EMPLOYEE_MODULES_JSON for module parity; with DB-backed admin_roles, AUTH_ADMIN_MERGE_ITEM_MODULE_ROLE_IDS (default 2) merges catalog item into admin_roles.modules when missing so staff can use product APIs
VariablePurpose
(per store)Terminal key is not global — devices are configured in app settings; sent as x-pos-terminal-key (see POS and payment webhooks)
VariablePurpose
PUBLIC_API_BASE_URLOptional. Public API origin (no path) used when POST /api/v1/pos-bridge/activate builds wsUrl and webhookUrl. If unset, the handler uses X-Forwarded-Host / Host and X-Forwarded-Proto / request protocol from the activate request (see pos-bridge.controller.ts). Set this when terminals must use a different base than the host header seen by the server (e.g. reverse proxy, split DNS).
DEFAULT_POS_CURRENCYOptional. Fallback ISO currency for POS payment flows when not specified (defaults to USD in PosService).
VariableAppsPurpose
VITE_API_URLadmin-web, vendor-webAPI origin; empty in Docker build → same-origin /api/v1 (see Frontend applications)

These are read by apps/vendor-web/playwright.config.cjs and e2e/login.spec.ts (not Vite import.meta.env):

VariableDefaultPurpose
PLAYWRIGHT_API_BASE_URLhttp://127.0.0.1:3000Nest origin; wired into the Playwright-managed Vite process as VITE_API_URL
PLAYWRIGHT_VENDOR_WEB_PORT5187Port for npm run dev under test (avoids 5174 dev default)
PLAYWRIGHT_VENDOR_OWNER_EMAILowner@nipos.local (or owner@test.nipos.local when .env.test is loaded)Owner login E2E — must exist in DB when DB_ENABLED=true
PLAYWRIGHT_VENDOR_OWNER_PASSWORDsecret12 / 123123 with .env.testOwner password for the same test
PLAYWRIGHT_VENDOR_EMPLOYEE_EMAILemployee@nipos.local (or cashier@test.nipos.local for Cashier desktop)Staff / cashier login E2E
PLAYWRIGHT_VENDOR_EMPLOYEE_PASSWORDsecret12 / 123123 with .env.testStaff password for the same test

Failure screenshots, video, and traces are written under apps/vendor-web/test-results/ (see Frontend applicationsScreenshots & traces). Login E2E also attaches a full-page PNG per test in the HTML report via e2e/helpers/attach-screenshot.ts.