Skip to content

Environment Variables

Document Control

FieldValue
Source Filepackages/core/src/common/environments.ts (93 lines)
ClassEnvironmentKeys extends BaseEnvironmentKeys
Total Variables65+ (11 inherited + 54 application-specific)
FrameworkIGNIS 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.

typescript
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():

typescript
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

VariableTypeDefaultDescription
APP_ENV_APPLICATION_NAMEstringAPPApplication name used in logs and identification
APP_ENV_APPLICATION_SECRETstring--Application encryption secret for JWT payload encryption
APP_ENV_APPLICATION_TIMEZONEstringAsia/Ho_Chi_MinhDefault timezone for date operations
APP_ENV_APPLICATION_ROLESstring--Comma-separated list of application role identifiers

JWT Authentication

VariableTypeDefaultDescription
APP_ENV_JWT_SECRETstring--Secret key for signing JWT tokens
APP_ENV_JWT_EXPIRES_INnumber86400JWT token expiration time in seconds (default 24 hours)

Server

VariableTypeDefaultDescription
APP_ENV_SERVER_HOSTstringlocalhostServer bind address
APP_ENV_SERVER_PORTnumber3000Server listen port
APP_ENV_SERVER_BASE_PATHstring/Base path prefix for all routes

PostgreSQL

VariableTypeDefaultDescription
APP_ENV_POSTGRES_HOSTstringlocalhostPostgreSQL server host
APP_ENV_POSTGRES_PORTnumber5432PostgreSQL server port
APP_ENV_POSTGRES_DATABASEstring--Database name
APP_ENV_POSTGRES_USERNAMEstringpostgresDatabase username
APP_ENV_POSTGRES_PASSWORDstring--Database password

3. Application

Variables specific to BANA application configuration.

VariableTypeDefaultDescription
APP_ENV_NODE_ENVstringdevelopmentRuntime environment (development, test, staging, production)
APP_ENV_APPLICATION_EXPLORER_URLstring--URL for the API explorer / Swagger UI
APP_ENV_PARSE_RESULT_FOLDER_PATHstring--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.

VariableTypeDefaultDescription
APP_ENV_SNOWFLAKE_WORKER_IDnumber--Unique worker ID (0--1023) for this service instance
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINTnumber--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.

VariableTypeDefaultDescription
APP_ENV_MINIO_HOSTstring--MinIO server hostname
APP_ENV_MINIO_API_PORTnumber9000MinIO API port
APP_ENV_MINIO_ACCESS_KEYstring--MinIO access key ID
APP_ENV_MINIO_SECRET_KEYstring--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).

VariableTypeDefaultDescription
APP_ENV_BULLMQ_REDIS_IDENTIFIERstring--Connection identifier for logging and diagnostics
APP_ENV_BULLMQ_REDIS_HOSTstring--Redis host for BullMQ
APP_ENV_BULLMQ_REDIS_PORTnumber6379Redis port
APP_ENV_BULLMQ_REDIS_DBnumber0Redis database number
APP_ENV_BULLMQ_REDIS_PASSWORDstring--Redis password (optional if no auth)
APP_ENV_BULLMQ_REDIS_MAX_RETRYnumber--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).

VariableTypeDefaultDescription
APP_ENV_CACHE_REDIS_IDENTIFIERstring--Connection identifier for logging and diagnostics
APP_ENV_CACHE_REDIS_HOSTstring--Redis host for caching
APP_ENV_CACHE_REDIS_PORTnumber6379Redis port
APP_ENV_CACHE_REDIS_DBnumber0Redis database number
APP_ENV_CACHE_REDIS_PASSWORDstring--Redis password (optional if no auth)
APP_ENV_CACHE_REDIS_MAX_RETRYnumber--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).

VariableTypeDefaultDescription
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_IDENTIFIERstring--Connection identifier for logging and diagnostics
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_HOSTstring--Redis host for subscriber
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PORTnumber6379Redis port
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_DBnumber0Redis database number
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_PASSWORDstring--Redis password (optional if no auth)
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_MAX_RETRYnumber--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).

VariableTypeDefaultDescription
APP_ENV_PUBSUB_PUBLISHER_REDIS_IDENTIFIERstring--Connection identifier for logging and diagnostics
APP_ENV_PUBSUB_PUBLISHER_REDIS_HOSTstring--Redis host for publisher
APP_ENV_PUBSUB_PUBLISHER_REDIS_PORTnumber6379Redis port
APP_ENV_PUBSUB_PUBLISHER_REDIS_DBnumber0Redis database number
APP_ENV_PUBSUB_PUBLISHER_REDIS_PASSWORDstring--Redis password (optional if no auth)
APP_ENV_PUBSUB_PUBLISHER_REDIS_MAX_RETRYnumber--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.

VariableTypeDefaultDescription
APP_ENV_WEBSOCKET_REDIS_MODEstringsingleRedis mode: single or cluster
APP_ENV_WEBSOCKET_REDIS_IDENTIFIERstring--Connection identifier (single mode)
APP_ENV_WEBSOCKET_REDIS_HOSTstring--Redis host (single mode)
APP_ENV_WEBSOCKET_REDIS_PORTnumber6379Redis port (single mode)
APP_ENV_WEBSOCKET_REDIS_DBnumber0Redis database number (single mode)
APP_ENV_WEBSOCKET_REDIS_PASSWORDstring--Redis password (single mode, optional)
APP_ENV_WEBSOCKET_REDIS_MAX_RETRYnumber--Maximum connection retry attempts (single mode)
APP_ENV_WEBSOCKET_REDIS_CLUSTER_IDENTIFIERstring--Connection identifier (cluster mode)
APP_ENV_WEBSOCKET_REDIS_CLUSTER_NODESstring--Comma-separated cluster node addresses (e.g., node1:6379,node2:6379,node3:6379)

Single mode example:

bash
APP_ENV_WEBSOCKET_REDIS_MODE=single
APP_ENV_WEBSOCKET_REDIS_HOST=localhost
APP_ENV_WEBSOCKET_REDIS_PORT=6379
APP_ENV_WEBSOCKET_REDIS_DB=0

Cluster mode example:

bash
APP_ENV_WEBSOCKET_REDIS_MODE=cluster
APP_ENV_WEBSOCKET_REDIS_CLUSTER_NODES=redis-node1:6379,redis-node2:6379,redis-node3:6379

11. 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.

VariableTypeDefaultDescription
APP_ENV_WEBSOCKET_ECDH_INFOstring--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.

VariableTypeDefaultDescription
APP_ENV_MAIL_HOSTstringsmtp.gmail.comSMTP server hostname
APP_ENV_MAIL_PORTnumber465SMTP server port
APP_ENV_MAIL_SECUREbooleantrueEnable TLS for SMTP connection
APP_ENV_MAIL_USERstring--SMTP username or sender email address
APP_ENV_MAIL_CLIENT_IDstring--OAuth2 client ID (for Gmail)
APP_ENV_MAIL_CLIENT_SECRETstring--OAuth2 client secret
APP_ENV_MAIL_REFRESH_TOKENstring--OAuth2 refresh token
APP_ENV_MAIL_QUEUE_TYPEstringinternalQueue type for mail delivery (internal or external queue)
APP_ENV_MAIL_INTERNAL_QUEUE_IDENTIFIERstring--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.

VariableTypeDefaultDescription
APP_ENV_IDENTITY_SERVICE_BASE_URLstring--Identity service base URL (e.g., http://localhost:3001)
APP_ENV_COMMERCE_SERVICE_BASE_URLstring--Commerce service base URL (e.g., http://localhost:3002)

14. T-VAN / IIAPI (Vietnam E-Invoice)

Configuration for Vietnam electronic invoice integrations.

VariableTypeDefaultDescription
APP_ENV_VNPAY_IIAPI_CLIENT_NAMEstring--Named client identifier for the IIAPI registry
APP_ENV_VNPAY_TVAN_API_KEYstring--API key for T-VAN service authentication

15. Kafka

Apache Kafka connection settings for event streaming. Used when Kafka-based messaging is enabled.

VariableTypeDefaultDescription
APP_ENV_KAFKA_BROKERSstring--Comma-separated broker addresses (e.g., kafka1:9092,kafka2:9092)
APP_ENV_KAFKA_CLIENT_IDstring--Kafka client identifier
APP_ENV_KAFKA_GROUP_IDstring--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:

  1. .env -- base defaults
  2. .env.local -- local overrides
  3. .env.{NODE_ENV} -- environment-specific values (e.g., .env.development)
  4. .env.{NODE_ENV}.local -- environment-specific local overrides

17. Complete .env.example

bash
# =============================================
# 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-group

18. Usage in Code

Reading Variables

typescript
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

typescript
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

bash
# .gitignore
.env.local
.env.*.local
.env.production

Use Different Secrets Per Environment

bash
# 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

yaml
# 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_SECRET
  • APP_ENV_APPLICATION_SECRET
  • APP_ENV_POSTGRES_PASSWORD
  • APP_ENV_MINIO_SECRET_KEY
  • APP_ENV_MAIL_CLIENT_SECRET
  • APP_ENV_VNPAY_TVAN_API_KEY

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.