Environment Variables
SST has built-in support for loading environment variables from a .env
file into process.env
using dotenv.
This is similar to what Create React App and Next.js do for environment variables.
For example if you add the following .env
file to your project root.
TABLE_READ_CAPACITY=5
TABLE_WRITE_CAPACITY=5
SST will load the process.env.TABLE_READ_CAPACITY
and process.env.TABLE_WRITE_CAPACITY
variables into the Node.js environment; automatically allowing you to use them in your CDK code.
Types of .env
files
Aside from the default .env
file, there are a couple of other types of .env
files. You can use them to better organize the environment variables in your SST app.
.env.$STAGE
You can add a .env.$STAGE
file to override the default values for a specific stage. For example, this overrides the value for the prod
stage:
TABLE_READ_CAPACITY=20
.env*.local
You can also add .env.local
and .env.$STAGE.local
files to set up environment variables that are specific to your local machine.
Priority
Here's the priority in which these files are loaded. Starting with the one that has the highest priority.
.env.dev.local
.env.dev
.env.local
.env
Assume that the current stage is dev
.
Committing .env
files
The .env
and .env.$STAGE
files can be committed to your Git repository. On the other hand, the .env.local
and .env.$STAGE.local
shouldn't.
The .env*.local
files are meant to specify sensitive information specific to your machine. They should be ignored through the .gitignore
file.
caution
Don't commit any .env
files to Git that contain sensitive information.
Note that, SST doesn't enforce these conventions. They are just guidelines that you can use to organize your environment variables. Similar to the ones used by Create React App and Next.js.
Expanding variables
SST will also automatically expand variables ($VAR
). For example:
DEFAULT_READ_CAPACITY=5
USERS_TABLE_READ_CAPACITY=$DEFAULT_READ_CAPACITY
POSTS_TABLE_READ_CAPACITY=$DEFAULT_READ_CAPACITY
If you are trying to use a variable with a $
in the actual value, it needs to be escaped, \$
.
NAME=Spongebob
# becomes "Hi Spongebob"
GREETING=Hi $NAME
# becomes "Hi $NAME"
GREETING=Hi \$NAME
Other environment variables
The .env
environment variables will not modify an environment variable that has been previously set. So if you run the following:
NAME=Spongebob
npx sst deploy
While your .env
has.
NAME=Patrick
The .env
value will be ignored and process.env.NAME
will be set to Spongebob
.
Environment variables in Seed
The above idea also applies to environment variables that are set in Seed or other CIs. If you have an environment variable set in Seed, it'll override the one you have set in your .env
files.
Environment variables in Lambda functions
The .env
environment variables are only available in your CDK code.
You can also set them as Lambda environment variables by including them in the Function environment
prop:
new Function(this, "MyFunction", {
handler: "src/api.main",
environment: {
MY_ENV_VAR: process.env.MY_ENV_VAR,
},
});
Or you can use the App's setDefaultFunctionProps
method to set it for all the functions in your app.
export default function main(app) {
app.setDefaultFunctionProps({
environment: { MY_ENV_VAR: process.env.MY_ENV_VAR },
});
new MySampleStack(app, "sample");
}
Built-in environment variables
IS_LOCAL
SST sets the IS_LOCAL
environment variable to true
by default when running inside sst start
, the Live Lambda Development environment.
The process.env.IS_LOCAL
is set in both the CDK and Lambda function code.
So in your CDK code you can do something like.
function Stack(ctx) {
// Increase the timeout locally
const timeout = process.env.IS_LOCAL
? 900
: 15;
// Rest of the resources
}
And in your Lambda functions.
export async function main(event) {
const body = process.env.IS_LOCAL
? "Hello, Local!"
: "Hello, World!"
return {
body,
statusCode: 200,
headers: { "Content-Type": "text/plain" },
};
}
Working with secrets
While it is common to use .env*.local
files to store sensitive information (and not committing them to Git); the recommended way to work with secrets is to use AWS Systems Manager Parameter Store (SSM).
In this section let's compare the different ways secrets can be managed in SST. You can compare the different strategies and select the one that is right for you.
1. Use the .env*.local
files
- Usage in CDK: Reference via the the
process.env
- Usage in Lambda: Set via the Function's
environment
prop - Local usage: Store the secret in the
.env*.local
files that aren't committed to Git - CI usage: Store the secrets in the CI's dashboard
- Security: GOOD, but the secrets are exposed to the CI providers and exposed in the CloudFormation template
2. Fetch SSM values in CDK using the AWS SDK
Usage in CDK: Use the AWS SDK to fetch the SSM values
Usage in Lambda: Set via the Function's
environment
propLocal usage: Store the SSM paths in a
.env
fileCI usage: SSM paths loaded from the
.env
fileSecurity: BETTER, secrets are not exposed to CI providers, but they are displayed in plain text in Lambda console and the CloudFormation template
In your index file make a all to SSM to fetch the value.
stacks/index.jsimport AWS from "aws-sdk";
export default async function main(app) {
// Fetch SSM value using AWS SDK
const ssm = new AWS.SSM();
const paramRet = await ssm.getParameter({
Name: `/path/to/param`,
}).promise();
const paramValue = paramRet.Parameter.Value;
// Pass value to stack
new MyStack(app, "my-stack", paramValue);
}
3. Fetch SSM values in Lambda using the AWS SDK
- Usage in CDK: Cannot be used in CDK since it is resolved on deploy
- Usage in Lambda: Fetch the SSM values inside a Lambda function using the AWS SDK
- Local usage: Store the SSM paths in a
.env
file - CI usage: SSM paths loaded from the
.env
file - Security: BEST, secrets are not exposed to CI providers, Lambda console, or the CloudFormation template
In summary, while approach #1 is the easiest it is also the least secure. On the other hand #3 is the most secure but is not as easy to implement. We recommend using .env
for variables that aren't as sensitive and relying on SSM for the most sensitive values.