Deploy a Stripe sample to a cloud service with Terraform
Published: 2022-08-10 18:03:13

The [Stripe samples](https://github.com/stripe-samples) are great ways to see how to build payments into your web app. This article will show you how to use [Terraform](https://www.terraform.io/), a popular infrastructure-as-code software tool, to deploy a Stripe sample to AWS. 

But why use Terraform? Terraform lets you provision API objects with specific attributes, such as EC2 instances, Lambda functions, etc. through a declarative configuration language. It’s also very flexible: it can simultaneously manage multiple different providers, as opposed to CloudFormation, which is only limited to AWS. You can even write your own Terraform provider for any API, and publish it to the open-sourced Terraform Registry!

# Before you begin
- You will need an AWS account with Identity and Access Management ([IAM](https://aws.amazon.com/iam/?trk=ced3f61b-256e-4936-a949-66a0aee40a02&sc_channel=ps&sc_campaign=acquisition&sc_medium=ACQ-P|PS-GO|Non-Brand|Desktop|SU|Security%20ID%20Compliance|Solution|US|EN|DSA&ef_id=Cj0KCQjwz96WBhC8ARIsAATR250nztYiRCl29e8AEmTn1fDWeSkIreH-fQcBaiAoSDTD0ShXBfO7xyMaAjpGEALw_wcB:G:s&s_kwcid=AL!4422!3!579296534079!!!g!!)) credentials. Specifically, you will need an AWS Access Key ID and Secret Access Key (refer to the “Programmatic access” section of the [AWS security credentials documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html) for detailed instructions on how to retrieve them). 
- You will also need a Stripe account.
- Follow the instructions to [install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli).
- Clone the [terraform-checkout-one-time-payments](https://git.corp.stripe.com/stripe-sandbox/terraform-checkout-one-time-payments) repository to walk through the example steps. (This repository builds off of the original [checkout-one-time-payments](https://github.com/stripe-samples/checkout-one-time-payments) Stripe sample repository.) You will have to follow the steps for running locally.
    - **[Important] The steps in this tutorial assume that you are running the Stripe sample with HTML and a JavaScript (Node) server implementation. So when you clone and configure the sample, be sure to choose these options.**

# High-level overview

We will use Terraform to provision many necessary AWS resources to host the app, which have been defined in `main.tf` in the terraform-checkout-one-time-payments repository. At a high level, we are creating a Lambda function that will handle API queries and connect to the AWS API Gateway service, which will also display the frontend of the app. Each of these resources is defined in its own `resource` block, like so:

    resource "aws_api_gateway_rest_api" "expressapi" {
        body = jsonencode({
            openapi = "3.0.1"
            info = {
                title   = "ExpressApi"
                version = "1.0"
            }
            paths = ...
        })
        binary_media_types = [ "*/*" ]
        name = "ExpressApi"
    }
    
    resource "aws_lambda_function" "expresslambdafunction" {
      ...
    }
    
    // ... other resources

In addition to the new `main.tf` file, the other major difference between the deployment tutorial repository and the original checkout-one-time-payments repository is the restructuring of the code directory tree. This is necessary for webpack to build and bundle the application. 

# Deploying with Terraform
## Step 1

Run `npm build` to initiate the build process and create the `dist`  folder, which will come in handy in the next step.

## Step 2

Now we need to prepare the code to be uploaded to the AWS Lambda function. Create one zip file containing all of the contents in the `dist` directory, but *do not zip the* `dist` *directory itself*. Name it whatever you’d like; running the Terraform script will later prompt you to input the name of the zip file you’d like to upload into Lambda. An example Linux command that you could run to do this would be:
`cd dist && zip -r ../out.zip .`
This will create a zip file titled `out.zip` in the root folder.

## Step 3

You are almost ready to initialize terraform! Before you continue, you will first have to use your IAM credentials to authenticate the Terraform AWS provider. Retrieve your AWS Access Key ID and Secret Access Key (refer to the “Programmatic access” section of the [AWS security credentials documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html) for detailed instructions). Then, in a `.env` file, correspondingly set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.


    AWS_ACCESS_KEY_ID=
    AWS_SECRET_ACCESS_KEY=
## Step 4

Now you can begin using Terraform commands!
While you are in the root directory, run `terraform` `init`, which will download the necessary providers and initialize Terraform.

## Step 5

Then, apply the AWS configurations using `terraform apply`. This will create all of the needed AWS resources for deployment. 

## Step 6

Enter the name of the zip file you created in the previous step when the Terraform CLI prompts you to do so. This will kick off the process of creating an API Gateway, Lambda function, and IAM roles. Once finished, it will output a few URLs:

- `lambda_function_console_url`: The URL to the created Lambda function overview 
![](https://paper-attachments.dropbox.com/s_152C22A11D34A75DD361ED76FD3D5D47D40E773F462A560BCAD3351290374F7F_1658178450764_Screen+Shot+2022-07-18+at+2.07.20+PM.png)

- `api_gateway_console_url`: The API Gateway console, where you can view all created API Gateway REST APIs — the newly created one will be called “ExpressApi” if you didn’t rename it in `main.tf`
![](https://paper-attachments.dropbox.com/s_152C22A11D34A75DD361ED76FD3D5D47D40E773F462A560BCAD3351290374F7F_1658178353433_Screen+Shot+2022-07-18+at+2.05.25+PM.png)

- `api_url`: The API endpoint itself where you can try out the Stripe sample
![](https://paper-attachments.dropbox.com/s_152C22A11D34A75DD361ED76FD3D5D47D40E773F462A560BCAD3351290374F7F_1658178400451_Screen+Shot+2022-07-18+at+2.06.29+PM.png)

## Step 7

At this point, you should be almost done, however, the `DOMAIN` environment variable still needs to be set so that the app will know which URL to redirect to once finishing the payments flow. 

Unfortunately, the `DOMAIN` cannot be known ahead of time before provisioning the API endpoint URL, and there is no way (yet) to declare using the output URL as the input to the Lambda function in Terraform. So, to get around this, paste the URL after the first call to  `terraform apply`  as the `DOMAIN` environment variable in `main.tf`. 

Navigate to `main.tf`, copy the value of `api_url` and paste it as the `DOMAIN` environment variable under the `"aws_lambda_function" "expresslambdafunction"` resource, then copy the rest of the environment variables from `server/.env` . Run `terraform apply` again to update with these changes.

The app should now be ready! Visit the `api_url` to view the running app.

# Wrap up

In this article, you learned how to deploy an existing Stripe sample application to AWS by using the checkout-one-time-payments sample as a walkthrough. You also initialized (`terraform init`) and ran (`terraform apply` ) a Terraform script (`main.tf`) to automatically provision the resources needed for the deployment. 

This tutorial just scratches the surface of what you can do with Terraform. For further exploration, consider these resources:

- [Official Terraform Tutorials](https://learn.hashicorp.com/terraform): learn about CLI commands, the Terraform Configuration Language syntax, writing modules, provisioning infrastructure, and Terraform state
- [Terraform Registry](https://registry.terraform.io/): browse the different resources types that existing providers can provision for you today

An official Terraform provider for the Stripe API is also currently in the works. We hope to publish it to the Terraform Registry soon. This will allow you to define and manage Stripe objects in your own Terraform files. A great use case for this would be creating and maintaining your webhook endpoints. 

We’d also love to hear what you think of this tutorial and if there are other interesting ways that you use Terraform!

# About the author

Erika Tan is an intern at Stripe on the Sandboxes team. Her favorite hobbies outside of work are reading and trying new restaurants.