Platform

Using the Supabase Terraform Provider

Using the Supabase Terraform Provider

Setting up a TF module

  1. Create a Personal Access Token from Supabase Dashboard.
  2. Save your access token locally to access-token file or a secure credentials store.
  3. Create module/provider.tf with the following contents:

_12
terraform {
_12
required_providers {
_12
supabase = {
_12
source = "supabase/supabase"
_12
version = "~> 1.0"
_12
}
_12
}
_12
}
_12
_12
provider "supabase" {
_12
access_token = file("${path.cwd}/access-token")
_12
}

Run the command terraform -chdir=module apply which should succeed in finding the provider.

Creating a project

Supabase projects are represented as a TF resource called supabase_project.

Create a module/resource.tf file with the following contents.


_11
# Create a project resource
_11
resource "supabase_project" "production" {
_11
organization_id = "<your-org-id>"
_11
name = "tf-example"
_11
database_password = "<your-password>"
_11
region = "ap-southeast-1"
_11
_11
lifecycle {
_11
ignore_changes = [database_password]
_11
}
_11
}

Remember to substitue placeholder values with your own. For sensitive fields like password, you may consider retrieving it from a secure credentials store.

Next, run terraform -chdir=module apply and confirm creating the new project resource.

Importing a project

If you have an existing project hosted on Supabase, you may import it into your local terraform state for tracking and management.

Edit module/resource.tf with the following changes.


_21
# Define a linked project variable as user input
_21
variable "linked_project" {
_21
type = string
_21
}
_21
_21
import {
_21
to = supabase_project.production
_21
id = var.linked_project
_21
}
_21
_21
# Create a project resource
_21
resource "supabase_project" "production" {
_21
organization_id = "<your-org-id>"
_21
name = "tf-example"
_21
database_password = "<your-password>"
_21
region = "ap-southeast-1"
_21
_21
lifecycle {
_21
ignore_changes = [database_password]
_21
}
_21
}

Run terraform -chdir=module apply and you will be prompted to enter the reference ID of an existing Supabase project. If your local TF state is empty, your project will be imported from remote rather than recreated.

Alternatively, you may use the terraform import ... command without editing the resource file.

Configuring a project

Keeping your project settings in-sync is easy with the supabase_settings resource.

Create module/settings.tf with the following contents.


_10
# Configure api settings for the linked project
_10
resource "supabase_settings" "production" {
_10
project_ref = var.linked_project
_10
_10
api = jsonencode({
_10
db_schema = "public,storage,graphql_public"
_10
db_extra_search_path = "public,extensions"
_10
max_rows = 1000
_10
})
_10
}

Project settings don't exist on their own. They are created and destroyed together with their corresponding project resource referenced by the project_ref field. This means there is no difference between creating and updating supabase_settings resource while deletion is always a no-op.

You may declare any subset of fields to be managed by your TF module. The Supabase provider always performs a partial update when you run terraform -chdir=module apply. The underlying API call is also idempotent so it's safe to apply again if the local state is lost.

To see the full list of settings available, try importing the supabase_settings resource instead.

Configuring branches

One of the most powerful features of TF is the ability to fan out configs to multiple resources. You can easily mirror the configurations of your production project to your branch databases using the for_each meta-argument.

Create a module/branches.tf file.


_17
# Fetch all branches of a linked project
_17
data "supabase_branch" "all" {
_17
parent_project_ref = var.linked_project
_17
}
_17
_17
# Override settings for each preview branch
_17
resource "supabase_settings" "branch" {
_17
for_each = { for b in data.supabase_branch.all.branches : b.project_ref => b }
_17
_17
project_ref = each.key
_17
_17
api = supabase_settings.production.api
_17
_17
auth = jsonencode({
_17
site_url = "http://localhost:3001"
_17
})
_17
}

When you run terraform -chdir=module apply, the provider will configure all branches associated with your linked_project to mirror the api settings of your production project.

In addition, the auth.site_url settings of your branches will be customised to a localhost URL for all branches. This allows your users to login via a separate domain for testing.

Committing your changes

Finally, you may commit the entire module directory to git for version control. This allows your CI runner to run terraform apply automatically on new config changes. Any command line variables can be passed to CI via TF_VAR_* environment variables instead.

Resolving config drift

Tracking your configs in TF module does not mean that you lose the ability to change configs through the dashboard. However, doing so could introduce config drift that you need to resolve manually by adding them to your *.tf files.