DEV Community

Cover image for How to configure and use Environment Variables in NestJS
Elizabeth Morillo for One Beyond

Posted on

How to configure and use Environment Variables in NestJS

NestJS is a framework in Node.js for building efficient, scalable server-side applications and also supports Typescript 😍

In this article I’ll show you how to set up the Environment Variables. These variables are used to store sensitive information, secrets and configuration data. Having this information hardcoded in your code is a huge security flaw and not a best practice.

Without further ado, let’s begin!

Set up a .env file

Let’s start by creating the most popular file to store and manage our Environment Variables, a file named .env at the root of your project. Here’s some example variables:

PORT=5000
NODE_ENV=development
API_URL=https://api.com
MONGODB_CONNECTION_STRING=mongodb@clusterdatabase
Enter fullscreen mode Exit fullscreen mode

If you are working with git (version control system), you should keep all your .env files out of version control, as it’s not information we want to share or upload to an open-source platform like GitHub. This means you avoid sharing all sensitive information with the whole world!

Always add your .env files to your .gitignore

.env.local
.env.development.local
.env.test.local
.env.production.local
Enter fullscreen mode Exit fullscreen mode

Custom Configuration file and ConfigProps

In the previous step we created a .env file with several Environment Variables, so the main idea for this step is to create a single directory for handling those variables. Instead of calling process.env in all the files we need, we’re going to create a custom configuration file. These files will return a nested object grouped by functions (settings, database), which will allow us to manage our variables in a more independent and orderly way. In the future, if we need to change some name or value, it will be as simple as opening a single file.

Let’s create in the src directory the next folders and files

src
├── config 
│   └── config.ts
├── interfaces
│   └── config.interface.ts
Enter fullscreen mode Exit fullscreen mode

The interface it’s going to be the structure type-checking for our config.ts file, once created we just need to export it.

config.interface.ts

interface ApiConfigProps {
 apiUrl: string
 httpTimeout: number
}

interface MongodbConfigProps {
 connectionString: string
 databaseName: string
}


export interface ConfigProps {
 port: number
 api: ApiConfigProps
 mongodb: {
   database: MongodbConfigProps
 }
}
Enter fullscreen mode Exit fullscreen mode
config.ts

export const config = ():ConfigProps => ({
 port: parseInt(process.env.PORT, 10) || 8080,
 api: {
   apiUrl: process.env.API_URL,
   httpTimeout: 1000,
 },
 mongodb: {
   database: {
     connectionString: process.env.MONGODB_CONNECTION_STRING || 'mongodb://localhost:27017',
     databaseName: process.env.NODE_ENV || 'local'
   }
 }
});
Enter fullscreen mode Exit fullscreen mode

NestJS configuration

To begin, we need to start by installing the required dependency.

npm i --save @nestjs/config

Once we have it installed, we import it in our root module AppModule, it's important to add it along with the method .forRoot() , as this method will allow us to register our ConfigService as a provider (dependency injection) and give us access to the .get() method which we will see later.

In order to use the custom config file globally in our application, we have to add a couple of settings to our ConfigModule options object. This is how should look like:

import { ConfigModule } from '@nestjs/config';
import { config } from './config/configuration';
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [config]
    })]
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Using ConfigService in main.ts

As we already have everything correctly configured, we can now access all the values in the config file. In the main.ts file, the PORT value is hardcoded by default. This value should be assigned to an Environment Variable and not have it written directly in the code, so we are going to change it by using the one that we have saved in the ConfigService.

import { ConfigService } from '@nestjs/config';

const configService = app.get(ConfigService);
const port = configService.get<number>('port');

await app.listen(port);
Logger.log(`~ Application is running on: ${await app.getUrl()}`);
Enter fullscreen mode Exit fullscreen mode

Use ConfigService in modules

For using our config file in a module we only have to import the ConfigService and access the method .get(). Let’s use as example an HTTP client module as is HTTP module, which is basically a module that wraps Axios and exposes all the methods to be able to use them.

We are going to declare our HTTP module and pass ​​options asynchronously with the values from our config file by adding a factory provider to inject dependencies.

import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule,
    HttpModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        baseURL: configService.get<string>('api.apiUrl'),
        timeout: configService.get<number>('api.httpTimeout')
      }),
      inject: [ConfigService]
    })
  ]
})
Enter fullscreen mode Exit fullscreen mode

Using ConfigService in providers

To conclude, we will give an example of how to integrate our config file in a provider such as the database. For this we are going to use the object modeling tool Mongoose, one of the methods that NestJs supports to integrate with MongoDB database.

export const databaseProviders = [
  {
    imports: [ConfigModule],
    provide: 'CONNECTION',
    useFactory: async (configService: ConfigService): Promise<typeof mongoose> => {
      const connectionData = {
        host: configService.get<string>('mongodb.database.connectionString'),
        databaseName: configService.get<string>('mongodb.database.databaseName')
      };
      const connection = await mongoose.connect(`${connectionData.host}`); 
      return connection;
    },
    inject: [ConfigService]
  },
];
Enter fullscreen mode Exit fullscreen mode

Thank you all very much for reading this article and I hope it helps you create great applications and please let me know in the comments what you think about this post or if you have any questions. Thank you so much for reading!

Thank you all and happy coding!🖖

Top comments (1)

Collapse
 
sagarvispute profile image
Sagar Vispute

You have forgotten to provide configuration for package.json, above code will work but with default configuration from .env file not local, test or prod file