Deploy a Node.js App to AWS Lambda
Deploy a Node.js app with an encrypted .env.vault file to AWS Lambda.
Find a complete code example on GitHub for this guide.
Initial setup
Create an aws-lambda project using node-lambda.
npx node-lambda@latest setup
This will create a handful of files.
ls -1a
.env
context.json
deploy.env
event.json
event_sources.json
Create an index.js file that includes process.env.HELLO.
index.js
exports.handler = function(event, context, callback) {
console.log(`Hello ${process.env.HELLO}.`)
callback(null, event)
}
Visit your IAM Dashboard and click Users > Add user. Enter node-lambda for the username and click 'Next'.
On the next screen, attach a policy directly, search for AWSLambda_FullAccess, and select it. Click 'Next'.
Finish creating that user and then on the user's page, generate an access key.
Grab the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from the UI and paste into your .env file.
.env
AWS_ENVIRONMENT=development
AWS_ACCESS_KEY_ID="AKAI6..."
AWS_SECRET_ACCESS_KEY="YiuNa..."
AWS_PROFILE=
AWS_SESSION_TOKEN=
AWS_ROLE_ARN=
AWS_REGION=us-east-1
AWS_FUNCTION_NAME=
AWS_HANDLER=index.handler
AWS_MEMORY_SIZE=128
AWS_TIMEOUT=3
AWS_DESCRIPTION=
AWS_RUNTIME=nodejs16.x
AWS_VPC_SUBNETS=
AWS_VPC_SECURITY_GROUPS=
AWS_TRACING_CONFIG=
AWS_LOGS_RETENTION_IN_DAYS=
EXCLUDE_GLOBS="event.json build/"
PACKAGE_DIRECTORY=build
Deploy your lambda code.
npx node-lambda@latest deploy
Test invocation of your function.
It will respond with Hello undefined as it doesn't have a way to access the environment variable yet. Let's do that next.
Install dotenv
Install dotenv.
npm install dotenv --save # Requires dotenv >= 16.1.0
As early as possible in your function, import and configure dotenv.
index.js
require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working
exports.handler = function(event, context, callback) {
...
Next let's build the .env.vault file.
Build .env.vault
Push your latest .env file changes and edit your production secrets. Learn more about syncing
npx dotenv-vault@latest push
npx dotenv-vault@latest open production
Use the UI to configure those secrets per environment.
Then build your encrypted .env.vault file.
npx dotenv-vault@latest build
Its contents should look something like this.
.env.vault
#/-------------------.env.vault---------------------/
#/ cloud-agnostic vaulting standard /
#/ [how it works](https://dotenv.org/env-vault) /
#/--------------------------------------------------/
# development
DOTENV_VAULT_DEVELOPMENT="/HqNgQWsf6Oh6XB9pI/CGkdgCe6d4/vWZHgP50RRoDTzkzPQk/xOaQs="
DOTENV_VAULT_DEVELOPMENT_VERSION=2
# production
DOTENV_VAULT_PRODUCTION="x26PuIKQ/xZ5eKrYomKngM+dO/9v1vxhwslE/zjHdg3l+H6q6PheB5GVDVIbZg=="
DOTENV_VAULT_PRODUCTION_VERSION=2
Set DOTENV_KEY
Fetch your production DOTENV_KEY.
npx dotenv-vault@latest keys production
# outputs: dotenv://:[email protected]/vault/.env.vault?environment=production
Using the DOTENV_KEY you fetched above, set it as an environment variable on the AWS Lambda dashboard.
Deploy it again.
npx node-lambda@latest deploy
Return to the AWS Console and invoke your function again.
It should say Hello production.
That's it! On invocation, your .env.vault file will be decrypted and its production secrets injected as environment variables – just-in-time.
You succesfully used the new .env.vault standard to encrypt and deploy your secrets. This is much safer than scattering your secrets across multiple third-party platforms and tools. Whenever you need to add or change a secret, just rebuild your .env.vault file and redeploy.