Open Source · MIT · Terraform

Your stack as code, Vercel + Supabase + Cloudflare in one apply.

A small Terraform repo with one module per provider. Twenty minutes to a full production stack. Reproducible everywhere.

terraform-stack is the wiring as code for the four-provider stack a solo engineer ships SaaS on in 2026: Vercel for the frontend, Supabase for database/auth/realtime/storage, Cloudflare for DNS/R2/KV, and DigitalOcean for any compute that does not fit on Vercel. Each provider lives in its own module, small enough to read in one sitting. The root main.tf wires them together so you can stand up a full stack with one command, and tear it down with another.

4
Providers
~20 min
To full stack
£30-80
/mo for a small SaaS
<50
Lines per module
MIT
Licence

Why this exists

A solo engineer shipping SaaS in 2026 typically uses six providers in the first month: Vercel, Supabase, Cloudflare, GitHub, a registrar, and an email service. Each console is excellent. Wiring them by hand is correct, slow, and not reproducible.

The generic "AWS-everywhere" Terraform stacks are wrong-shaped for this. The "click around in dashboards" approach is fine for one environment and hostile to two. The right answer is a small, opinionated set of modules that target the providers you actually use.

terraform-stack is that set. Four modules. A reference example. A WHITEPAPER explaining the choices. You apply once, you have a stack. You apply with different variables, you have staging or a per-PR preview.

What it does

Every feature below ships in the public repository today. Clone, configure, run.

Vercel module

Project linked to GitHub, custom domain, env vars templated from sibling module outputs.

Supabase module

Project provisioned in your region, generated DB password, organisation-scoped.

Cloudflare module

DNS A + CNAME at the apex, R2 bucket, Workers KV namespace, all named after the domain.

DigitalOcean (optional)

Droplet or DOKS cluster for the workloads that do not fit on Vercel. Off by default.

Reproducible everywhere

Production, staging, per-PR previews — same modules, different tfvars.

Each module fits in your head

Largest module under 50 lines. No deep abstractions, no library charts, no hidden state.

Cost discipline as a side effect

No hidden capacity, no orphaned LBs, no surprise vendors. Predictable monthly bill.

Sensitive outputs marked

Database passwords and service-role keys are sensitive. Mark your remote state encrypted.

No vendor lock by accident

Want to swap Supabase for Neon? Replace one module. The rest does not change.

Pairs with k8s-ops-toolkit

The DO module provisions a cluster. The k8s-ops-toolkit chart deploys onto it. Same opinionated stack, full coverage.

Tech stack

Terraform 1.9+vercel/vercelsupabase/supabasecloudflare/cloudflaredigitalocean/digitaloceanrandom_passwordS3-compatible state backend (R2 ready)

Architecture, in one diagram

The whole system on a single screen. Every box maps to a real folder in the repo.

┌─────────────────────────────────────────────────────────┐
│                  terraform apply                          │
└────────────────────────┬────────────────────────────────┘
                         │
        ┌────────────────┼────────────────┐
        ▼                ▼                ▼
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│  Vercel      │  │  Supabase    │  │  Cloudflare  │
│  - project   │  │  - project   │  │  - DNS       │
│  - domain    │  │  - DB pass   │  │  - R2 bucket │
│  - env vars  │  │              │  │  - KV ns     │
└──────┬───────┘  └──────┬───────┘  └──────┬───────┘
       │                 │                  │
       └─────────────────┼──────────────────┘
                         ▼
              ┌───────────────────────┐
              │  Optional:            │
              │  DigitalOcean droplet │
              │  or DOKS cluster      │
              └───────────────────────┘

Quick start

From clone to first request in under five minutes.

01
git clone https://github.com/sarmakska/terraform-stack.git
cd terraform-stack
cp terraform.tfvars.example terraform.tfvars
02
# edit terraform.tfvars (project_name, domain, github_repo, supabase_org_id)
export VERCEL_API_TOKEN=...
export SUPABASE_ACCESS_TOKEN=...
export CLOUDFLARE_API_TOKEN=...
03
terraform init
terraform plan
terraform apply
04
# outputs include vercel_project_id, supabase_api_url,
# anon_key, service_role_key, r2_bucket, kv_namespace

Where it fits

The patterns this repository was built around.

First-day SaaS provisioning

New project, want everything stood up in one command instead of four dashboards.

Reproducible staging

Production runs from main, staging runs from staging tfvars. Same shape, different region.

Per-PR preview environments

CI runs terraform apply with a unique workspace per PR. Tear down on close.

Onboarding a new team member

They run terraform apply against a sandbox tfvars file. Twenty minutes later they have a full stack to break.

Your full stack, one apply away. From scratch, every time.

Clone the repo, follow the four-step quick start, ship something real.

All open-source projects