Skip to content

Commit 2c2efeb

Browse files
committed
feat(infra): add Supabase Terraform provider for managed Postgres
- Add supabase.tf: project resource with auto-generated DB password, lifecycle prevent_destroy, and API keys data source - Update versions.tf: add supabase (~> 1.0) + hashicorp/random (~> 3.0) - Update variables.tf: supabase_access_token, org_id, project_name, region - Update outputs.tf: project ID, DB host, port, password, anon/service_role keys - Update terraform.tfvars.example: supabase section with instructions
1 parent aeb4f5f commit 2c2efeb

5 files changed

Lines changed: 134 additions & 1 deletion

File tree

infra/terraform/outputs.tf

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,44 @@ output "cloudflare_record_senzen" {
2222
description = "Cloudflare CNAME record for the frontend"
2323
value = cloudflare_record.senzen_frontend.hostname
2424
}
25+
26+
# ─────────────────────────────────────────────────────────────
27+
# Supabase outputs
28+
# ─────────────────────────────────────────────────────────────
29+
output "supabase_project_id" {
30+
description = "Supabase project reference ID"
31+
value = supabase_project.senzen.id
32+
}
33+
34+
output "supabase_db_host" {
35+
description = "Supabase Postgres connection host (pooler endpoint for serverless)"
36+
value = "aws-0-${var.supabase_region}.pooler.supabase.com"
37+
}
38+
39+
output "supabase_db_direct_host" {
40+
description = "Supabase Postgres direct connection host"
41+
value = "${supabase_project.senzen.id}.supabase.co"
42+
}
43+
44+
output "supabase_db_port" {
45+
description = "Supabase Postgres port"
46+
value = 5432
47+
}
48+
49+
output "supabase_db_password" {
50+
description = "Supabase Postgres password (auto-generated, stored in Terraform state)"
51+
value = random_password.db.result
52+
sensitive = true
53+
}
54+
55+
output "supabase_anon_key" {
56+
description = "Supabase anonymous (public) API key — safe to use in frontend"
57+
value = data.supabase_apikeys.senzen.anon_key
58+
sensitive = true
59+
}
60+
61+
output "supabase_service_role_key" {
62+
description = "Supabase service_role API key — full admin access, NEVER expose in frontend"
63+
value = data.supabase_apikeys.senzen.service_role_key
64+
sensitive = true
65+
}

infra/terraform/supabase.tf

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# =============================================================
2+
# Supabase — Managed Postgres Database
3+
# =============================================================
4+
# Terraform creates the entire Supabase project (Postgres DB,
5+
# Auth, Storage, Realtime) via the Supabase Management API.
6+
#
7+
# Prerequisites:
8+
# 1. Create a Personal Access Token at:
9+
# https://supabase.com/dashboard/account/tokens
10+
# 2. Find your Organization slug at:
11+
# Supabase Dashboard → Org Settings → General → Org slug
12+
# 3. Set supabase_access_token + supabase_org_id in
13+
# terraform.tfvars (local) or Terraform Cloud variables.
14+
# =============================================================
15+
16+
# ─────────────────────────────────────────────────────────────
17+
# Auto-generate a secure database password
18+
# ─────────────────────────────────────────────────────────────
19+
resource "random_password" "db" {
20+
length = 32
21+
special = false
22+
}
23+
24+
# ─────────────────────────────────────────────────────────────
25+
# Create the Supabase project
26+
# ─────────────────────────────────────────────────────────────
27+
resource "supabase_project" "senzen" {
28+
organization_id = var.supabase_org_id
29+
name = var.supabase_project_name
30+
database_password = random_password.db.result
31+
region = var.supabase_region
32+
33+
lifecycle {
34+
# Prevent accidental destruction of the production database
35+
prevent_destroy = true
36+
}
37+
}
38+
39+
# ─────────────────────────────────────────────────────────────
40+
# Fetch API keys for the project (anon + service_role)
41+
# ─────────────────────────────────────────────────────────────
42+
data "supabase_apikeys" "senzen" {
43+
project_ref = supabase_project.senzen.id
44+
}

infra/terraform/terraform.tfvars.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ github_repo = "Long104/Senzen"
4444
# frontend_domain = "senzen.pantorn.site"
4545
# vercel_cname_target = "cname.vercel-dns.com"
4646

47+
# ─────────────────────────────────────────────────────────────
48+
# Supabase (Managed Postgres Database)
49+
# Access Token: https://supabase.com/dashboard/account/tokens
50+
# Org Slug: Dashboard → Org Settings → General → Organization slug
51+
# ─────────────────────────────────────────────────────────────
52+
supabase_access_token = "sbp-access-token-here"
53+
supabase_org_id = "your-org-slug-here"
54+
# supabase_project_name defaults to "senzen"
55+
# supabase_region defaults to "ap-southeast-1" (Singapore)
56+
4757
# ─────────────────────────────────────────────────────────────
4858
# Backend env vars — DOCUMENTATION ONLY.
4959
# These are NOT used by Terraform. They are listed here so you

infra/terraform/variables.tf

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,33 @@ variable "render_service_name" {
7171
variable "vercel_cname_target" {
7272
description = "Vercel's CNAME target (cname.vercel-dns.com)"
7373
type = string
74-
default = "cname.vercel-dns.com"
74+
default = "cname.vercel-dns.com"
75+
}
76+
77+
# ─────────────────────────────────────────────────────────────
78+
# Supabase (Managed Postgres Database)
79+
# ─────────────────────────────────────────────────────────────
80+
variable "supabase_access_token" {
81+
description = "Supabase Personal Access Token — https://supabase.com/dashboard/account/tokens"
82+
type = string
83+
sensitive = true
84+
}
85+
86+
variable "supabase_org_id" {
87+
description = "Supabase organization slug — Dashboard → Org Settings → General → Organization slug"
88+
type = string
89+
}
90+
91+
variable "supabase_project_name" {
92+
description = "Name for the Supabase project"
93+
type = string
94+
default = "senzen"
95+
}
96+
97+
variable "supabase_region" {
98+
description = "Region for the Supabase project (e.g. ap-southeast-1 for Singapore, us-east-1 for N. Virginia)"
99+
type = string
100+
default = "ap-southeast-1"
75101
}
76102

77103
# ─────────────────────────────────────────────────────────────

infra/terraform/versions.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ terraform {
1818
source = "cloudflare/cloudflare"
1919
version = "~> 4.0"
2020
}
21+
supabase = {
22+
source = "supabase/supabase"
23+
version = "~> 1.0"
24+
}
25+
random = {
26+
source = "hashicorp/random"
27+
version = "~> 3.0"
28+
}
2129
}
2230
}
2331

@@ -28,3 +36,7 @@ provider "vercel" {
2836
provider "cloudflare" {
2937
api_token = var.cloudflare_api_token
3038
}
39+
40+
provider "supabase" {
41+
access_token = var.supabase_access_token
42+
}

0 commit comments

Comments
 (0)