node dotenv won't work with pm2

2 min read 06-10-2024
node dotenv won't work with pm2


Why Your .env Variables Aren't Loading with PM2 and How to Fix It

Using dotenv to manage environment variables is a common practice in Node.js applications. However, when you deploy your app with PM2, you might find that your .env variables aren't loaded, leading to errors or unexpected behavior. This article will explain why this happens and guide you on how to fix it.

The Problem:

PM2, a popular process manager for Node.js applications, creates a separate environment for your application. This means that the environment variables set within your dotenv configuration are not directly accessible by the PM2-managed process.

Scenario:

Let's say you have a Node.js application that uses a .env file to store sensitive information like database credentials:

// app.js
require('dotenv').config();

const databaseUrl = process.env.DATABASE_URL;

// ... rest of your app logic

When you run the app directly using node app.js, everything works fine. However, when you start the application with PM2 using pm2 start app.js, you might get an error like DATABASE_URL is not defined.

Why this Happens:

  • Isolated Environments: PM2 creates an isolated environment for each process. The .env file is loaded in the context of your original process, not the PM2-managed process.
  • Process Isolation: PM2 utilizes fork to create child processes, which results in an isolated environment for each process.

Solution:

There are a few ways to solve this issue:

  1. Passing Environment Variables to PM2:

    You can set environment variables directly in your PM2 configuration file (ecosystem.config.js):

    module.exports = {
      apps: [{
        name: 'my-app',
        script: 'app.js',
        env: {
          DATABASE_URL: 'your_database_url',
          API_KEY: 'your_api_key'
        }
      }]
    };
    

    Now, start your app with PM2: pm2 start ecosystem.config.js. Your environment variables will be available within your application.

  2. Using PM2 Ecosystem Variables:

    PM2 allows you to define variables within your ecosystem.config.js that can be accessed by your application:

    module.exports = {
      apps: [{
        name: 'my-app',
        script: 'app.js',
        env_production: {
          DATABASE_URL: 'your_database_url',
          API_KEY: 'your_api_key'
        }
      }]
    };
    

    In your app.js:

    // app.js
    const { DATABASE_URL } = process.env;
    
    // ... rest of your app logic
    

    PM2 will automatically inject these variables into your process environment.

  3. Loading .env Within Your PM2 Script:

    You can load .env within your PM2 configuration using the env_production.post_setup property:

    module.exports = {
      apps: [{
        name: 'my-app',
        script: 'app.js',
        env_production: {
          NODE_ENV: 'production'
        },
        env_production: {
          post_setup: 'npm run build && source .env'
        }
      }]
    };
    

    This approach ensures .env is loaded within the PM2 environment.

Additional Considerations:

  • Security: Always store sensitive information in environment variables, never commit them directly to your source code.
  • Environment-Specific Configurations: Use PM2's env_production, env_development, etc., to manage different environment configurations.
  • Error Handling: Implement robust error handling to gracefully handle cases where environment variables are not available.

Conclusion:

Using dotenv with PM2 requires some extra steps to ensure environment variables are properly loaded. By understanding the isolation mechanisms of PM2 and using the correct techniques, you can effectively manage your application's environment variables and ensure a seamless deployment process.