Skip to contentSkip to navigationSkip to topbar
On this page

Use Terraform and Twilio Serverless


Terraform(link takes you to an external page) is a infrastructure as code (IaC) tool that makes it easier to provision the infrastructure resources for your application. In this guide we will look at how and why you might want to leverage Terraform with your Twilio Functions and Assets project.


Prerequisites

prerequisites page anchor

You'll need the latest Terraform CLI(link takes you to an external page) installed on your system.

Additionally, make sure you have either have the following environment variables defined on your system:

  • TWILIO_ACCOUNT_SID with the Account SID of the project you want to deploy to
  • TWILIO_API_KEY with a valid API Key
  • TWILIO_API_SECRET with a valid secret for your API Key

Make sure you also have the latest version of the Serverless Toolkit installed. In this tutorial we'll be using the Twilio CLI plugin. Install the latest version of the Serverless Toolkit by running:

1
twilio plugins:remove @twilio-labs/plugin-serverless
2
twilio plugins:install @twilio-labs/plugin-serverless@latest

You'll also need an existing Twilio Serverless project created with the Serverless Toolkit. If you don't have one you can follow the Getting Started guide.


A brief Terraform introduction

a-brief-terraform-introduction page anchor

Before we start with the work, there's a couple of things you need to understand about Terraform.

1. Provisioning not deployment

1-provisioning-not-deployment page anchor

Terraform is primarily used to provision various resources but not for deploying applications. By default when you run twilio serverless:deploy or twilio-run deploy the Serverless Toolkit will handle both provisioning the respective Serverless Service and Environment and afterwards deploy your code to them.

Provisioning in this context is creating a Serverless Service/Environment resource but could also be any other Service you'd be creating using the CLI, API, or the Console. This can even be purchasing a new phone number. Deploying involves taking the respective code for your project and uploading it to those provisioned resources.

With Terraform we are splitting provisioning and deployment into distinct steps. Splitting these two steps has a couple of benefits:

  1. Separation of concerns. With Terraform you can provide a variety of Twilio and non-Twilio resources (more about this later). Grouping all resource provisioning together makes it easier to identify what resources are required for a project.
  2. Predictable and reproducible. Especially if your project involves several Twilio resources having these steps separately means we can rely on the correct resources to be created and can even share it with colleagues working on the same project (see the next section on state).

An important aspect of Terraform is the fact that it maintains state of your resources. It does so by either creating a .tfstate file on your system or by storing it in a backend of your choice(link takes you to an external page). The Terraform state contains information such as the SIDs of the Twilio resources you might have created through Terraform. By sharing this Terraform state with your colleagues by using a shared backend (you generally don't want to check-in a .tfstate file in your project) you can make sure you are all deploying to the right project.

Terraform providers are essentially integrations that can be used to teach Terraform how to create certain resources. We've released a Twilio provider for Terraform(link takes you to an external page) that we'll be using as part of this project. If you find any issues with it, don't hesitate to create a GitHub issue on the project(link takes you to an external page).

In the Terraform Registry(link takes you to an external page) you can find a wide variety of providers for other platforms.

4. Common Terraform commands

4-common-terraform-commands page anchor

There are a few common Terraform commands that will likely use when working with Terraform.

terraform init is used to set up your project. You'll need to run this for example if you clone your project or if you start using new providers. terraform fmt will make sure your Terraform file is formatted appropriately. terraform validate verifies that your file is correct including using the right resources available through the provider. terraform plan will compute the plan on how Terraform can move from the current state to the new state described in your Terraform file. terraform apply will handle the actual provisioning. It also runs terraform plan under the hood if you didn't run it before.


Write your Terraform script

write-your-terraform-script page anchor

Start by creating a main.tf file at the root of your project.

All the following code has to be added to this main.tf file in the order mentioned below. At the end of the section you can also find the full file if you want to copy and paste it.

Use the Twilio provider for Terraform

use-the-twilio-provider-for-terraform page anchor

To create the Twilio resources we'll be using the Twilio provider(link takes you to an external page). In order to make sure you are using the latest version, head over to the Terraform Registry page(link takes you to an external page). Click the "Use Provider" button and copy the content into your main.tf file.

The result should look like this with possibly a different version.

1
terraform {
2
required_providers {
3
twilio = {
4
source = "twilio/twilio"
5
version = "0.7.0"
6
}
7
}
8
}
9
10
provider "twilio" {
11
# Configuration options
12
}

Define which resources to create

define-which-resources-to-create page anchor

From here we can define which resources we want to create with Terraform. You can find a list of all available Twilio resources on GitHub(link takes you to an external page). In our case we'll create a twilio_serverless_services_v1 and a twilio_serverless_services_environments_v1 as both are required for our Serverless deployment.

Add the following lines to your main.tf file:

1
resource "twilio_serverless_services_v1" "service" {
2
friendly_name = "Terraform Example Service"
3
unique_name = "terraform-demo"
4
include_credentials = true
5
}
6
7
resource "twilio_serverless_services_environments_v1" "environment" {
8
service_sid = twilio_serverless_services_v1.service.sid
9
unique_name = "stage-environment"
10
domain_suffix = "stage"
11
}

The first resource we create is a Serverless Service with the name terraform-demo and friendly name Terraform Example Service. The second resource we create is a Serverless Environment with the domain suffix stage and name stage-environment. For this resource we are passing in the SID of the previously created Service.

This is one of the strengths of us using Terraform for the provisioning as we can immediately define the relationship between the resources.

We'll have to tell the Serverless Toolkit to deploy the code to the Service and Environment we provisioned with Terraform. To do this we have to output the SIDs for the Service and Environment from Terraform.

Add the following code to your main.tf to output the relevant SIDs:

1
output "serverlessService" {
2
value = twilio_serverless_services_v1.service.sid
3
sensitive = true
4
}
5
6
output "serverlessEnvironment" {
7
value = twilio_serverless_services_environments_v1.environment.sid
8
sensitive = true
9
}

This completes our main.tf Terraform file that should look in total like this:

1
terraform {
2
required_providers {
3
twilio = {
4
source = "twilio/twilio"
5
version = "0.7.0"
6
}
7
}
8
}
9
10
provider "twilio" {
11
# Configuration options
12
}
13
14
resource "twilio_serverless_services_v1" "service" {
15
friendly_name = "Terraform Example Service"
16
unique_name = "terraform-demo"
17
include_credentials = true
18
}
19
20
resource "twilio_serverless_services_environments_v1" "environment" {
21
service_sid = twilio_serverless_services_v1.service.sid
22
unique_name = "stage-environment"
23
domain_suffix = "stage"
24
}
25
26
output "serverlessService" {
27
value = twilio_serverless_services_v1.service.sid
28
sensitive = true
29
}
30
31
output "serverlessEnvironment" {
32
value = twilio_serverless_services_environments_v1.environment.sid
33
sensitive = true
34
}

Run your Terraform script

run-your-terraform-script page anchor

Now that we have our completed Terraform file it's time to provision our resources.

First, if you have not done so yet, initialize your Terraform project by running:

terraform init

Next ensure that your main.tf is valid by running:

1
terraform fmt
2
terraform validate

If you want to get a preview of what will be provisioned run:

terraform plan

Now it's time to provision the resources by running:

terraform apply

Once you confirmed the provisioning with yes all the resources will be created using the credentials in your environment variables.

You should also see the new service that was created in your Twilio Console(link takes you to an external page).


Now that the resources have been provisioned we can deploy our code. For this we first have to retrieve the relevant SIDs from Terraform. We can use terraform output for this.

We'll store them in temporary variables using:

1
SERVERLESS_SID=$(terraform output -raw serverlessService)
2
ENVIRONMENT_SID=$(terraform output -raw serverlessEnvironment)

With this we can trigger the deployment by passing in the relevant SIDs using --service-sid and --environment:

1
twilio serverless:deploy \
2
--service-sid "$SERVERLESS_SID" \
3
--environment "$ENVIRONMENT_SID" \
4
--username $TWILIO_API_KEY
5
--password $TWILIO_API_SECRET

This will kick of the same deployment that you are used to but it will explicitly deploy to the Service and Environment you have passed in.


Create more resources with Terraform

create-more-resources-with-terraform page anchor

As mentioned before we can use Terraform to provision a variety of Twilio resources. For example you can use it to provision a Verify service by adding:

1
resource "twilio_verify_services_v2" "service" {
2
friendly_name = "Verify Demo"
3
}
4
5
output "verifyServiceSid" {
6
value = twilio_verify_services_v2.service.sid
7
sensitive = true
8
}

If you want to pass the Service SID to your Twilio Functions deployment you can do this using the Serverless Toolkit by running:

1
VERIFY_SERVICE_SID=$(terraform output -raw verifyServiceSid)
2
twilio serverless:env:set --key VERIFY_SERVICE_SID --value "$VERIFY_SERVICE_SID"

Check out more examples on the Twilio Terraform Provider GitHub(link takes you to an external page).


Use a Continuous Delivery system

use-a-continuous-delivery-system page anchor

With all of this set up we can actually move this into a Continuous Integration / Continuous Delivery (CI/CD) system. How exactly you use Terraform depends on your the system you are using. Make sure to consult the Terraform docs for more information. You will also have to use some backend to store your Terraform state. To learn more on how to use the Serverless Toolkit from CI/CD environments check out our dedicated guide for it.

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.