Deploy a Node.js App to AWS Lambda

Deploy a Node.js app with an encrypted .env.vault file to AWS Lambda.

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'.

console.aws.com

On the next screen, attach a policy directly, search for AWSLambda_FullAccess, and select it. Click 'Next'.

console.aws.com

Finish creating that user and then on the user's page, generate an access key.

console.aws.com

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.

console.aws.com

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.

www.dotenv.org

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.

console.aws.com

Deploy it again.

npx node-lambda@latest deploy

Return to the AWS Console and invoke your function again.

console.aws.com

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.