This Terraform project provisions a Google Cloud Firestore database.
graph TD
A[User] -->|terraform apply| B(Terraform)
B -->|Auth via gcloud ADC| C{GCP API}
C -->|Create| D[Firestore Database]
sequenceDiagram
participant U as User
participant T as Terraform
participant G as gcloud CLI
participant API as GCP Cloud API
U->>G: gcloud auth application-default login
G-->>U: Authentication Success
U->>T: terraform apply
T->>API: Authenticate using ADC
T->>API: Plan & Create Firestore Database
API-->>T: Database Provisioned
T-->>U: Outputs (Database Name, Location)
- Database Mode:
NATIVE_MODEorDATASTORE_MODE. - Location: Restricted to
us-west1,us-central1, orus-east1(GCP Always Free Tier regions). - Type: Defaults to
FIRESTORE_NATIVE. - Provisioning Only: This project creates the Firestore database resource only; no collections or documents are created.
To stay within the free tier, ensure your usage does not exceed:
- Document Reads: 50,000 per day.
- Document Writes: 20,000 per day.
- Document Deletes: 20,000 per day.
- Storage: 1 GiB of stored data.
- Network Egress: 10 GiB per month (within the same region).
-
Google Cloud SDK: Installed and initialized.
-
Terraform: Installed.
-
Enable the Firestore API in your GCP project:
gcloud services enable firestore.googleapis.com -
Ensure the authenticating identity has the required IAM role. The
roles/editorrole is not sufficient. One of the following roles is required:roles/datastore.owner(Cloud Datastore Owner)roles/firestore.admin(Firestore Admin)
If your project requires conditions on IAM bindings, add the role with a condition:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:YOUR_SA_EMAIL" \ --role="roles/datastore.owner" \ --condition="expression=request.time < timestamp('2027-01-01T00:00:00Z'),title=tf-firestore-access"
-
Authenticate and Select Project: Instead of using a service account JSON file, this project uses your local
gcloudcredentials.# Authenticate gcloud auth application-default login # Select your project gcloud config set project your-project-id
-
Configure Variables: Create a
terraform.tfvarsfile based on the example:project_id = "your-project-id" region = "us-central1" database_id = "my-firestore-database"
-
Deploy:
# Initialize terraform init # Apply changes terraform apply
-
Outputs: After a successful deployment, Terraform will output the database details.
-
Enable the Firestore API in your GCP project:
gcloud services enable firestore.googleapis.com -
Create a service account with the required role and generate a JSON key:
The
roles/editorrole is not sufficient. You must grant one of:roles/datastore.owner(Cloud Datastore Owner)roles/firestore.admin(Firestore Admin)
Using the gcloud CLI:
gcloud iam service-accounts create tf-firestore-sa \ --display-name="Terraform Firestore SA" gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:tf-firestore-sa@PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/datastore.owner"
If your project requires conditions on IAM bindings, append:
--condition="expression=request.time < timestamp('2027-01-01T00:00:00Z'),title=tf-firestore-access"Generate a JSON key:
gcloud iam service-accounts keys create key.json \ --iam-account=tf-firestore-sa@PROJECT_ID.iam.gserviceaccount.com
Or via the GCP Console:
- IAM & Admin → Service Accounts → Create Service Account
- Grant role: Cloud Datastore Owner (add a condition if required by org policy)
- Keys → Add Key → Create New Key → JSON
- Copy the entire JSON file contents
-
Add a GitHub secret named
GCP_SA_KEYcontaining the full JSON key from step 2:- GitHub repo → Settings → Secrets and variables → Actions → New repository secret
- Name:
GCP_SA_KEY - Value: (paste the entire JSON contents)
-
Create a GCS bucket for Terraform remote state (if not already created):
gcloud storage buckets create gs://your-terraform-state-bucket \ --location=us-central1 \ --uniform-bucket-level-access
-
Add GitHub Secrets for backend state bucket:
Secret Name Value TF_BUCKET_NAMEYour GCS bucket name (e.g., your-terraform-state-bucket)TF_BUCKET_PREFIXBucket prefix/path (e.g., terraform-gcp-cloud-sql) -
Run the workflow:
- Apply: Go to Actions → CD - Terraform Apply → fill in all inputs
- Destroy: Go to Actions → CD - Terraform Destroy → fill in essential inputs only
Alternatively, create a
backend.tfvarsfrombackend.tfvars.exampleand reference it withterraform init -backend-config="backend.tfvars"for local use.
Reference this repository as a Terraform module in your own configurations:
Option 1: Terraform Registry (recommended)
module "db-firestore" { source = "marcuwynu23/db-firestore/gcp" version = "1.0.0" project_id = var.project_id region = "us-central1" database_id = "my-app-firestore" database_type = "FIRESTORE_NATIVE" }Option 2: GitHub source
module "db-firestore" { source = "github.com/marcuwynu23/terraform-gcp-firestore?ref=main" project_id = var.project_id region = "us-central1" database_id = "my-app-firestore" database_type = "FIRESTORE_NATIVE" }
Then use the outputs in your configuration:
# Example: pass the database name to a Cloud Run service
resource "google_cloud_run_v2_service" "app" {
# ...
template {
containers {
env {
name = "FIRESTORE_DATABASE"
value = module.firestore_db.database_name
}
}
}
}| Variable | Description | Type | Default |
|---|---|---|---|
project_id |
GCP project ID | string |
(required) |
region |
GCP region (free tier: us-west1, us-central1, us-east1) | string |
"us-central1" |
database_id |
Firestore database ID | string |
"default" |
database_type |
Firestore database type: FIRESTORE_NATIVE or DATASTORE_MODE | string |
"FIRESTORE_NATIVE" |
| Output | Description |
|---|---|
database_name |
Name of the created Firestore database |
database_id |
ID of the created Firestore database |
database_location |
Location of the Firestore database |