What is serverless-dotenv-plugin?
The serverless-dotenv-plugin is a Serverless Framework plugin that automatically loads environment variables from a .env file into your serverless project. This allows you to manage environment-specific configurations and secrets in a centralized and secure manner.
What are serverless-dotenv-plugin's main functionalities?
Load Environment Variables
This feature allows you to load environment variables from a .env file into your serverless project. The code sample demonstrates how to configure the serverless-dotenv-plugin in the serverless.yml file and access an environment variable in a function.
module.exports = {
service: 'my-service',
plugins: ['serverless-dotenv-plugin'],
provider: {
name: 'aws',
runtime: 'nodejs14.x'
},
functions: {
hello: {
handler: 'handler.hello',
environment: {
MY_ENV_VAR: process.env.MY_ENV_VAR
}
}
}
};
Custom .env File Path
This feature allows you to specify a custom path for your .env file. The code sample shows how to configure the plugin to load environment variables from a .env file located in a custom directory.
module.exports = {
service: 'my-service',
plugins: ['serverless-dotenv-plugin'],
custom: {
dotenv: {
path: './config/.env'
}
},
provider: {
name: 'aws',
runtime: 'nodejs14.x'
},
functions: {
hello: {
handler: 'handler.hello',
environment: {
MY_ENV_VAR: process.env.MY_ENV_VAR
}
}
}
};
Multiple Environment Files
This feature allows you to use different .env files for different environments. The code sample demonstrates how to configure the plugin to load environment variables from different .env files based on the environment.
module.exports = {
service: 'my-service',
plugins: ['serverless-dotenv-plugin'],
custom: {
dotenv: {
path: {
development: './config/.env.development',
production: './config/.env.production'
}
}
},
provider: {
name: 'aws',
runtime: 'nodejs14.x'
},
functions: {
hello: {
handler: 'handler.hello',
environment: {
MY_ENV_VAR: process.env.MY_ENV_VAR
}
}
}
};
Other packages similar to serverless-dotenv-plugin
dotenv
dotenv is a popular package for loading environment variables from a .env file into process.env. It is widely used in Node.js applications but does not have built-in support for the Serverless Framework. You would need to manually integrate it into your serverless project.
serverless-secrets-plugin
serverless-secrets-plugin is another Serverless Framework plugin that helps manage secrets and environment variables. It integrates with AWS Secrets Manager to securely store and retrieve secrets. Unlike serverless-dotenv-plugin, it focuses on using AWS Secrets Manager rather than .env files.
serverless-env-generator
serverless-env-generator is a plugin that generates environment variables for your serverless project based on a configuration file. It provides more flexibility in generating environment variables but requires additional configuration compared to serverless-dotenv-plugin.
serverless-dotenv-plugin
![npm version](https://img.shields.io/npm/v/serverless-dotenv-plugin.svg?style=flat)
Preload environment variables into serverless. Use this plugin if you have variables stored in a .env
file that you want loaded into your serverless yaml config. This will allow you to reference them as ${env:VAR_NAME}
inside your config and it will load them into your lambdas.
Install and Setup
First, install the plugin:
> npm i -D serverless-dotenv-plugin
Next, add the plugin to your serverless config file:
service: myService
plugins:
- serverless-dotenv-plugin
...
Now, just like you would using dotenv in any other JS application, create your .env
file in the root of your app:
DYNAMODB_TABLE=myTable
AWS_REGION=us-west-1
AUTH0_CLIENT_ID=abc12345
AUTH0_CLIENT_SECRET=12345xyz
Once loaded, you can now access the vars using the standard method for accessing ENV vars in serverless:
...
provider:
name: aws
runtime: nodejs6.10
stage: ${env:STAGE}
region: ${env:AWS_REGION}
...
Automatic ENV File Resolution
By default, the plugin looks for the file: .env
. In most use cases this is all that is needed. However, there are times where you want different env files based on environment. For instance:
.env.development
.env.production
When you deploy with NODE_ENV
set: NODE_ENV=production sls deploy
the plugin will look for files named .env
, .env.production
, .env.production.local
. If for some reason you can't set NODE_ENV, you could always just pass it in as an option: sls deploy --env production
or sls deploy --stage production
. If NODE_ENV
, --env
or --stage
is not set, it will default to development
.
The precedence between the options is the following:
NODE_ENV
> --env
> --stage
The env resolution pattern follows the one used by Rail's dotenv and create-react-app
Valid .env file names | Description |
---|
.env | Default file, always included |
.env.local | Included in all environments except test |
.env.development | If NODE_ENV or --env or --stage is not set, will try to load .env.development . |
.env.{ENV} | If NODE_ENV or --env or --stage is set, will try to load .env.{env} . |
.env.{ENV}.local | Every env set up in .env.{ENV}.local will override other envs |
Note: .env, .env.development, and .env.production files should be included in your repository as they define defaults. .env*.local should be added to .gitignore, as those files are intended to be ignored. .env.local is where secrets can be stored.
Lambda Environment Variables
Again, remember that when you deploy your service, the plugin will inject these environment vars into every lambda functions you have and will therefore allow you to reference them as process.env.AUTH0_CLIENT_ID
(Nodejs example). If this behaviour is not desireable, set include
to []
.
Plugin options
All options are optional.
custom:
dotenv:
path: path/to/my/dotenvfiles
dotenvParser: dotenv.config.js
include:
- DDB_TABLE
- S3_BUCKET
exclude:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
- NODE_ENV
logging: true
required:
env:
- API_KEY
file: true
variableExpansion: false
Example dotenvParser
file:
const dotenv = require('dotenv')
const dotenvExpand = require('dotenv-expand')
module.exports = function({ dotenv, paths }) {
const envVarsArray = [...paths]
.reverse()
.map(path => {
const parsed = dotenv.config({ path })
return dotenvExpand(parsed).parsed
})
return envVarsArray.reduce((acc, curr) => ({ ...acc, ...curr }), {})
}
Examples
You can find example usage in the examples
folder.
FAQ
This plugin loads the dotenv environment variables inside the plugin constructor. Aside from legacy reasons, this also means all your dotenv environment variables are available to the other plugins being loaded.
However, Serverless variables are not resolved in the constructor:
Variable references in the serverless instance are not resolved before a Plugin's constructor is called, so if you need these, make sure to wait to access those from your hooks.
~https://www.serverless.com/framework/docs/providers/aws/guide/plugins/#plugins/
This is important for several FAQ items below.
Why doesn't the basePath
or path
options support Serverless variables?
Because Serverless variables have not been interpolated when this plugin runs, basePath
and path
will always be treated like literal strings (e.g. ${opt:stage}
would be presented to the plugin, not the passed in via --stage
). The suggested pattern is to store all your dotenv files in one folder, and rely on NODE_ENV
, --env
, or --stage
to resolve to the right file.
There are no plans to support anything other than literal strings at this time, although you are free to discuss this in #52.
Why doesn't this plugin work when provider.environment
references another file?
This plugin manipuluates provider.environment
directly by adding to the list. Because Serverless variables have not been interpolated when this plugin runs, provider.environment
is presented to this plugin uninterpolated (e.g. ${file(./serverless-env.yml):environment}
), this plugin is unable to manipulate it.
To work around this, you can set the include
option to []
to avoid adding any environment variables to provider.environment
. However, this means you will have to wire up the environment variables yourself by referencing every single one you need. E.g.
provider:
environment:
- DDB_TABLE: ${env:DDB_TABLE}
More details are available at #38.
Contributing
Because of the highly dependent nature of this plugin (i.e. thousands of developers depend on this to deploy their apps to production) I cannot introduce changes that are backwards incompatible. Any feature requests must first consider this as a blocker. If submitting a PR ensure that the change is developer opt-in only meaning it must guarantee that it will not affect existing workflows, it's only available with an opt-in setting. I appreciate your patience on this. Thanks.