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.