O Firebase está começando a oferecer suporte ao
Terraform.
Se a sua equipe quer automatizar e padronizar a criação de projetos
do Firebase com provisionamento de recursos e ativação de serviços específicos, usar o
Terraform e o Firebase pode ser uma boa opção.
O fluxo de trabalho básico para usar o Terraform com o Firebase inclui o seguinte:
Criação e personalização de um arquivo de configuração do Terraform (um arquivo .tf) que especifica a infraestrutura que você quer provisionar, ou seja, os recursos que você quer provisionar e os serviços que você quer ativar.
Uso de comandos da CLI gcloud que interagem com o Terraform para
provisionar a infraestrutura especificada no arquivo .tf.
O que você pode fazer com o Terraform e o Firebase?
Neste guia, o exemplo de fluxo de trabalho genérico
é criar um novo projeto do Firebase com um app Android. Mas você pode fazer muito
mais com o Terraform, como:
Excluir e modificar infraestruturas atuais usando o Terraform.
Gerenciar configurações e tarefas específicas do produto usando o Terraform, como:
Ativar os provedores de login do Firebase Authentication.
Criar buckets do Cloud Storage ou instâncias de bancos de dados e implantar
regras de segurança do Firebase.
Você pode usar arquivos de configuração e comandos padrão do Terraform para realizar todas essas
tarefas. Para ajudar nisso, mostramos
exemplos de arquivos de configuração do Terraform para vários casos de uso comuns.
Fluxo de trabalho genérico para uso do Terraform com o Firebase
Pré-requisitos
Este guia é uma introdução ao uso do Terraform com o Firebase, portanto, é necessário conhecer os princípios básicos do Terraform. Verifique se você concluiu os seguintes
pré-requisitos antes de iniciar esse fluxo de trabalho:
Confira os requisitos para contas de usuário e contas de serviço
Ao usar uma conta de usuário, você precisa aceitar os Termos de Serviço do Firebase (TOS do Firebase). Se você visualizou um projeto no Console do Firebase, então aceitou os TOS do Firebase.
Para que o Terraform realize algumas ações, como criar projetos,
o seguinte precisa ser verdadeiro:
O usuário ou a conta de serviço precisa ter o acesso de IAM aplicável para essas ações.
Se o usuário ou a conta de serviço fizer parte de uma organização do Google Cloud, as políticas da organização precisam permitir que a conta realize essas ações.
Etapa 1: criar e personalizar um arquivo de configuração do Terraform
Um arquivo de configuração do Terraform precisa de duas seções principais, explicadas em detalhes abaixo:
Uma configuração de provider é necessária, seja quais forem os produtos ou serviços do Firebase envolvidos.
Crie um arquivo de configuração do Terraform (como o main.tf) no diretório local.
Neste guia, você vai usar esse arquivo de configuração para especificar as características de provider e toda a infraestrutura a ser criada pelo Terraform. No entanto, você tem opções para incluir a configuração do provedor.
Conheça as maneiras de incluir a configuração de provider.
Você tem as seguintes opções para incluir uma definição de provider no restante da sua configuração do Terraform:
Opção 1: incluir na parte superior de um único arquivo de configuração .tf do Terraform, como mostrado neste guia.
Use essa opção se você estiver começando a usar o Terraform ou apenas
testando essa ferramenta com o Firebase.
Opção 2: incluir em um arquivo .tf separado (como um provider.tf), diferente do .tf, em que você especifica a infraestrutura a ser criada (como um arquivo main.tf).
Use essa opção se você fizer parte de uma equipe maior que precisa padronizar a configuração.
Ao executar os comandos do Terraform, os arquivos provider.tf e main.tf precisam estar no mesmo diretório.
Inclua a seguinte configuração de provider na parte superior do arquivo main.tf.
Use o provedor google-beta porque esta é uma versão Beta da integração do Firebase e Terraform. Tenha cuidado ao utilizar esse recurso na produção.
# Terraform configuration to set up providers by version.
terraform {
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 4.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
}
Acesse a próxima seção para concluir o arquivo de configuração e especificar qual infraestrutura será criada.
Especificar qual infraestrutura criar usando blocos de resource
No arquivo de configuração do Terraform (para este guia, o arquivo main.tf), é necessário especificar toda a infraestrutura que você quer que o Terraform crie, ou seja, todos os recursos a serem provisionados e todos os serviços a serem ativados. Neste guia você encontra uma lista completa de todos os
recursos do Firebase que oferecem suporte ao Terraform.
Abra seu arquivo main.tf.
Na configuração de provider, inclua a seguinte definição dos blocos de
resource.
Este exemplo básico cria um novo projeto do Firebase e, em seguida, um
app Android do Firebase nesse projeto.
# 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,
]
}
Confira uma versão
com várias anotações deste arquivo de exemplo de configuração
Se você não conhece a infraestrutura de projetos e apps como
recursos, consulte a seguinte documentação:
# 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,
]
}
Etapa 2: executar comandos do Terraform para criar a infraestrutura especificada
Para provisionar os recursos e ativar os serviços especificados no arquivo main.tf, execute os seguintes comandos no mesmo diretório de main.tf.
Se você quiser informações detalhadas sobre esses comandos, consulte a
documentação do Terraform.
Se esta for a primeira vez que você está executando comandos do Terraform no
diretório, inicialize o diretório de configuração e instale
o provedor do Google Terraform. Para isso, execute o seguinte comando:
terraform init
Crie a infraestrutura especificada no arquivo main.tf executando o
seguinte comando:
terraform apply
Confirme se tudo foi provisionado ou ativado conforme o esperado:
Opção 1: revise a configuração mostrada no terminal executando o
seguinte comando:
Os seguintes recursos do Firebase e do Google oferecem suporte ao Terraform. Novos recursos são adicionados constantemente. Portanto, se você não encontrar o que procura, volte em breve para conferir se ele está disponível ou solicite
ao informar um problema no repositório do GitHub.
google_identity_platform_config:
ative o Google Cloud Identity Platform (GCIP) (que é o back-end do Firebase Authentication)
e envie as configurações de autenticação no nível do projeto.
O projeto em que o Terraform vai ativar o GCIP e/ou o Firebase Authentication
precisa estar no plano de preços Blaze, ou seja, o projeto precisa ter uma
conta do Cloud Billing associada. Isso pode ser feito de maneira programática
configurando o atributo
billing_account
no recurso google_project.
Implantar regras de segurança do Firebase Realtime Database pelo Terraform (aprenda a
implantar essas regras
usando outras ferramentas, incluindo opções programáticas)
Importante: não use dados reais de usuários finais ou de produção neste arquivo.
Regras de segurança do Firebase (para o Cloud Firestore e o Cloud Storage)
O Firebase Realtime Database usa um sistema de provisionamento diferente para as regras de segurança do Firebase.
google_firebaserules_ruleset:
defina as regras de segurança do Firebase que se aplicam à instância do Cloud Firestore ou a um bucket do Cloud Storage.
google_firebaserules_release:
implante conjuntos de regras específicos na instância do Cloud Firestore ou em um bucket do Cloud Storage.
Exemplos de arquivos de configuração do Terraform para casos de uso comuns
Configurar o Firebase Authentication com o
GCIP
Essa configuração cria um novo projeto do Google Cloud, associa esse projeto a uma conta do Cloud Billing (o plano de preços Blaze é necessário para o Firebase Authentication com GCIP), ativa os serviços do Firebase para o projeto, configura o Firebase Authentication com o GCIP
e registra três tipos diferentes de apps no projeto.
A ativação do GCIP é necessária para configurar o Firebase Authentication pelo 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
# For example, you can configure to auto-delete Anonymous users.
autodelete_anonymous_users = true
# Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
depends_on = [
google_project_service.auth,
]
}
# Adds more configurations, like for the email/password sign-in provider.
resource "google_identity_platform_project_default_config" "auth" {
provider = google-beta
project = google_project.auth.project_id
sign_in {
allow_duplicate_emails = false
anonymous {
enabled = true
}
email {
enabled = true
password_required = false
}
}
# Wait for Authentication to be initialized before enabling email/password.
depends_on = [
google_identity_platform_config.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,
]
}
Provisionar a
instância padrão do Firebase Realtime Database
Essa configuração cria um novo projeto do Google Cloud, ativa os serviços do Firebase para o projeto, provisiona a instância padrão do Realtime Database dele e registra três tipos diferentes de app.
# 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/projects/locations#rtdb-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,
]
}
Provisionar várias
instâncias do Firebase Realtime Database
Essa configuração cria um novo projeto do Google Cloud, associa esse projeto a uma conta do Cloud Billing (o plano de preços Blaze é necessário para várias instâncias do Realtime Database), ativa os serviços do Firebase para ele, provisiona várias instâncias do Realtime Database, incluindo a instância padrão do Realtime Database, e registra três tipos diferentes de app.
# 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/projects/locations#rtdb-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,
]
}
Provisionar a
instância do Cloud Firestore
Essa configuração cria um novo projeto do Google Cloud,
ativa os serviços do Firebase,
provisiona a instância do Cloud Firestore do projeto
e registra três tipos diferentes de apps.
Também provisiona regras de segurança do Firebase para a instância do Cloud Firestore,
cria um índice do Cloud Firestore
e adiciona um documento do Cloud Firestore com dados de origem.
# 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/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.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,
]
}
Esse é o conjunto de regras de segurança do Cloud Firestore que deve estar em um arquivo local
chamado firestore.rules.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null;
}
}
Provisionar o
bucket padrão do Cloud Storage
Essa configuração cria um novo projeto do Google Cloud, ativa os serviços do Firebase nele, provisiona o bucket padrão do Cloud Storage e registra três tipos de apps diferentes.
Também provisiona regras de segurança do Firebase para o bucket do Cloud Storage
e faz upload de um arquivo para o bucket.
# Creates a new Google Cloud project.
resource "google_project" "storage" {
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" "storage" {
provider = google-beta.no_user_project_override
project = google_project.storage.project_id
for_each = toset([
"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" {
provider = google-beta
project = google_project.storage.project_id
}
# Provisions the default Cloud Storage bucket for the project via Google App Engine.
resource "google_app_engine_application" "default" {
provider = google-beta
project = google_project.storage.project_id
# See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
# This will set the location for the default Storage bucket and the App Engine App.
location_id = "name-of-region-for-default-bucket"
# If you use Firestore, uncomment this to make sure Firestore is provisioned first.
# depends_on = [
# google_firestore_database.firestore
# ]
}
# Makes the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "default-bucket" {
provider = google-beta
project = google_project.storage.project_id
bucket_id = google_app_engine_application.default.default_bucket
}
# Creates a ruleset of Cloud Storage Security Rules from a local file.
resource "google_firebaserules_ruleset" "storage" {
provider = google-beta
project = google_project.storage.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 default Storage bucket to be provisioned before creating this ruleset.
depends_on = [
google_firebase_project.storage,
]
}
# Releases the ruleset to the default Storage bucket.
resource "google_firebaserules_release" "default-bucket" {
provider = google-beta
name = "firebase.storage/${google_app_engine_application.default.default_bucket}"
ruleset_name = "projects/${google_project.storage.project_id}/rulesets/${google_firebaserules_ruleset.storage.name}"
project = google_project.storage.project_id
}
# Uploads a new file to the default Storage bucket.
# Don't use real end-user or production data in this file.
resource "google_storage_bucket_object" "cat-picture" {
provider = google-beta
name = "cat.png"
source = "path/to/cat.png"
bucket = google_app_engine_application.default.default_bucket
}
# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "storage" {
provider = google-beta
project = google_project.storage.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,
]
}
# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "storage" {
provider = google-beta
project = google_project.storage.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,
]
}
# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "storage" {
provider = google-beta
project = google_project.storage.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.storage,
]
}
Esse é o conjunto de regras de segurança do Cloud Storage que deve estar em um arquivo local
chamado storage.rules.
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Provisionar vários buckets do Cloud Storage
Essa configuração cria um novo projeto do Google Cloud, associa o projeto a uma conta do Cloud Billing (o plano de preços Blaze é necessário para vários buckets), ativa os serviços do Firebase, provisiona vários buckets do Cloud Storage
(incluindo o bucket padrão do projeto no Cloud Storage)
e registra três tipos diferentes de apps.
Também provisiona regras de segurança do Firebase para os buckets do Cloud Storage
e faz upload de um arquivo para o bucket padrão do 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 the default Cloud Storage bucket for the project via Google App Engine.
resource "google_app_engine_application" "default-multi" {
provider = google-beta
project = google_project.storage-multi.project_id
# See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
# This will set the location for the default Storage bucket and the App Engine App.
location_id = "name-of-region-for-default-bucket"
# If you use Firestore, uncomment this to make sure Firestore is provisioned first.
# depends_on = [
# google_firestore_database.firestore
# ]
}
# Provisions an additional Cloud Storage bucket.
# Additional Cloud Storage buckets are not provisioned via App Engine.
resource "google_storage_bucket" "bucket-multi" {
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 default Storage bucket.
location = "name-of-region-for-additional-bucket"
}
# Makes the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "default-bucket-multi" {
provider = google-beta
project = google_project.storage-multi.project_id
bucket_id = google_app_engine_application.default-multi.default_bucket
}
# Makes the additional Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-multi" {
provider = google-beta
project = google_project.storage-multi.project_id
bucket_id = google_storage_bucket.bucket-multi.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 default Storage bucket.
resource "google_firebaserules_release" "default-bucket-multi" {
provider = google-beta
name = "firebase.storage/${google_app_engine_application.default-multi.default_bucket}"
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-multi" {
provider = google-beta
name = "firebase.storage/${google_storage_bucket.bucket-multi.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 default 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_app_engine_application.default-multi.default_bucket
}
# 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"
# 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.storage-multi,
]
}
Esse é o conjunto de regras de segurança do Cloud Storage que deve estar em um arquivo local
chamado storage.rules.
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Provisionar a
instância do Cloud Firestore e o bucket padrão do Cloud Storage
Essa configuração cria um novo projeto do Google Cloud, ativa os serviços do Firebase para o projeto, provisiona a instância do Cloud Firestore e, em seguida, provisiona o bucket padrão do Cloud Storage.
Também provisiona regras de segurança do Firebase para a instância do Cloud Firestore e o bucket
padrão do Cloud Storage.
# Creates a new Google Cloud project.
resource "google_project" "fs" { # fs = Firestore + Storage
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" "fs" {
provider = google-beta.no_user_project_override
project = google_project.fs.project_id
for_each = toset([
"serviceusage.googleapis.com",
"cloudresourcemanager.googleapis.com",
"firebaserules.googleapis.com",
"firebasestorage.googleapis.com",
"storage.googleapis.com",
"firestore.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" "fs" {
provider = google-beta
project = google_project.fs.project_id
}
#### Set up Firestore before default Cloud Storage bucket ####
# Provisions the Firestore database instance.
resource "google_firestore_database" "firestore-fs" {
provider = google-beta
project = google_project.fs.project_id
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.fs,
]
}
# Creates a ruleset of Firestore Security Rules from a local file.
resource "google_firebaserules_ruleset" "firestore-fs" {
provider = google-beta
project = google_project.fs.project_id
source {
files {
# Write security rules in a local file named "firestore.rules".
# Learn more: https://firebase.google.com/docs/firestore/security/get-started
name = "firestore.rules"
content = file("firestore.rules")
}
}
# Wait for Firestore to be provisioned before creating this ruleset.
depends_on = [
google_firestore_database.firestore-fs
]
}
# Releases the ruleset for the Firestore instance.
resource "google_firebaserules_release" "firestore-fs" {
provider = google-beta
name = "cloud.firestore" # must be cloud.firestore
ruleset_name = google_firebaserules_ruleset.firestore-fs.name
project = google_project.fs.project_id
# Wait for Firestore to be provisioned before releasing the ruleset.
depends_on = [
google_firestore_database.firestore-fs,
]
}
#### Set up default Cloud Storage default bucket after Firestore ####
# Provisions the default Cloud Storage bucket for the project via Google App Engine.
resource "google_app_engine_application" "default-bucket-fs" {
provider = google-beta
project = google_project.fs.project_id
# See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
# This will set the location for the default Storage bucket and the App Engine App.
location_id = "name-of-region" # Must be in the same location as Firestore (above)
# Wait for Firestore to be provisioned first.
# Otherwise, the Firestore instance will be provisioned in Datastore mode (unusable by Firebase).
depends_on = [
google_firestore_database.firestore-fs,
]
}
# Makes the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "default-bucket-fs" {
provider = google-beta
project = google_project.fs.project_id
bucket_id = google_app_engine_application.default-bucket-fs.default_bucket
}
# Creates a ruleset of Cloud Storage Security Rules from a local file.
resource "google_firebaserules_ruleset" "default-bucket-fs" {
provider = google-beta
project = google_project.fs.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 Cloud Storage bucket to be provisioned before creating this ruleset.
depends_on = [
google_firebase_project.fs,
]
}
# Releases the ruleset to the default Storage bucket.
resource "google_firebaserules_release" "default-bucket-fs" {
provider = google-beta
name = "firebase.storage/${google_app_engine_application.default-bucket-fs.default_bucket}"
ruleset_name = "projects/${google_project.fs.project_id}/rulesets/${google_firebaserules_ruleset.default-bucket-fs.name}"
project = google_project.fs.project_id
}
Esse é o conjunto de regras de segurança do Cloud Firestore que deve estar em um arquivo local
chamado firestore.rules.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null;
}
}
Esse é o conjunto de regras de segurança do Cloud Storage que deve estar em um arquivo local
chamado storage.rules.
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Solução de problemas e perguntas frequentes
Conheça
todos os atributos relacionados ao projeto, como
project e user_project_override
Este guia usa os seguintes atributos do Terraform ao trabalhar com projetos.
project em um bloco resource
Recomendado: sempre que possível, inclua o atributo project em cada
bloco resource.
Ao incluir um atributo de projeto, o Terraform vai criar a infraestrutura especificada no bloco de recursos dentro do projeto especificado. Usamos essa prática neste guia e nos nossos arquivos de exemplo de configuração.
Consulte a documentação oficial do Terraform sobre
project.
user_project_override no bloco provider
Para provisionar a maioria dos recursos, use
user_project_override = true, o que significa verificar a cota do seu próprio
projeto do Firebase. No entanto, para configurar o novo projeto para que ele possa aceitar verificações de cota, primeiro você precisa usar user_project_override = false.
Você recebe este erro:
generic::permission_denied: Firebase Tos Not Accepted.
Verifique se a conta de usuário que você está usando para executar os comandos da CLI gcloud
aceitou os Termos de Serviço do Firebase (TOS do Firebase).
Para fazer isso, conecte-se à conta de usuário em um navegador e
tente visualizar um projeto existente do Firebase no
Console do Firebase. Se você conseguir visualizar um projeto existente do Firebase, então a conta de usuário aceitou os TOS do Firebase.
Se não, provavelmente a conta de usuário não aceitou os TOS do Firebase. Para corrigir isso, crie um novo
projeto do Firebase usando o
Console do Firebase e aceite os
TOS como parte da criação de projetos. Você pode excluir esse projeto imediatamente nas Configurações do projeto no console.
Depois de executar
terraform apply, você recebe este erro:
generic::permission_denied: IAM authority does not have the
permission.
Aguarde alguns minutos e tente executar terraform apply novamente.
Ocorreu um falha ao criar um recurso, mas, ao executar terraform apply novamente, ALREADY_EXISTS aparece.
Isso pode ocorrer devido a um atraso na propagação em vários sistemas. Para tentar resolver o problema, importe o recurso para o estado do Terraform e execute terraform import. Em seguida, tente executar terraform apply novamente.
Ao trabalhar com o
Cloud Firestore, você recebe este erro: Error creating Index: googleapi:
Error 409;...Concurrent access -- try again
Como o erro sugere, o Terraform pode estar tentando provisionar vários índices e/ou criar um documento ao mesmo tempo, e encontrou um erro de simultaneidade.
Tente executar terraform apply novamente.
Você recebe este erro:
"you may need to specify 'X-Goog-User-Project' HTTP header for quota and
billing purposes".
Esse erro significa que o Terraform não sabe em qual projeto deve verificar a cota. Para resolver problemas, verifique o seguinte no bloco resource:
Verifique se você especificou um valor para o atributo project.
Verifique se você está usando o provedor com user_project_override = true (sem alias), em que as amostras do Firebase são google-beta.
Ao criar um projeto do Google Cloud, você recebe o erro de que o ID do projeto especificado para o novo projeto já existe.
Confira os possíveis motivos disso:
O projeto associado a esse ID pertence a outra pessoa.
Para resolver o problema, escolha outro ID.
O projeto associado a esse ID foi excluído recentemente (no estado de
exclusão reversível).
Solução: se você achar que o projeto associado ao ID pertence a você, verifique o estado do projeto usando a API REST projects.get.
O projeto associado a esse ID existe corretamente no usuário atual. Uma
causa possível para o erro é a interrupção anterior na execução de terraform apply.
Solução: execute os seguintes comandos: terraform import google_project.default PROJECT_ID
e depois terraform import google_firebase_project.default PROJECT_ID
Ao
tentar provisionar o Cloud Firestore e, em seguida, o Cloud Storage (pelo
google_app_engine_application), você recebe este erro:
Error: Error creating App Engine application: googleapi: Error 409:
Cannot create Firestore database resource <resource-name> since it
already exists at location <location-id>, alreadyExists.
Um aplicativo do App Engine requer uma instância do Cloud Firestore, mas você só pode ter uma instância por projeto. Portanto, como a mensagem de erro sugere,
se você já tiver provisionado a instância do Cloud Firestore no projeto em um
local, o App Engine vai mostrar um erro caso tente provisionar uma instância do Cloud Firestore em um local diferente. O App Engine pensa que você está tentando "re-provisionar" a instância do Cloud Firestore.
Para resolver esse erro, use o mesmo local para o Cloud Firestore e o aplicativo do App Engine. Se você precisar incluir um bucket do Cloud Storage em um
local diferente do Cloud Firestore, provisione buckets adicionais
(consulte a
configuração de amostra para criar vários buckets do
Cloud Storage).
Ao
tentar provisionar o Cloud Storage (via
google_app_engine_application) e, em seguida, o Cloud Firestore, você recebe
este erro:
Error: Error creating Database: googleapi: Error 409: Database already
exists. Please use another database_id.
Quando você provisiona o bucket padrão do Cloud Storage de um projeto (usando
google_app_engine_application) e o projeto ainda não tem uma
instância do Cloud Firestore, google_app_engine_application provisiona automaticamente
a instância do Cloud Firestore no projeto.
Portanto, se a instância do Cloud Firestore no seu projeto já estiver provisionada,
o erro google_firestore_database vai ser mostrado caso você tente provisionar explicitamente uma
instância do Cloud Firestore.
Depois que a instância do Cloud Firestore do projeto for provisionada, não vai ser possível
provisioná-la novamente ou mudar o local dela. Para interromper o erro,
remova o bloco de recursos google_firestore_database do arquivo de configuração.
No entanto, recomendamos que você provisione o Cloud Firestore antes do
bucket padrão do Cloud Storage do projeto pelo motivo descrito abaixo.