In this post, I’ll be describing the process of automatically deploying an API built with Express.js to AWS API Gateway using claudia.js and GitHub actions.

Setting up your AWS credentials

I’ll assume you have you AWS ID and secret set up on your machine. In case you don’t, take a look here.

I recommend creating a profile with an user that has only the permissions required by claudia (AWSLambdaFullAccess, IAMFullAccess and AmazonAPIGatewayAdministrator).

Setting up claudia

In case you are not familiar with it, claudia.js is a open-source deployment tool aimed at making the process of deploying a Node.js project to AWS Lambda easier.

I’ll summarize what we will need to configure, but if you run into any issues check their official documentation. First, go ahead and install it globally:

npm install claudia -g

Updating your project

If you are developing using Express, you probably have something among this lines in your app.js:

'use strict'

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

In order to use claudia, we’ll have to export app instead of start listening. You should have something like this instead:

'use strict'

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

module.exports = app;

This will prevent you from running you API locally. If you want to, you can create a file called app.local.js with the following content:

'use strict'

var app = require('./app');

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

And start your server locally using it.

Creating the proxy

In order for your app to run on Lambda, you’ll have to use a proxy. To create it, simply run

claudia generate-serverless-express-proxy --express-module app

This should create a lambda.js file in your project’s root folder. Add it to source control.

Creating the API

Run the following command to deploy your API to API Gateway:

claudia create --version [version] --config api-config.json --region [region] --handler lambda.handler --deploy-proxy-api --name [name] --profile [profile]

Replacing the values between square brackets for the appropriate value.

Parameter Description
version Stage of your API (e.g. dev, prod)
region AWS region to deploy to (e.g us-east-1)
name The name of the API to be created on API Gateway
profile The profile you defined in your .aws/credentials file (e.g. devops-credentials)


A file named api-config.json should have been created. Add it to source control.

Setting up your secrets on GitHub

In a web browser, navigate to you repository page and then to Settings > Secrets.

In here, add a key called AWS_ACCESS_KEY_ID and another called AWS_SECRET_ACCESS_KEY with the appropriate values. Also add keys for any other environment variables you want passed to your API (e.g. JWT secret, database connection string, etc.)

Creating GitHub Actions

Back to your code editor, navigate to the folder .github\workflows (create it if it doesn’t exist). Create a file called deploy.yml.

Add the following content:

name: Send to AWS (dev)

# This action runs when we push to dev
on:
  push:
    branches:
    - dev

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    # This step configures the AWS credentials used by claudia
    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        # Replace this with the region you want to deploy to
        aws-region: us-east-1
    # This step converts the variables you defined as GitHub secrets to a JSON
    # This JSON will later be loaded by claudia and passed onto the API
    - name: Create environment JSON
      id: create-env
      uses: schdck/create-env-json@v1
      with:
        file-name: "./env.dev.json"
        # Declare here the variables you want to be passed to your API
        STAGE: "DEV"
        JWT_KEY: ${{ secrets.JWT_SECRET_DEV }}
        MONGO_URL: $\{{ secrets.MONGO_URL_DEV }}
    # This step will install claudia globally and build/test your code
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: '12.x'
    - name: npm install, build, and test
      run: |
        npm install
        npm install -g claudia
        npm run build --if-present
        npm test
      env:
        CI: true
    # This step will actually deploy your files to API Gateway
    - name: Send files to AWS
      run: claudia set-version --version dev --config api-config.json --set-env-from-json $

If you want, you can create a release.yml that is run when pushes are made to master. Just remember to change the --version flag on the last step of the Action and the environment variables you are loading.

The reason I had to use an intermediate Action to convert the environment variables to JSON was that my environment variable’s values contained commas (,). Because of that, I could not pass them directly using claudia’s --set-env. If this is not your case, you can remove that step and modify the last one to pass your variables straight into the command line.



That’s it for today. As always, if you have any questions or feedback, please drop me a line 🙂