Mulai menggunakan Terraform dan Firebase

Firebase mulai mendukung Terraform. Jika Anda berada dalam tim yang ingin mengotomatiskan dan menstandarkan pembuatan project Firebase dengan menyediakan resource dan mengaktifkan layanan tertentu, penggunaan Terraform dengan Firebase merupakan pilihan tepat.

Alur kerja dasar untuk menggunakan Terraform dengan Firebase mencakup langkah berikut:

  • Membuat dan menyesuaikan file konfigurasi Terraform (file .tf) yang menentukan infrastruktur yang ingin Anda sediakan (yakni, resource yang ingin disediakan dan layanan yang ingin diaktifkan).

  • Menggunakan perintah gcloud CLI yang berantarmuka dengan Terraform untuk menyediakan infrastruktur yang ditentukan dalam file .tf.

Apa yang dapat Anda lakukan dengan Terraform dan Firebase?

Contoh alur kerja umum dalam panduan ini akan membuat project Firebase baru dengan aplikasi Android. Namun, Anda dapat menggunakan Terraform untuk banyak hal lainnya, seperti:

  • Menghapus dan memodifikasi infrastruktur yang ada.

  • Mengelola tugas dan konfigurasi spesifik per produk, seperti:

    • Mengaktifkan penyedia login Firebase Authentication.
    • Membuat bucket Cloud Storage atau instance database dan men-deploy Firebase Security Rules untuk keduanya.

Anda dapat menggunakan perintah dan file konfigurasi Terraform standar untuk menyelesaikan semua tugas ini. Untuk memudahkan Anda, kami juga telah menyediakan contoh file konfigurasi Terraform untuk beberapa kasus penggunaan umum.



Alur kerja umum untuk menggunakan Terraform dengan Firebase

Prasyarat

Panduan ini merupakan pengantar penggunaan Terraform dengan Firebase, sehingga diasumsikan bahwa Anda telah memiliki pemahaman dasar tentang Terraform. Pastikan Anda telah menyelesaikan prasyarat berikut sebelum memulai alur kerja ini.

  • Menginstal Terraform dan memahami Terraform melalui tutorial resminya.

  • Instal Google Cloud CLI (gcloud CLI). Login menggunakan akun pengguna atau akun layanan.

    • Jika menggunakan akun pengguna, Anda harus telah menyetujui Persyaratan Layanan (ToS) Firebase. Sebelum menyetujui ToS Firebase, Anda tidak akan dapat melihat project Firebase di Firebase console
    • Agar Terraform dapat melakukan tindakan tertentu (misalnya membuat project), hal berikut harus terpenuhi:
      • Akun pengguna atau akun layanan harus memiliki akses IAM yang berlaku untuk tindakan tersebut.
      • Jika akun pengguna atau akun layanan merupakan bagian dari organisasi Google Cloud, kebijakan organisasi harus mengizinkan akun tersebut untuk melakukan tindakan itu.


Langkah 1: Membuat dan menyesuaikan file konfigurasi Terraform

File konfigurasi Terraform memerlukan dua bagian utama (yang dijelaskan secara mendetail di bawah):

Menyiapkan provider

Penyiapan provider diperlukan, apa pun produk atau layanan Firebase yang digunakan.

  1. Buat file konfigurasi Terraform (seperti file main.tf) di direktori lokal.

    Dalam panduan ini, Anda akan menggunakan file konfigurasi ini untuk menentukan penyiapan provider dan semua infrastruktur yang Anda inginkan untuk dibuat oleh Terraform. Namun, perlu diperhatikan bahwa ada beberapa opsi terkait cara menyertakan penyiapan provider.

    Opsi berikut tersedia untuk menyertakan penyiapan provider pada konfigurasi Terraform lainnya:

    • Opsi 1: Menyertakan penyiapan provider di bagian atas sebuah file konfigurasi .tf Terraform (seperti yang ditunjukkan dalam panduan ini).

      • Gunakan opsi ini jika Anda baru mulai menggunakan Terraform atau baru mencoba Terraform dengan Firebase.
    • Opsi 2: Menyertakan penyiapan provider dalam file .tf tersendiri (seperti file provider.tf), yang terpisah dari file .tf tempat Anda menentukan infrastruktur yang akan dibuat (seperti file main.tf).

      • Gunakan opsi ini jika Anda adalah bagian dari tim yang lebih besar yang perlu menstandarkan penyiapan.
      • Saat menjalankan perintah Terraform, baik file provider.tf maupun file main.tf harus berada di direktori yang sama.

  2. Sertakan penyiapan provider berikut di bagian atas file main.tf.

    Anda harus menggunakan provider google-beta karena ini adalah rilis beta dari penggunaan Firebase dengan Terraform. Berhati-hatilah saat menggunakannya dalam produksi.

    # Terraform configuration to set up providers by version.
    terraform {
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 5.0"
        }
      }
    }
    
    # Configures the provider to use the resource block's specified project for quota checks.
    provider "google-beta" {
      user_project_override = true
    }
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    # This provider should only be used during project creation and initializing services.
    provider "google-beta" {
      alias = "no_user_project_override"
      user_project_override = false
    }

    Pelajari lebih lanjut berbagai jenis atribut terkait project (termasuk yang dalam panduan ini disebut sebagai "quota-check project") saat menggunakan Terraform dengan Firebase.

  3. Lanjutkan ke bagian berikutnya untuk menyelesaikan file konfigurasi dan menentukan infrastruktur yang akan dibuat.

Menentukan infrastruktur yang akan dibuat menggunakan blok resource

Dalam file konfigurasi Terraform (untuk panduan ini, file main.tf), Anda harus menentukan semua infrastruktur yang Anda inginkan untuk dibuat oleh Terraform (artinya, semua resource yang ingin disediakan dan semua layanan yang ingin diaktifkan). Dalam panduan ini, temukan daftar lengkap semua resource Firebase yang mendukung Terraform.

  1. Buka file main.tf.

  2. Pada penyiapan provider, sertakan konfigurasi blok resource berikut.

    Contoh dasar ini akan membuat project Firebase baru, lalu membuat Aplikasi Android Firebase di dalam project tersebut.

    # Terraform configuration to set up providers by version.
    ...
    
    # Configures the provider to use the resource block's specified project for quota checks.
    ...
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    ...
    
    # Creates a new Google Cloud project.
    resource "google_project" "default" {
      provider   = google-beta.no_user_project_override
    
      name       = "Project Display Name"
      project_id = "project-id-for-new-project"
      # Required for any service that requires the Blaze pricing plan
      # (like Firebase Authentication with GCIP)
      billing_account = "000000-000000-000000"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    # Enables required APIs.
    resource "google_project_service" "default" {
      provider = google-beta.no_user_project_override
      project  = google_project.default.project_id
      for_each = toset([
        "cloudbilling.googleapis.com",
        "cloudresourcemanager.googleapis.com",
        "firebase.googleapis.com",
        # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
        "serviceusage.googleapis.com",
      ])
      service = each.key
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enables Firebase services for the new project created above.
    resource "google_firebase_project" "default" {
      provider = google-beta
      project  = google_project.default.project_id
    
      # Waits for the required APIs to be enabled.
      depends_on = [
        google_project_service.default
      ]
    }
    
    # Creates a Firebase Android App in the new project created above.
    resource "google_firebase_android_app" "default" {
      provider = google-beta
    
      project      = google_project.default.project_id
      display_name = "My Awesome Android app"
      package_name = "awesome.package.name"
    
      # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
      depends_on = [
        google_firebase_project.default,
      ]
    }

Jika Anda belum familier dengan infrastruktur project dan aplikasi sebagai resource, pelajari dokumentasi berikut:

# Terraform configuration to set up providers by version.
...

# Configures the provider to use the resource block's specified project for quota checks.
...

# Configures the provider to not use the resource block's specified project for quota checks.
...

# Creates a new Google Cloud project.
resource "google_project" "default" {
  # Use the provider that enables the setup of quota checks for a new project
  provider   = google-beta.no_user_project_override

  name            = "Project Display Name"        // learn more about the project name
  project_id      = "project-id-for-new-project"  // learn more about the project ID
  # Required for any service that requires the Blaze pricing plan
  # (like Firebase Authentication with GCIP)
  billing_account = "000000-000000-000000"

  # Required for the project to display in any list of Firebase projects.
  labels = {
    "firebase" = "enabled"  // learn more about the Firebase-enabled label
  }
}

# Enables required APIs.
resource "google_project_service" "default" {
  # Use the provider without quota checks for enabling APIS
  provider = google-beta.no_user_project_override
  project  = google_project.default.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
# This action essentially "creates a Firebase project" and allows the project to use
# Firebase services (like Firebase Authentication) and
# Firebase tooling (like the Firebase console).
# Learn more about the relationship between Firebase projects and Google Cloud.
resource "google_firebase_project" "default" {
  # Use the provider that performs quota checks from now on
  provider = google-beta

  project  = google_project.default.project_id

  # Waits for the required APIs to be enabled.
  depends_on = [
    google_project_service.default
  ]
}

# Creates a Firebase Android App in the new project created above.
# Learn more about the relationship between Firebase Apps and Firebase projects.
resource "google_firebase_android_app" "default" {
  provider = google-beta

  project      = google_project.default.project_id
  display_name = "My Awesome Android app"  # learn more about an app's display name
  package_name = "awesome.package.name"    # learn more about an app's package name

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.default,
  ]
}


Langkah 2: Menjalankan perintah Terraform untuk membuat infrastruktur yang ditentukan

Untuk menyediakan resource dan mengaktifkan layanan yang ditentukan dalam file main.tf, jalankan perintah berikut dari direktori yang sama dengan file main.tf Anda. Untuk mendapatkan informasi selengkapnya tentang perintah ini, lihat dokumentasi Terraform.

  1. Jika ini adalah pertama kalinya Anda menjalankan perintah Terraform di direktori, Anda harus menginisialisasi direktori konfigurasi dan menginstal provider Google Terraform. Lakukan hal ini dengan menjalankan perintah berikut:

    terraform init
  2. Buat infrastruktur yang ditentukan dalam file main.tf dengan menjalankan perintah berikut:

    terraform apply
  3. Pastikan bahwa segala sesuatunya telah disediakan atau diaktifkan seperti yang diharapkan:

    • Opsi 1: Lihat konfigurasi yang tercetak di terminal dengan menjalankan perintah berikut:

      terraform show
    • Opsi 2: Lihat project Firebase di Firebase console.



Resource Firebase yang memiliki dukungan Terraform

Resource Firebase dan Google berikut memiliki dukungan Terraform. Kami juga menambahkan lebih banyak resource dari waktu ke waktu. Jadi, jika Anda belum menemukan resource yang ingin dikelola dengan Terraform, segera periksa kembali untuk mengetahui apakah resource tersebut telah tersedia, atau kirimkan permintaan dengan melaporkan masalah di repo GitHub.


Pengelolaan aplikasi dan project Firebase

  • google_firebase_project — mengaktifkan layanan Firebase di project Google Cloud yang ada

  • Aplikasi Firebase


Firebase Authentication

Belum didukung:

  • Mengonfigurasi autentikasi multi-faktor (MFA) melalui Terraform

Firebase Realtime Database

Belum didukung:

  • Men-deploy Firebase Realtime Database Security Rules melalui Terraform (pelajari cara men-deploy Rules ini menggunakan alat lain, termasuk opsi terprogram)

Cloud Firestore

  • google_firestore_database — membuat instance Cloud Firestore

  • google_firestore_index — mengaktifkan kueri yang efisien untuk Cloud Firestore

  • google_firestore_document — membuat seed instance Cloud Firestore dengan dokumen tertentu dalam suatu kumpulan

    Penting: Jangan gunakan data produksi atau pengguna akhir sebenarnya dalam dokumen seed ini.


Cloud Storage for Firebase

  • google_firebase_storage_bucket — membuat bucket Cloud Storage yang ada dapat diakses untuk Firebase SDK, autentikasi, dan Firebase Security Rules

  • google_storage_bucket_object — menambahkan objek ke bucket Cloud Storage

    Penting: Jangan gunakan data produksi atau pengguna akhir sebenarnya dalam file ini.


Firebase Security Rules (untuk Cloud Firestore dan Cloud Storage)

Perhatikan bahwa Firebase Realtime Database menggunakan sistem penyediaan yang berbeda untuk Firebase Security Rules-nya.

  • google_firebaserules_ruleset — menentukan Firebase Security Rules yang berlaku untuk instance Cloud Firestore atau bucket Cloud Storage

  • google_firebaserules_release — men-deploy kumpulan aturan tertentu ke instance Cloud Firestore atau bucket Cloud Storage


Firebase App Check


Firebase Extensions



Contoh file konfigurasi Terraform untuk kasus penggunaan umum

Konfigurasi ini akan membuat project Google Cloud baru, mengaitkan project dengan akun Cloud Billing (paket harga Blaze diperlukan untuk Firebase Authentication dengan GCIP), mengaktifkan layanan Firebase untuk project, menyiapkan Firebase Authentication dengan GCIP, dan mendaftarkan tiga jenis aplikasi berbeda ke project tersebut.

Perhatikan bahwa GCIP harus diaktifkan untuk menyiapkan Firebase Authentication melalui Terraform.

# Creates a new Google Cloud project.
resource "google_project" "auth" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for Firebase Authentication with GCIP).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "auth" {
  provider = google-beta.no_user_project_override
  project  = google_project.auth.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "identitytoolkit.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  depends_on = [
    google_project_service.auth,
  ]
}

# Creates an Identity Platform config.
# Also enables Firebase Authentication with Identity Platform in the project if not.
resource "google_identity_platform_config" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  # Auto-deletes anonymous users
  autodelete_anonymous_users = true

  # Configures local sign-in methods, like anonymous, email/password, and phone authentication.
  sign_in {
    allow_duplicate_emails = true

    anonymous {
      enabled = true
    }

    email {
      enabled = true
      password_required = false
    }

    phone_number {
      enabled = true
      test_phone_numbers = {
        "+11231231234" = "000000"
      }
    }
  }

  # Sets an SMS region policy.
  sms_region_config {
    allowlist_only {
      allowed_regions = [
        "US",
        "CA",
      ]
    }
  }

  # Configures blocking functions.
  blocking_functions {
    triggers {
      event_type = "beforeSignIn"
      function_uri = "https://us-east1-${google_project.auth.project_id}.cloudfunctions.net/before-sign-in"
    }
    forward_inbound_credentials {
      refresh_token = true
      access_token = true
      id_token = true
    }
  }

  # Configures a temporary quota for new signups for anonymous, email/password, and phone number.
  quota {
    sign_up_quota_config {
      quota = 1000
      start_time = ""
      quota_duration = "7200s"
    }
  }

  # Configures authorized domains.
  authorized_domains = [
    "localhost",
    "${google_project.auth.project_id}.firebaseapp.com",
    "${google_project.auth.project_id}.web.app",
  ]

  # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
  depends_on = [
    google_project_service.auth,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaktifkan layanan Firebase untuk project, menyediakan instance Realtime Database default project, dan mendaftarkan tiga jenis aplikasi berbeda ke project tersebut.

# Creates a new Google Cloud project.
resource "google_project" "rtdb" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb.project_id
  for_each = toset([
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb" {
  provider = google-beta
  project  = google_project.rtdb.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database" {
  provider    = google-beta
  project     = google_project.rtdb.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaitkan project dengan akun Cloud Billing (paket harga Blaze diperlukan untuk beberapa instance Realtime Database), mengaktifkan layanan Firebase untuk project, menyediakan beberapa instance Realtime Database (termasuk instance Realtime Database default project), dan mendaftarkan tiga jenis aplikasi berbeda ke project tersebut.

# Creates a new Google Cloud project.
resource "google_project" "rtdb-multi" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associate the project with a Cloud Billing account
  # (required for multiple Realtime Database instances).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb-multi" {
  provider = google-beta
  project  = google_project.rtdb-multi.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database-default" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb-multi.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Provisions an additional Realtime Database instance.
resource "google_firebase_database_instance" "database-additional" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/projects/locations#rtdb-locations
  # This location doesn't need to be the same as the default database instance.
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "name-of-additional-database-instance"
  type        = "USER_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaktifkan layanan Firebase untuk project, menyediakan instance Cloud Firestore default project, dan mendaftarkan tiga jenis aplikasi berbeda ke project tersebut.

Konfigurasi ini juga akan menyediakan Firebase Security Rules untuk instance Cloud Firestore default, membuat indeks Cloud Firestore, dan menambahkan dokumen Cloud Firestore dengan data seed.

# Creates a new Google Cloud project.
resource "google_project" "firestore" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "firestore" {
  provider = google-beta.no_user_project_override
  project  = google_project.firestore.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "firestore.googleapis.com",
    "firebaserules.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "firestore" {
  provider                    = google-beta
  project                     = google_project.firestore.project_id
  name                        = "(default)"
  # See available locations: https://firebase.google.com/docs/firestore/locations
  location_id                 = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type                        = "FIRESTORE_NATIVE"
  concurrency_mode            = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a ruleset of Firestore Security Rules from a local file.
resource "google_firebaserules_ruleset" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
  source {
    files {
      name = "firestore.rules"
      # Write security rules in a local file named "firestore.rules".
      # Learn more: https://firebase.google.com/docs/firestore/security/get-started
      content = file("firestore.rules")
    }
  }

  # Wait for Firestore to be provisioned before creating this ruleset.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Releases the ruleset for the Firestore instance.
resource "google_firebaserules_release" "firestore" {
  provider     = google-beta
  name         = "cloud.firestore"  # must be cloud.firestore
  ruleset_name = google_firebaserules_ruleset.firestore.name
  project      = google_project.firestore.project_id

  # Wait for Firestore to be provisioned before releasing the ruleset.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore index.
resource "google_firestore_index" "indexes" {
  provider = google-beta
  project  = google_project.firestore.project_id

  collection  = "quiz"
  query_scope = "COLLECTION"

  fields {
    field_path = "question"
    order      = "ASCENDING"
  }

  fields {
    field_path = "answer"
    order      = "ASCENDING"
  }

  # Wait for Firestore to be provisioned before adding this index.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore document with seed data.
# Don't use real end-user or production data in this seed document.
resource "google_firestore_document" "doc" {
  provider    = google-beta
  project     = google_project.firestore.project_id
  collection  = "quiz"
  document_id = "question-1"
  fields      = "{\"question\":{\"stringValue\":\"Favorite Database\"},\"answer\":{\"stringValue\":\"Firestore\"}}"

  # Wait for Firestore to be provisioned before adding this document.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

Ini adalah kumpulan aturan Cloud Firestore Security Rules yang harus ada dalam file lokal yang bernama firestore.rules.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, create, update: if request.auth != null;
    }
  }
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaitkan project dengan akun Cloud Billing (paket harga Blaze diperlukan untuk bucket tambahan), mengaktifkan layanan Firebase untuk project, menyediakan bucket Cloud Storage tambahan non-default, dan mendaftarkan tiga jenis aplikasi berbeda ke project tersebut.

Konfigurasi ini juga akan menyediakan Firebase Security Rules untuk setiap bucket Cloud Storage, dan mengupload file ke salah satu bucket Cloud Storage.

# Creates a new Google Cloud project.
resource "google_project" "storage-multi" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for multiple Cloud Storage buckets).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "storage-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.storage-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebaserules.googleapis.com",
    "firebasestorage.googleapis.com",
    "storage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
}

# Provisions a Cloud Storage bucket.
resource "google_storage_bucket" "bucket-1" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  location = "name-of-region-for-bucket"
}

# Provisions an additional Cloud Storage bucket.
resource "google_storage_bucket" "bucket-2" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-additional-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  # This location does not need to be the same as the existing Storage bucket.
  location = "name-of-region-for-additional-bucket"
}

# Makes the first Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-1" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-1.name
}

# Makes the additional Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-2" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-2.name
}

# Creates a ruleset of Firebase Security Rules from a local file.
resource "google_firebaserules_ruleset" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  source {
    files {
      # Write security rules in a local file named "storage.rules"
      # Learn more: https://firebase.google.com/docs/storage/security/get-started
      name    = "storage.rules"
      content = file("storage.rules")
    }
  }

  # Wait for the Storage buckets to be provisioned before creating this ruleset.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Releases the ruleset to the first Storage bucket.
resource "google_firebaserules_release" "bucket-1" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-1.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Releases the ruleset to the additional Storage bucket.
resource "google_firebaserules_release" "bucket-2" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-2.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Uploads a new file to the first Storage bucket.
# Do not use real end-user or production data in this file.
resource "google_storage_bucket_object" "cat-picture-multi" {
  provider = google-beta
  name     = "cat.png"
  source   = "path/to/cat.png"
  bucket   = google_storage_bucket.bucket-1.name
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Web app"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

Ini adalah kumpulan aturan Cloud Storage Security Rules yang harus ada dalam file lokal yang bernama storage.rules.

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /some_folder/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaktifkan layanan Firebase untuk project, serta menyiapkan dan mengaktifkan penerapan Firebase App Check untuk Cloud Firestore sehingga hanya dapat diakses dari aplikasi Android Anda.

# Creates a new Google Cloud project.
resource "google_project" "appcheck" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "services" {
  provider = google-beta.no_user_project_override
  project  = google_project.appcheck.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    "firebaseappcheck.googleapis.com",
    "firestore.googleapis.com",
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created earlier.
resource "google_firebase_project" "appcheck" {
  provider = google-beta
  project  = google_project.appcheck.project_id

  depends_on = [google_project_service.services]
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "database" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  name     = "(default)"
  # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
  location_id = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type             = "FIRESTORE_NATIVE"
  concurrency_mode = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.appcheck,
  ]
}

# Creates a Firebase Android App in the new project created earlier.
resource "google_firebase_android_app" "appcheck" {
  provider     = google-beta
  project      = google_firebase_project.appcheck.project
  display_name = "Play Integrity app"
  package_name = "package.name.playintegrity"
  sha256_hashes = [
    # TODO: insert your Android app's SHA256 certificate
  ]
}

# It takes a while for App Check to recognize the new app
# If your app already exists, you don't have to wait 30 seconds.
resource "time_sleep" "wait_30s" {
  depends_on      = [google_firebase_android_app.appcheck]
  create_duration = "30s"
}

# Register the Android app with the Play Integrity provider
resource "google_firebase_app_check_play_integrity_config" "appcheck" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  app_id   = google_firebase_android_app.appcheck.app_id

  depends_on = [time_sleep.wait_30s, google_firestore_database.database]

  lifecycle {
    precondition {
      condition     = length(google_firebase_android_app.appcheck.sha256_hashes) > 0
      error_message = "Provide a SHA-256 certificate on the Android App to use App Check"
    }
  }
}

# Enable enforcement of App Check for Firestore
resource "google_firebase_app_check_service_config" "firestore" {
  provider = google-beta

  project    = google_firebase_project.appcheck.project
  service_id = "firestore.googleapis.com"

  depends_on = [google_project_service.services]
}

Konfigurasi ini akan membuat project Google Cloud baru, mengaktifkan layanan Firebase untuk project, dan menginstal instance Firebase Extension baru dalam project. Jika instance sudah ada, parameternya akan diperbarui berdasarkan nilai yang diberikan dalam konfigurasi.

# Creates a new Google Cloud project.
resource "google_project" "extensions" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required to use Firebase Extensions).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "extensions" {
  provider = google-beta.no_user_project_override
  project  = google_project.extensions.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "firebase.googleapis.com",
    "firebaseextensions.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "extensions" {
  provider = google-beta
  project  = google_project.extensions.project_id

  depends_on = [
    google_project_service.extensions,
  ]
}

# Installs an instance of the "Translate Text in Firestore" extension.
# Or updates the extension if the specified instance already exists.
resource "google_firebase_extensions_instance" "translation" {
  provider = google-beta
  project = google_project.extensions.project_id

  instance_id = "translate-text-in-firestore"
  config {
    extension_ref = "firebase/firestore-translate-text"

    params = {
      COLLECTION_PATH      = "posts/comments/translations"
      DO_BACKFILL          = true
      LANGUAGES            = "ar,en,es,de,fr"
      INPUT_FIELD_NAME     = "input"
      LANGUAGES_FIELD_NAME = "languages"
      OUTPUT_FIELD_NAME    = "translated"
    }

    system_params = {
      "firebaseextensions.v1beta.function/location"                   = "us-central1"
      "firebaseextensions.v1beta.function/memory"                     = "256"
      "firebaseextensions.v1beta.function/minInstances"               = "0"
      "firebaseextensions.v1beta.function/vpcConnectorEgressSettings" = "VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED"
    }
  }
}



Pemecahan masalah dan pertanyaan umum (FAQ)

Panduan ini menggunakan atribut Terraform berikut saat menangani "project".

project dalam blok resource

Direkomendasikan: jika memungkinkan, sertakan atribut project dalam setiap blok resource

Dengan menyertakan atribut project, Terraform akan membuat infrastruktur yang ditentukan di blok resource dalam project yang ditentukan. Panduan ini dan contoh file konfigurasi kami semuanya menggunakan praktik ini.

Lihat dokumentasi Terraform resmi tentang project.

user_project_override dalam blok provider

Untuk menyediakan sebagian besar resource, Anda harus menggunakan user_project_override = true, yang berarti memeriksa kuota terhadap project Firebase Anda sendiri. Namun, untuk menyiapkan project baru agar dapat menerima pemeriksaan kuota, Anda harus menggunakan user_project_override = false terlebih dahulu.

Lihat dokumentasi Terraform resmi tentang user_project_override.

Pastikan akun pengguna yang digunakan untuk menjalankan perintah gcloud CLI telah menyetujui Persyaratan Layanan (ToS) Firebase.

  • Anda dapat melakukan pemeriksaan ini dengan menggunakan browser yang telah login ke akun pengguna tersebut dan mencoba melihat project Firebase yang ada di Firebase console. Jika Anda dapat melihat project Firebase yang ada, berarti akun pengguna itu telah menyetujui ToS Firebase.

  • Jika Anda tidak dapat melihat project Firebase yang ada, akun pengguna tersebut kemungkinan belum menyetujui ToS Firebase. Untuk mengatasi masalah ini, buat project Firebase baru melalui Firebase console dan setujui ToS Firebase sebagai bagian dari pembuatan project. Anda dapat langsung menghapus project ini melalui Project Settings di konsol.

Tunggu beberapa menit, lalu coba jalankan terraform apply lagi.

Hal ini kemungkinan disebabkan oleh keterlambatan penerapan di berbagai sistem. Coba selesaikan masalah ini dengan mengimpor resource ke status Terraform dengan menjalankan terraform import. Lalu, coba jalankan terraform apply lagi.

Anda dapat mempelajari cara mengimpor setiap resource di bagian "Impor" dalam dokumentasi Terraform-nya (misalnya, dokumentasi "Impor" untuk Cloud Firestore).

Error ini menunjukkan bahwa Terraform mungkin mencoba menyediakan beberapa indeks dan/atau membuat dokumen secara bersamaan, lalu mengalami error serentak. Coba jalankan terraform apply lagi.

Error ini berarti bahwa Terraform tidak mengetahui project mana yang akan diperiksa kuotanya. Untuk memecahkan masalah, periksa hal-hal berikut di blok resource:

  • Pastikan Anda telah menentukan nilai untuk atribut project.
  • Pastikan Anda menggunakan penyedia dengan user_project_override = true (tanpa alias), yang dalam contoh Firebase adalah google-beta.

Berikut kemungkinan alasan project ID mungkin sudah ada:

  • Project yang terkait dengan ID tersebut adalah milik orang lain.

    • Untuk mengatasi: Pilih project ID lain.
  • Project yang terkait dengan ID tersebut baru saja dihapus (dalam status penghapusan sementara).

    • Untuk mengatasi: Jika menurut Anda project yang terkait dengan ID tersebut adalah milik Anda, periksa statusnya menggunakan REST API projects.get.
  • Project yang terkait dengan ID tersebut ada dengan benar di bawah pengguna saat ini. Kemungkinan penyebab error ini adalah karena terraform apply sebelumnya terganggu.

    • Untuk mengatasi: Jalankan perintah berikut:
      terraform import google_project.default PROJECT_ID lalu
      terraform import google_firebase_project.default PROJECT_ID

Jika Anda menyediakan bucket Cloud Storage default (melalui google_app_engine_application) sebelum mencoba menyediakan instance Cloud Firestore default, Anda akan menemukan bahwa instance Cloud Firestore default telah disediakan. Perhatikan bahwa instance database yang disediakan berada dalam mode Datastore, artinya, instance ini tidak dapat diakses oleh Firebase SDK, autentikasi, atau Firebase Security Rules. Jika ingin menggunakan Cloud Firestore dengan layanan Firebase ini, Anda harus mengosongkan database, lalu mengubah jenis database-nya di Google Cloud console.

Saat Anda menyediakan bucket Cloud Storage default project (melalui google_app_engine_application) dan project belum memiliki instance Cloud Firestore, google_app_engine_application akan menyediakan instance Cloud Firestore default project secara otomatis.

Jadi, karena instance Cloud Firestore default project Anda sudah disediakan, google_firestore_database akan mengalami error jika Anda mencoba kembali menyediakan instance default tersebut secara eksplisit.

Setelah instance Cloud Firestore default project disediakan, Anda tidak dapat "menyediakannya ulang" atau mengubah lokasinya. Perhatikan bahwa instance database yang disediakan berada dalam mode Datastore, artinya, instance ini tidak dapat diakses oleh Firebase SDK, autentikasi, atau Firebase Security Rules. Jika ingin menggunakan Cloud Firestore dengan layanan Firebase ini, Anda harus mengosongkan database, lalu mengubah jenis database-nya di Google Cloud console.