Episode ini membahas manajemen konfigurasi NestJS: modul @nestjs/config, configuration modules, konfigurasi per environment, validation schema, externalized configuration memakai environment variables, serta praktik pengelolaan secrets di development dan production.

Aplikasi production tidak boleh berisi nilai konfigurasi yang di-hard-code — seperti secret database atau API key — langsung di dalam source code. Konfigurasi harus dipisahkan dari kode dan dikelola per environment.
Episode 8 membahas @nestjs/config, konfigurasi per environment, validasi schema, externalized configuration, dan cara aman mengelola secrets.
@nestjs/config adalah modul resmi yang menangani konfigurasi. Install dulu:
npm install @nestjs/configLalu daftarkan di module:
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})
export class AppModule {}Dengan isGlobal: true, ConfigService bisa di-inject di mana saja tanpa perlu mengimpor modul berulang kali.
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class AppConfigService {
constructor(private readonly configService: ConfigService) {}
getPort(): number {
return this.configService.get<number>("PORT", 3000);
}
getNodeEnv(): string {
return this.configService.get<string>("NODE_ENV", "development");
}
}configService.get("PORT", 3000) membaca nilai dengan fallback default jika tidak ditemukan.
ConfigModule.forRoot() membaca file .env di root project. Untuk environment berbeda, kita bisa memakai file yang berbeda:
PORT=3000
DATABASE_URL=sqlite:data.sqlite
JWT_SECRET=rahasia-developmentUntuk production, nilai disuntikkan dari environment variable sistem atau secret manager, bukan dari file .env yang ter-commit.
Untuk mengelompokkan konfigurasi, buat factory function:
export default () => ({
port: parseInt(process.env.PORT ?? "3000", 10),
database: {
url: process.env.DATABASE_URL,
},
});Lalu arahkan ConfigModule ke file ini:
ConfigModule.forRoot({
load: [configuration],
})Salah konfigurasi sebaiknya dideteksi saat aplikasi start, bukan runtime. Gunakan Joi untuk validasi:
npm install joiimport * as Joi from "joi";
ConfigModule.forRoot({
validationSchema: Joi.object({
NODE_ENV: Joi.string()
.valid("development", "production", "test")
.default("development"),
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
}),
})Jika variabel yang di-required tidak ada, aplikasi langsung gagal start dengan pesan yang jelas.
Prinsip externalized configuration: kode yang sama berjalan di semua environment, dan nilai konfigurasi disuntikkan dari luar. Ini memungkinkan deploy yang sama ke staging dan production tanpa mengubah kode.
PORT=8080 DATABASE_URL=postgres://user:pass@host/db npm run start:prodDi development, .env cukup. Di production, secret sebaiknya disimpan di secret manager — seperti AWS Secrets Manager, HashiCorp Vault, atau fitur secrets bawaan platform deployment. Jangan pernah menaruh secret di repository, termasuk file .env yang ter-commit.
.env
.env.local
.env.*.localDengan .gitignore di atas, file env lokal tidak akan pernah ikut ter-commit ke Git.
Episode 8 membuat aplikasi kalian siap berpindah environment tanpa mengubah kode: @nestjs/config, configuration modules, validation schema, externalized configuration, dan praktik secrets yang aman.
Inti yang harus dibawa pulang:
ConfigModule.forRoot() membaca file .env dan mengekspos ConfigService.isGlobal: true membuat ConfigService bisa di-inject di mana saja.Di episode 9 selanjutnya kita akan membahas logging, monitoring, dan health — built-in logger dan custom logger service, integrasi Winston dan Pino, health checks dengan @nestjs/terminus, serta pola observability dasar untuk metrics.