Deploying a REST API with AWS App Runner and Fauna
Tags: fauna, aws, devops, node
Published: 2021-09-16 14:57:42

[AWS App Runner](https://aws.amazon.com/apprunner/) is a [new service from AWS](https://aws.amazon.com/blogs/aws/app-runner-from-code-to-scalable-secure-web-apps/) that allows you to run and scale web applications in only a few clicks. App Runner can build and deploy containers for you directly from your GitHub repo, freeing you from Dockerfile creation and management. The service also hides the complexity of VPC configuration. In short, with App Runner, you write it, AWS runs it.

In this post, you use App Runner to deploy a REST API in minutes using [Express.js](https://expressjs.com) and [Fauna](https://fauna.com), the data API for modern applications. You create a database in Fauna and securely store an access key in [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html). You clone an Express.js application that performs CRUD operations on your data in Fauna. Finally, you launch an App Runner service that builds, deploys, and runs your code.

### Pre-requisites

To follow along with this post you must have access to a Fauna account, a GitHub account, and an AWS account. 

* [Register for a free Fauna account](https://dashboard.fauna.com/accounts/register) and benefit from [Fauna’s free tier](https://fauna.com/pricing) while you learn and build. You do not need to provide payment information until you upgrade your plan. 
* [Sign up for a free GitHub account](https://github.com/join) if you do not already have one. 
* Sign up for an AWS account by [following these instructions](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/). AWS also offers a [free tier](https://aws.amazon.com/free/), but you must provide a payment method to create an AWS account.

## Configuring a database in Fauna

[Open the Fauna dashboard](https://dashboard.fauna.com/) and choose “New Database” to create a new database for your application. Enter `aws-app-runner` as the *Database Name*, ensure that *Pre-populate with demo data* is selected, and choose *Save*.

![Creating a new database in Fauna](//images.ctfassets.net/po4qc9xpmpuh/6aHUqt8ALYxYhNxv8r3z0L/7e6d0491244749fd876b8dd095afbcd8/Creating_a_new_database_in_Fauna.png)

Once your database is available, select the *Security* tab and choose *New Key* to create your first key. Accept the defaults of the current database and *Admin* for the role, enter `Parameter Store` as the *Key Name*, and choose *Save* to create a new key.

![Creating a new key in Fauna](//images.ctfassets.net/po4qc9xpmpuh/7nnLofgSKKtbsZjnNZWdPW/f14a68091bdc9ddc596022ea5b1238c8/Creating_a_new_key_in_Fauna.png)

Copy the key’s secret to your clipboard to store in the next step.

![Copying a key's secret in Fauna](//images.ctfassets.net/po4qc9xpmpuh/3vWCSFvnYqRXCN32Fig74j/75887eb668632f3dacac92c42219668b/Copying_a_secret.png)

## Storing secrets in Parameter Store

The key you create in the previous step can perform any action on your database, so you must protect it by storing it securely. App Runner does not offer a built-in way to access secrets securely, so you will store your API key in Parameter Store.

Parameter Store *SecureString* values allow you to encrypt and store secrets and API keys for use in your application. Open [Parameter Store](https://console.aws.amazon.com/systems-manager/parameters) in the AWS Management Console and choose *Create parameter*. Enter `fauna-secret` as the name of your parameter, select *SecureString* as the parameter type, and paste the key you copied in the previous step into the *Value* text box. Choose *Create parameter* to store your key. Parameter Store creates the fauna-secret parameter and displays it on the *My parameters* tab.

![AWS Systems Manager Parameter Store - My parameters](//images.ctfassets.net/po4qc9xpmpuh/6bMYmLd8dJfmW6NEzHVsmW/ad6cdcdca8da98fe65c5689a0dc822a7/my-parameters.png)

## Fork this repository

App Runner installs the "AWS Connector for GitHub" app in your GitHub account to provide access for deployments. To deploy the sample app, you need to fork a copy into your own GitHub account.

1. Open the [sample app repository](https://github.com/fauna-labs/aws-app-runner).
1. Choose the *Fork* button and select an account or organization to fork the repository into. **Note**: If you choose an organization as the destination, you must have permission to create repositories and install apps in that organization.
1. After a few seconds, the forked repository is displayed.

## Deploy with App Runner

The sample app uses the environment variable *FAUNA_SECRET_PARAMETER* to identify the Parameter Store key for retrieving your database secret. **Note**: This is *not* the value of the secret, only its location in Parameter Store. The value of this environment variable is set in your [App Runner config file](https://github.com/fauna-labs/aws-app-runner/blob/d79f5df0f501a3e096466da1f561216b746fddd4/apprunner.yaml#L19). It should match the parameter you created in the section [Storing secrets in Parameter Store](#storing-secrets-in-parameter-store).

To retrieve the value of your secret, you must create an [AWS IAM](https://aws.amazon.com/iam/) role with permission to read from Parameter Store. You assign this role to your App Runner service when you create it in the console.

### Create an AWS IAM role

Open the [Create role](https://console.aws.amazon.com/iam/home?region=us-east-2#/roles$new?step=type) page in the AWS IAM console. As of the creation of this blog post (19 May 2019), App Runner is not a listed service on the *AWS service* tab. Choose *EC2* as a placeholder, and choose *Next: Permissions*.

In the *Attach permissions policies* section, enter *SSMReadOnly* in the search box, select the *AmazonSSMReadOnlyAccess* policy, and choose *Next: Tags* to continue. In the *Add tags (optional)* section that appears, choose *Next: Review*.

Enter *AppRunnerSSMReadOnlyAccess* for the Role name, ensure the *AmazonSSMReadOnlyAccess* [AWS managed policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html) is listed, and choose *Create role*.

![Creating a role](//images.ctfassets.net/po4qc9xpmpuh/8g3GmePtzs9kNYbVbp0w9/9849638d2627ea4cce3ac88789c15ab9/creating-a-role.png)

AWS IAM creates the role and displays a confirmation. Choose *AppRunnerSSMReadOnlyAccess*, select the *Trust relationships* tab, and choose *Edit trust relationship*.

In the Policy Document that appears, change *ec2.amazonaws.com* to *tasks.apprunner.amazonaws.com* and choose *Update Trust Policy*.

![Editing an AWS IAM role's trust relationship](//images.ctfassets.net/po4qc9xpmpuh/39ZH0kQgwqMclvGEdUzUsx/f5b28046ba59dc24802d731d2e492184/editing-trust-relationship.png)

IAM updates the trust policy, allowing the App Runner service to assume the role you create and retrieve parameters from Parameter Store.

### Create an App Runner service

From the [App Runner console](https://console.aws.amazon.com/apprunner/home), choose *Create an App Runner service*. On the *Source and deployment* screen, select *Source code repository* and choose *Add new* to install the AWS Connector for GitHub in the account or organization where you forked the sample repository. The *Create a new connection* wizard walks you through installing the app. Give your connection a name, e.g. `fauna-labs`, install the app if required, make sure the correct account or organization is selected, and choose *Next*.

![Creating a new connection](//images.ctfassets.net/po4qc9xpmpuh/5RkyiSxE64fHQQsFffW2Eu/9606e017723c8254709b91685e1386dd/creating-a-new-connection.png)

Select the connection you create, select the forked repository *aws-app-runner*, and choose to build from the *main* branch. Select *Automatic* to deploy the service every time you push changes to your *main* branch, and choose *Next*.

![Repository and branch settings](//images.ctfassets.net/po4qc9xpmpuh/7tvGjApVWuvuup5T5zUBXQ/717c4898c3572b3225c6e084b5557ab0/repository-and-branch-settings.png)

On the *Configure build* screen select *Use a configuration file* and choose *Next*. This tells App Runner to pull build and run settings from the [appconfig.yaml](https://github.com/fauna-labs/aws-app-runner/blob/main/apprunner.yaml) file in your repository.

On the *Configure service* screen, enter `fauna-rest-api` as the *Service name* and leave the Virtual CPU & memory defaults. Open the *Security* section and choose the *AppRunnerSSMReadOnlyAccess* IAM role you created previously from the *Instance role* dropdown. Choose *Next* to review your App Runner service.

![Choosing an IAM role](//images.ctfassets.net/po4qc9xpmpuh/44QRjPRNnYMTN0hgt6Om4H/3ec80355b6b0fdc1496aab6f6b8420da/choosing-an-iam-role.png)

Review the settings for your service and choose *Create & deploy*. App Runner clones your repository, installs dependencies, and deploys your application to the *Default domain* shown on the *Service overview* card. Copy this value, as you will use it to test your service in the next step.

![Running showing domain name](//images.ctfassets.net/po4qc9xpmpuh/fJAT07DwXD4Qhto31LPd1/65e99c899f968b542a990f409168ab79/running-showing-domain-name.png)

### Test your service

Once the App Runner console displays *Create service succeeded* and the *Status* in the *Service overview* is *Running*, you are ready to test your API.

Test your service by sending HTTP requests to the *App Runner URL* using [curl](https://curl.se/), [httpie](https://httpie.io/), or an API client like [Postman](https://www.postman.com/product/api-client/). Replace `${App Runner URL}` in the commands below with the value of *Default domain* from your App Runner dashboard. This will look something like `https://<unique-identifier>.<region>.awsapprunner.com`.

* List all stores (HTTP GET)
    ```bash
    curl ${App Runner URL}/stores
    ```
* Create a store (HTTP POST). The file [@events/create-store.json](https://github.com/fauna-labs/aws-app-runner/events/create-store.json) can be retrieved from the accompanying repository.
    ```bash
    curl --request POST \
      --header "Content-Type: application/json" \
      --data @events/create-store.json \
      ${App Runner URL}/stores
    ```
* Update a store (HTTP PUT). Note that you must replace `{id}` in the URL with the value of `id` of an existing store. As before, the file [@events/update-store.json](https://github.com/fauna-labs/aws-app-runner/events/update-store.json) can be retrieved from the accompanying repository.
    ```bash
    curl --request PUT \
      --header "Content-Type: application/json" \
      --data @events/update-store.json \
      ${App Runner URL}/stores/{id}
    ```
* Delete a store (HTTP DELETE). Note that you must replace `{id}` in the URL with the value of `id` of an existing store.
    ```bash
    curl --request DELETE ${App Runner URL}/stores/{id}
    ```

## Next steps

This application demonstrates how to quickly deploy an API with Fauna, GitHub, and AWS App Runner. Before running an API in production you should add authentication, monitoring, input validation, and more. [This blog post](https://fauna.com/blog/choosing-an-authentication-strategy-with-fauna) helps you choose an authentication strategy with Fauna and provides links to example code for first and third-party authentication strategies. For a deeper understanding of FQL, see [this blog series](https://fauna.com/blog/getting-started-with-fql-faunadbs-native-query-language-part-1) and the [FQL API documentation](https://docs.fauna.com/fauna/current/api/fql/).

## Cleaning up resources

Once you complete this tutorial, you may wish to remove all the resources you create to avoid unexpected charges. You will need to remove your App Runner service, Parameter Store parameter, CloudWatch logs, and Fauna database.

1. Open the [App Runner console](https://console.aws.amazon.com/apprunner/home), select the *fauna-rest-api* stack, and choose *Delete* from the *Actions* dropdown menu. Confirm that you want to delete the stack and all resources by typing *delete* and choosing *Delete*. App Runner initiates the delete process, which should take less than one minute to complete.

1. Open the [Parameter Store console](https://console.aws.amazon.com/systems-manager/parameters/), select the *fauna-secret* parameter, and choose *Delete*. Confirm that you want to delete the parameter by choosing *Delete parameters*.

1. Open the [CloudWatch console](https://console.aws.amazon.com/cloudwatch/), select *Log groups* in the *Logs* section, and select any log groups created by your application that you wish to remove. App Runner log groups begin with */aws/apprunner*. Open the *Actions* dropdown menu and choose *Delete log group(s)*. Confirm that you want to delete the selected log groups by choosing *Delete*.

1. Open the [Fauna dashboard](https://dashboard.fauna.com) and choose the *aws-app-runner* database from the list of databases. Choose *Settings* to open the *Database Settings* screen, then choose *Delete*. Confirm that you want to delete the database by choosing *Delete*.

## Conclusion

In this post, you learned how to build a simple REST API using AWS App Runner and Fauna. You created a database and access key in Fauna and stored that key securely using Parameter Store. You learned how to launch your service using an AWS IAM role that provides read access to an API key stored in Parameter Store. Finally, you built and deployed your application from a GitHub repository using App Runner.

Fork [this GitHub repository](https://github.com/fauna-labs/aws-app-runner), add your routes and business logic, and start building with Fauna today!