Environment Variables
Document Control
| Field | Value |
|---|---|
| Source File | packages/core/src/common/environments.ts (93 lines) |
| Class | EnvironmentKeys extends BaseEnvironmentKeys |
| Total Variables | 65+ (11 inherited + 54 application-specific) |
| Framework | IGNIS Environment Variables |
1. Overview
The EnvironmentKeys class in @nx/core extends the IGNIS framework's BaseEnvironmentKeys to define all environment variables used across BANA services. Every variable follows the APP_ENV_ prefix convention.
import { EnvironmentKeys as BaseEnvironmentKeys } from '@venizia/ignis';
export class EnvironmentKeys extends BaseEnvironmentKeys {
static readonly APP_ENV_NODE_ENV = 'APP_ENV_NODE_ENV';
// ... 54 application-specific keys
}Inheritance chain:
BaseEnvironmentKeys (IGNIS) ← Application, JWT, Server, PostgreSQL
└── EnvironmentKeys (@nx/core) ← Redis, Minio, Mail, WebSocket, Kafka, etc.All variables are accessed via applicationEnvironment.get():
import { applicationEnvironment } from '@venizia/ignis';
import { EnvironmentKeys } from '@nx/core';
const host = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_HOST);For the full IGNIS base variables reference, see the IGNIS Environment Variables documentation.
2. Inherited from IGNIS (BaseEnvironmentKeys)
These variables are defined in the IGNIS framework and inherited by EnvironmentKeys through class extension. They are available in every BANA service without redeclaration.
Application
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_APPLICATION_NAME | string | APP | Application name used in logs and identification |
APP_ENV_APPLICATION_SECRET | string | -- | Application encryption secret for JWT payload encryption |
APP_ENV_APPLICATION_TIMEZONE | string | Asia/Ho_Chi_Minh | Default timezone for date operations |
APP_ENV_APPLICATION_ROLES | string | -- | Comma-separated list of application role identifiers |
JWT Authentication
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_JWT_SECRET | string | -- | Secret key for signing JWT tokens |
APP_ENV_JWT_EXPIRES_IN | number | 86400 | JWT token expiration time in seconds (default 24 hours) |
Server
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_SERVER_HOST | string | localhost | Server bind address |
APP_ENV_SERVER_PORT | number | 3000 | Server listen port |
APP_ENV_SERVER_BASE_PATH | string | / | Base path prefix for all routes |
PostgreSQL
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_POSTGRES_HOST | string | localhost | PostgreSQL server host |
APP_ENV_POSTGRES_PORT | number | 5432 | PostgreSQL server port |
APP_ENV_POSTGRES_DATABASE | string | -- | Database name |
APP_ENV_POSTGRES_USERNAME | string | postgres | Database username |
APP_ENV_POSTGRES_PASSWORD | string | -- | Database password |
3. Application
Variables specific to BANA application configuration.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_NODE_ENV | string | development | Runtime environment (development, test, staging, production) |
APP_ENV_APPLICATION_EXPLORER_URL | string | -- | URL for the API explorer / Swagger UI |
APP_ENV_PARSE_RESULT_FOLDER_PATH | string | -- | Temporary folder path for file parsing results |
4. Snowflake ID Generator
Configuration for distributed Snowflake ID generation. Each service instance must have a unique worker ID to avoid collisions.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_SNOWFLAKE_WORKER_ID | number | -- | Unique worker ID (0--1023) for this service instance |
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT | number | -- | Custom epoch timestamp in milliseconds (e.g., 1704067200000 for 2024-01-01) |
5. Minio (S3-Compatible Storage)
Connection settings for MinIO object storage, used by the asset service for file uploads and presigned URL generation.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_MINIO_HOST | string | -- | MinIO server hostname |
APP_ENV_MINIO_API_PORT | number | 9000 | MinIO API port |
APP_ENV_MINIO_ACCESS_KEY | string | -- | MinIO access key ID |
APP_ENV_MINIO_SECRET_KEY | string | -- | MinIO secret access key |
6. Redis -- BullMQ (Job Queues)
Dedicated Redis connection for BullMQ job queues. Used by services that process background jobs (sale, payment, finance, mq-pay).
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_BULLMQ_REDIS_IDENTIFIER | string | -- | Connection identifier for logging and diagnostics |
APP_ENV_BULLMQ_REDIS_HOST | string | -- | Redis host for BullMQ |
APP_ENV_BULLMQ_REDIS_PORT | number | 6379 | Redis port |
APP_ENV_BULLMQ_REDIS_DB | number | 0 | Redis database number |
APP_ENV_BULLMQ_REDIS_PASSWORD | string | -- | Redis password (optional if no auth) |
APP_ENV_BULLMQ_REDIS_MAX_RETRY | number | -- | Maximum connection retry attempts |
7. Redis -- Cache
Dedicated Redis connection for application caching. Used by services for lookup caching (e.g., inventory tracking types, payment configurations).
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_CACHE_REDIS_IDENTIFIER | string | -- | Connection identifier for logging and diagnostics |
APP_ENV_CACHE_REDIS_HOST | string | -- | Redis host for caching |
APP_ENV_CACHE_REDIS_PORT | number | 6379 | Redis port |
APP_ENV_CACHE_REDIS_DB | number | 0 | Redis database number |
APP_ENV_CACHE_REDIS_PASSWORD | string | -- | Redis password (optional if no auth) |
APP_ENV_CACHE_REDIS_MAX_RETRY | number | -- | Maximum connection retry attempts |
8. Redis -- PubSub Subscriber
Dedicated Redis connection for the pub/sub subscriber side. Used by services that listen for cross-service events (e.g., finance listening for payment events).
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_IDENTIFIER | string | -- | Connection identifier for logging and diagnostics |
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_HOST | string | -- | Redis host for subscriber |
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PORT | number | 6379 | Redis port |
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_DB | number | 0 | Redis database number |
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PASSWORD | string | -- | Redis password (optional if no auth) |
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_MAX_RETRY | number | -- | Maximum connection retry attempts |
9. Redis -- PubSub Publisher
Dedicated Redis connection for the pub/sub publisher side. Used by services that emit cross-service events (e.g., payment publishing payment success events).
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_PUBSUB_PUBLISHER_REDIS_IDENTIFIER | string | -- | Connection identifier for logging and diagnostics |
APP_ENV_PUBSUB_PUBLISHER_REDIS_HOST | string | -- | Redis host for publisher |
APP_ENV_PUBSUB_PUBLISHER_REDIS_PORT | number | 6379 | Redis port |
APP_ENV_PUBSUB_PUBLISHER_REDIS_DB | number | 0 | Redis database number |
APP_ENV_PUBSUB_PUBLISHER_REDIS_PASSWORD | string | -- | Redis password (optional if no auth) |
APP_ENV_PUBSUB_PUBLISHER_REDIS_MAX_RETRY | number | -- | Maximum connection retry attempts |
10. Redis -- WebSocket
Redis connection for WebSocket cross-instance message delivery. Supports both single-node and cluster modes. Used exclusively by the @nx/signal service.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_WEBSOCKET_REDIS_MODE | string | single | Redis mode: single or cluster |
APP_ENV_WEBSOCKET_REDIS_IDENTIFIER | string | -- | Connection identifier (single mode) |
APP_ENV_WEBSOCKET_REDIS_HOST | string | -- | Redis host (single mode) |
APP_ENV_WEBSOCKET_REDIS_PORT | number | 6379 | Redis port (single mode) |
APP_ENV_WEBSOCKET_REDIS_DB | number | 0 | Redis database number (single mode) |
APP_ENV_WEBSOCKET_REDIS_PASSWORD | string | -- | Redis password (single mode, optional) |
APP_ENV_WEBSOCKET_REDIS_MAX_RETRY | number | -- | Maximum connection retry attempts (single mode) |
APP_ENV_WEBSOCKET_REDIS_CLUSTER_IDENTIFIER | string | -- | Connection identifier (cluster mode) |
APP_ENV_WEBSOCKET_REDIS_CLUSTER_NODES | string | -- | Comma-separated cluster node addresses (e.g., node1:6379,node2:6379,node3:6379) |
Single mode example:
APP_ENV_WEBSOCKET_REDIS_MODE=single
APP_ENV_WEBSOCKET_REDIS_HOST=localhost
APP_ENV_WEBSOCKET_REDIS_PORT=6379
APP_ENV_WEBSOCKET_REDIS_DB=0Cluster mode example:
APP_ENV_WEBSOCKET_REDIS_MODE=cluster
APP_ENV_WEBSOCKET_REDIS_CLUSTER_NODES=redis-node1:6379,redis-node2:6379,redis-node3:637911. WebSocket ECDH Encryption
Encryption parameter for the ECDH P-256 key exchange used by the signal service. This value is used as the info parameter in HKDF key derivation to produce the shared AES-256-GCM encryption key.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_WEBSOCKET_ECDH_INFO | string | -- | HKDF info string for ECDH shared key derivation |
12. Mail (SMTP)
SMTP and OAuth2 configuration for the email component. Supports basic SMTP authentication and Gmail OAuth2.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_MAIL_HOST | string | smtp.gmail.com | SMTP server hostname |
APP_ENV_MAIL_PORT | number | 465 | SMTP server port |
APP_ENV_MAIL_SECURE | boolean | true | Enable TLS for SMTP connection |
APP_ENV_MAIL_USER | string | -- | SMTP username or sender email address |
APP_ENV_MAIL_CLIENT_ID | string | -- | OAuth2 client ID (for Gmail) |
APP_ENV_MAIL_CLIENT_SECRET | string | -- | OAuth2 client secret |
APP_ENV_MAIL_REFRESH_TOKEN | string | -- | OAuth2 refresh token |
APP_ENV_MAIL_QUEUE_TYPE | string | internal | Queue type for mail delivery (internal or external queue) |
APP_ENV_MAIL_INTERNAL_QUEUE_IDENTIFIER | string | -- | Identifier for the internal mail queue |
13. Service URLs (Inter-Service Communication)
Base URLs for cross-service HTTP communication via IdentityNetworkService and other network services.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_IDENTITY_SERVICE_BASE_URL | string | -- | Identity service base URL (e.g., http://localhost:3001) |
APP_ENV_COMMERCE_SERVICE_BASE_URL | string | -- | Commerce service base URL (e.g., http://localhost:3002) |
14. T-VAN / IIAPI (Vietnam E-Invoice)
Configuration for Vietnam electronic invoice integrations.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_VNPAY_IIAPI_CLIENT_NAME | string | -- | Named client identifier for the IIAPI registry |
APP_ENV_VNPAY_TVAN_API_KEY | string | -- | API key for T-VAN service authentication |
15. Kafka
Apache Kafka connection settings for event streaming. Used when Kafka-based messaging is enabled.
| Variable | Type | Default | Description |
|---|---|---|---|
APP_ENV_KAFKA_BROKERS | string | -- | Comma-separated broker addresses (e.g., kafka1:9092,kafka2:9092) |
APP_ENV_KAFKA_CLIENT_ID | string | -- | Kafka client identifier |
APP_ENV_KAFKA_GROUP_ID | string | -- | Consumer group identifier |
16. Environment File Loading
BANA uses dotenv-flow for environment variable loading. Each package maintains its own set of .env files.
File Structure
packages/<service>/
├── .env # Base defaults (committed)
├── .env.local # Local overrides (gitignored)
├── .env.development # Development environment
├── .env.test # Test environment
├── .env.staging # Staging environment
├── .env.production # Production environment
└── .env.example # Template for team reference (committed)Load Order (dotenv-flow)
Files are loaded in the following order. Later files override earlier ones:
.env-- base defaults.env.local-- local overrides.env.{NODE_ENV}-- environment-specific values (e.g.,.env.development).env.{NODE_ENV}.local-- environment-specific local overrides
17. Complete .env.example
# =============================================
# NX-SELLER ENVIRONMENT VARIABLES
# =============================================
# Copy this file to .env.development and fill in values.
# =============================================
# APPLICATION
# =============================================
APP_ENV_NODE_ENV=development
APP_ENV_APPLICATION_NAME=my-service
APP_ENV_APPLICATION_SECRET=generate-a-strong-random-secret
APP_ENV_APPLICATION_EXPLORER_URL=
APP_ENV_APPLICATION_TIMEZONE=Asia/Ho_Chi_Minh
APP_ENV_PARSE_RESULT_FOLDER_PATH=/tmp/parsed-results
# =============================================
# SERVER
# =============================================
APP_ENV_SERVER_HOST=0.0.0.0
APP_ENV_SERVER_PORT=3000
APP_ENV_SERVER_BASE_PATH=/v1/api
# =============================================
# JWT AUTHENTICATION
# =============================================
APP_ENV_JWT_SECRET=generate-another-strong-random-secret
APP_ENV_JWT_EXPIRES_IN=86400
# =============================================
# POSTGRESQL
# =============================================
APP_ENV_POSTGRES_HOST=localhost
APP_ENV_POSTGRES_PORT=5432
APP_ENV_POSTGRES_DATABASE=bana
APP_ENV_POSTGRES_USERNAME=postgres
APP_ENV_POSTGRES_PASSWORD=password
# =============================================
# SNOWFLAKE ID GENERATOR
# =============================================
APP_ENV_SNOWFLAKE_WORKER_ID=1
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT=1704067200000
# =============================================
# MINIO (S3-Compatible Storage)
# =============================================
APP_ENV_MINIO_HOST=localhost
APP_ENV_MINIO_API_PORT=9000
APP_ENV_MINIO_ACCESS_KEY=minioadmin
APP_ENV_MINIO_SECRET_KEY=minioadmin
# =============================================
# REDIS - BullMQ (Job Queues)
# =============================================
APP_ENV_BULLMQ_REDIS_IDENTIFIER=bullmq
APP_ENV_BULLMQ_REDIS_HOST=localhost
APP_ENV_BULLMQ_REDIS_PORT=6379
APP_ENV_BULLMQ_REDIS_DB=1
APP_ENV_BULLMQ_REDIS_PASSWORD=
APP_ENV_BULLMQ_REDIS_MAX_RETRY=5
# =============================================
# REDIS - Cache
# =============================================
APP_ENV_CACHE_REDIS_IDENTIFIER=cache
APP_ENV_CACHE_REDIS_HOST=localhost
APP_ENV_CACHE_REDIS_PORT=6379
APP_ENV_CACHE_REDIS_DB=0
APP_ENV_CACHE_REDIS_PASSWORD=
APP_ENV_CACHE_REDIS_MAX_RETRY=5
# =============================================
# REDIS - PubSub Subscriber
# =============================================
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_IDENTIFIER=pubsub-subscriber
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_HOST=localhost
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PORT=6379
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_DB=0
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PASSWORD=
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_MAX_RETRY=5
# =============================================
# REDIS - PubSub Publisher
# =============================================
APP_ENV_PUBSUB_PUBLISHER_REDIS_IDENTIFIER=pubsub-publisher
APP_ENV_PUBSUB_PUBLISHER_REDIS_HOST=localhost
APP_ENV_PUBSUB_PUBLISHER_REDIS_PORT=6379
APP_ENV_PUBSUB_PUBLISHER_REDIS_DB=0
APP_ENV_PUBSUB_PUBLISHER_REDIS_PASSWORD=
APP_ENV_PUBSUB_PUBLISHER_REDIS_MAX_RETRY=5
# =============================================
# REDIS - WebSocket (Single Mode)
# =============================================
APP_ENV_WEBSOCKET_REDIS_MODE=single
APP_ENV_WEBSOCKET_REDIS_IDENTIFIER=websocket
APP_ENV_WEBSOCKET_REDIS_HOST=localhost
APP_ENV_WEBSOCKET_REDIS_PORT=6379
APP_ENV_WEBSOCKET_REDIS_DB=0
APP_ENV_WEBSOCKET_REDIS_PASSWORD=
APP_ENV_WEBSOCKET_REDIS_MAX_RETRY=5
# REDIS - WebSocket (Cluster Mode — uncomment to use)
# APP_ENV_WEBSOCKET_REDIS_MODE=cluster
# APP_ENV_WEBSOCKET_REDIS_CLUSTER_IDENTIFIER=websocket-cluster
# APP_ENV_WEBSOCKET_REDIS_CLUSTER_NODES=node1:6379,node2:6379,node3:6379
# =============================================
# WEBSOCKET ECDH ENCRYPTION
# =============================================
APP_ENV_WEBSOCKET_ECDH_INFO=bana-websocket-encryption
# =============================================
# MAIL (SMTP / Gmail OAuth2)
# =============================================
APP_ENV_MAIL_HOST=smtp.gmail.com
APP_ENV_MAIL_PORT=465
APP_ENV_MAIL_SECURE=true
APP_ENV_MAIL_USER=noreply@example.com
APP_ENV_MAIL_CLIENT_ID=
APP_ENV_MAIL_CLIENT_SECRET=
APP_ENV_MAIL_REFRESH_TOKEN=
APP_ENV_MAIL_QUEUE_TYPE=internal
APP_ENV_MAIL_INTERNAL_QUEUE_IDENTIFIER=
# =============================================
# INTER-SERVICE COMMUNICATION
# =============================================
APP_ENV_IDENTITY_SERVICE_BASE_URL=http://localhost:3001
APP_ENV_COMMERCE_SERVICE_BASE_URL=http://localhost:3002
# =============================================
# T-VAN / IIAPI (Vietnam E-Invoice)
# =============================================
APP_ENV_VNPAY_IIAPI_CLIENT_NAME=
APP_ENV_VNPAY_TVAN_API_KEY=
# =============================================
# KAFKA (Event Streaming)
# =============================================
APP_ENV_KAFKA_BROKERS=localhost:9092
APP_ENV_KAFKA_CLIENT_ID=bana
APP_ENV_KAFKA_GROUP_ID=bana-group18. Usage in Code
Reading Variables
import { applicationEnvironment } from '@venizia/ignis';
import { EnvironmentKeys } from '@nx/core';
// String value
const host = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_HOST);
// Number value (requires parsing)
const port = parseInt(
applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_PORT) || '5432',
);
// Boolean value
const secure = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_MAIL_SECURE) === 'true';
// With fallback default
const nodeEnv = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_NODE_ENV)
?? 'development';Startup Validation
function validateEnvironment() {
const required = [
EnvironmentKeys.APP_ENV_POSTGRES_HOST,
EnvironmentKeys.APP_ENV_POSTGRES_DATABASE,
EnvironmentKeys.APP_ENV_SNOWFLAKE_WORKER_ID,
EnvironmentKeys.APP_ENV_JWT_SECRET,
EnvironmentKeys.APP_ENV_APPLICATION_SECRET,
];
const missing = required.filter(key => !applicationEnvironment.get(key));
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}19. Security Best Practices
Never Commit Secrets
# .gitignore
.env.local
.env.*.local
.env.productionUse Different Secrets Per Environment
# Development
APP_ENV_JWT_SECRET=dev-secret-not-for-production
# Production (from secret manager)
APP_ENV_JWT_SECRET=<from-vault-or-k8s-secret>Use Secret Managers in Production
# Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
stringData:
APP_ENV_JWT_SECRET: "production-jwt-secret"
APP_ENV_APPLICATION_SECRET: "production-app-secret"
APP_ENV_POSTGRES_PASSWORD: "production-db-password"Rotate Secrets Regularly
Schedule regular rotation for:
APP_ENV_JWT_SECRETAPP_ENV_APPLICATION_SECRETAPP_ENV_POSTGRES_PASSWORDAPP_ENV_MINIO_SECRET_KEYAPP_ENV_MAIL_CLIENT_SECRETAPP_ENV_VNPAY_TVAN_API_KEY