Search code examples
javascriptnode.jstypescriptnestjsnestjs-config

How do I use different config files for environment variables, ensuring that these files are distinct for development and production environments?


I'm currently developing a NestJS application and want to manage environment variables using different configuration files for development and production environments. I understand that it's common practice to separate configurations to avoid accidentally exposing sensitive information or misconfiguring settings.

I would like to know the best approach to achieve this in a NestJS application. Specifically, I'm looking for guidance on:

How to create and structure separate configuration files (e.g., .env.development and .env.production). How to load the appropriate configuration file based on the environment (e.g., using NODE_ENV). Any recommended libraries or modules to facilitate this process (e.g., @nestjs/config).


Solution

  • You should manage the prod/preprod variables at the infrastructure layer rather than in the development environment. Any secrets must be encrypted and stored securely like in a vault service, and loaded during the cicd pipeline execution

    1. Production for production and preprod store secrets and env variables in a secure vault, like AWS Secrets Manager``Azure key vault or HashiCorp vault` etc. this way all secrets are encrypted and can be accessed securely

    Use your cicd pipeline (GitHub Actions circleci etc.) to load environment variables from the vault and inject them into your application during deployment

    2. Local Development: for local development you can use .env files for the configuration. But avoid committing these files to VCS like github or gitlab etc.

    I think it is apparent from your question that you would use the @nestjs/config and dotenv dependency for loading the ennviroment variables

    inside app.module.ts

    import { Module } from '@nestjs/common';
    import { ConfigModule } from '@nestjs/config';
    import * as process from 'process';
    import * as path from 'path';
    
    const envFilePath = path.resolve(
      process.cwd(),
      `.env.${process.env.NODE_ENV || 'development'}`,
    );
    
    @Module({
      imports: [
        ConfigModule.forRoot({
          envFilePath: envFilePath,
          isGlobal: true,
        })
      ],
    
    })
    export class AppModule {}
    

    you can now use the config service to access the env variables

    import { Injectable } from '@nestjs/common';
    import { ConfigService } from '@nestjs/config';
    
    @Injectable()
    export class AppService {
      constructor(private configService: ConfigService) {}
    
      getDatabaseConfig() {
        const host = this.configService.get<string>('DATABASE_HOST');
        const port = this.configService.get<number>('DATABASE_PORT');
        const user = this.configService.get<string>('DATABASE_USER');
        const password = this.configService.get<string>('DATABASE_PASSWORD');
    
        return {
          host,
          port,
          user,
          password,
        };
      }
    }
    

    make sure you add this variable in your env file

    NODE_ENV=development
    

    NestJs has a very detailed documentation, read more about this here: https://docs.nestjs.com/techniques/configuration