How to configure and use Environment Variables in NestJS
Tags: beginners, nestjs, javascript, tutorial
Published: 2023-01-20 11:14:59

[NestJS](https://docs.nestjs.com) is a framework in Node.js for building efficient, scalable server-side applications and also supports [Typescript](https://www.typescriptlang.org) 😍

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:

```javascript
PORT=5000
NODE_ENV=development
API_URL=https://api.com
MONGODB_CONNECTION_STRING=mongodb@clusterdatabase
```

If you are working with [git](https://git-scm.com/) (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**

```javascript
.env.local
.env.development.local
.env.test.local
.env.production.local
```


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

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

```typescript
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
 }
}
```

```typescript
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'
   }
 }
});
```

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

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

## 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`.

```typescript
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()}`);
```

## 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](https://axios-http.com/docs/intro) 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](https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory) to inject dependencies.

```typescript
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]
    })
  ]
})
```

## 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](https://mongoosejs.com), one of the methods that NestJs supports to integrate with [MongoDB](https://www.mongodb.com/home) database.

```typescript
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]
  },
];
```

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!🖖