In NestJS, configuration management is critical as it involves securely handling environment variables, configuration files, and sensitive data. NestJS provides multiple ways to manage and inject configurations, including the @nestjs/config module. Below is a detailed explanation of configuration management in NestJS v10.
Installing the Configuration Module
First, you need to install the @nestjs/config module.
npm install @nestjs/configConfiguring the Global Module
To use the configuration module throughout the application, configure it in app.module.ts as follows:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
// Import the configuration module globally
ConfigModule.forRoot({
isGlobal: true, // Set as global configuration
envFilePath: ['.env'], // Specify the environment variable file
validationSchema: Joi.object({ // Optional: Use Joi for schema validation
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
}),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Using Environment Variables
You can define environment variables in a .env file, for example:
# .env file
PORT=3000
DATABASE_URL=postgres://user:password@localhost:5432/dbnameThen, use the ConfigService to access these values in services or controllers:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Controller()
export class AppController {
constructor(private readonly configService: ConfigService) {}
@Get()
getHello(): string {
const port = this.configService.get<number>('PORT');
const dbUrl = this.configService.get<string>('DATABASE_URL');
return `Hello World! Running on port ${port}, connected to ${dbUrl}`;
}
}Using Configuration Files
In addition to environment variables, you can use JSON or TypeScript files to store configurations. For example, create a config directory and add a database.ts file:
// config/database.ts
export default {
type: process.env.DATABASE_TYPE,
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT),
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
};Then, import and use it in app.module.ts:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import databaseConfig from './config/database';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [databaseConfig], // Load configuration file
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Injecting Configuration
Inject configuration into services:
// app.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppService {
constructor(private readonly configService: ConfigService) {}
getHello(): string {
const dbConfig = this.configService.get('database');
return `Hello World! Database config: ${JSON.stringify(dbConfig)}`;
}
}Environment-Specific Configuration
You can use different .env files for different environments, such as .env.development, .env.production, etc.
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env', `.env.${process.env.NODE_ENV}`], // Automatically select based on NODE_ENV
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Configuration Validation
You can use Joi or other validation libraries to validate configurations:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import Joi from 'joi';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
}),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Dynamic Configuration
You can use dynamic configuration to load specific configuration files:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [`.env.${process.env.NODE_ENV}`], // Dynamically select environment file
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Using TypeORM
If you are using TypeORM, you can configure database connections through the configuration:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { User } from './entities/user.entity';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env'],
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: [User],
synchronize: true,
}),
inject: [ConfigService],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Using Other Configuration Tools
In addition to @nestjs/config, you can use other tools like dotenv or yargs to handle command-line arguments or environment variables.
Configuration Example
Below is a complete example including the use of a .env file, configuration files, and TypeORM database configuration.
app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { User } from './entities/user.entity';
import databaseConfig from './config/database';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env', `.env.${process.env.NODE_ENV}`],
load: [databaseConfig],
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: [User],
synchronize: true,
}),
inject: [ConfigService],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}.env File
# .env file
PORT=3000
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjsapp.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly configService: ConfigService, private readonly appService: AppService) {}
@Get()
getHello(): string {
const port = this.configService.get<number>('PORT');
const dbConfig = this.configService.get('database');
return `Hello World! Running on port ${port}, connected to ${JSON.stringify(dbConfig)}`;
}
}app.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppService {
constructor(private readonly configService: ConfigService) {}
getHello(): string {
const dbConfig = this.configService.get('database');
return `Hello World! Database config: ${JSON.stringify(dbConfig)}`;
}
}config/database.ts
// config/database.ts
import { ConfigService } from '@nestjs/config';
export default () => ({
type: process.env.DATABASE_TYPE,
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT),
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
});Using .env Files
Define environment variables in the .env file:
# .env file
PORT=3000
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjsUsing .env.development and .env.production
Create environment-specific .env files:
# .env.development
PORT=3001
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_dev
# .env.production
PORT=3000
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjs_prodUsing .env.test
For the test environment, create a .env.test file:
# .env.test
PORT=3002
DATABASE_TYPE=sqlite
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_testUsing .env.example
To help new team members understand how to configure the .env file, create a .env.example file as a template:
# .env.example
PORT=3000
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjsUsing .env.local
To allow developers to override default configurations, create a .env.local file:
# .env.local
PORT=3003
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjs_localUsing .env.ci
For continuous integration environments, create a .env.ci file:
# .env.ci
PORT=3004
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_ciUsing .env.staging
For staging environments, create a .env.staging file:
# .env.staging
PORT=3005
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjs_stagingUsing .env.docker
For Docker environments, create a .env.docker file:
# .env.docker
PORT=3006
DATABASE_TYPE=postgres
DATABASE_HOST=postgres
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjs_dockerUsing .env.k8s
For Kubernetes environments, create a .env.k8s file:
# .env.k8s
PORT=3007
DATABASE_TYPE=postgres
DATABASE_HOST=postgres-service
DATABASE_PORT=5432
DATABASE_USERNAME=user
DATABASE_PASSWORD=password
DATABASE_DATABASE=nestjs_k8sUsing .env.aws
For AWS environments, create a .env.aws file:
# .env.aws
PORT=3008
DATABASE_TYPE=rds
DATABASE_HOST=database-1.cjgqy5kx907r.us-east-1.rds.amazonaws.com
DATABASE_PORT=5432
DATABASE_USERNAME=admin
DATABASE_PASSWORD=admin123
DATABASE_DATABASE=nestjs_awsUsing .env.gcp
For GCP environments, create a .env.gcp file:
# .env.gcp
PORT=3009
DATABASE_TYPE=cloudsql
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_USERNAME=admin
DATABASE_PASSWORD=admin123
DATABASE_DATABASE=nestjs_gcpUsing .env.azure
For Azure environments, create a .env.azure file:
# .env.azure
PORT=3010
DATABASE_TYPE=mssql
DATABASE_HOST=server.database.windows.net
DATABASE_PORT=1433
DATABASE_USERNAME=admin
DATABASE_PASSWORD=admin123
DATABASE_DATABASE=nestjs_azureUsing .env.heroku
For Heroku environments, create a .env.heroku file:
# .env.heroku
PORT=3011
DATABASE_TYPE=postgres
DATABASE_HOST=dpg-ch4113066g427759l0g0-a.oregon-postgres.render.com
DATABASE_PORT=5432
DATABASE_USERNAME=heroku_user
DATABASE_PASSWORD=heroku_password
DATABASE_DATABASE=nestjs_herokuUsing .env.localhost
For local development environments, create a .env.localhost file:
# .env.localhost
PORT=3012
DATABASE_TYPE=sqlite
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_localUsing .env.travis
For Travis CI environments, create a .env.travis file:
# .env.travis
PORT=3013
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_travisUsing .env.circleci
For CircleCI environments, create a .env.circleci file:
# .env.circleci
PORT=3014
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_circleciUsing .env.github
For GitHub Actions environments, create a .env.github file:
# .env.github
PORT=3015
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_githubUsing .env.gitlab
For GitLab CI environments, create a .env.gitlab file:
# .env.gitlab
PORT=3016
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_gitlabUsing .env.bitbucket
For Bitbucket Pipelines environments, create a .env.bitbucket file:
# .env.bitbucket
PORT=3017
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_bitbucketUsing .env.netlify
For Netlify environments, create a .env.netlify file:
# .env.netlify
PORT=3018
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_netlifyUsing .env.vercel
For Vercel environments, create a .env.vercel file:
# .env.vercel
PORT=3019
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=root
DATABASE_DATABASE=nestjs_vercel



