Terraform module that bootstraps the foundation needed to manage a Google Cloud environment with Terraform. In a single apply it provisions a project (optionally inside a new folder), enables the baseline APIs, creates a dedicated automation service account with impersonation wired up, and stands up a versioned GCS bucket for remote state.
It is intended as the first thing you run against a fresh organization or folder, before any workload Terraform. Authenticate as a privileged user (see Prerequisites) for the bootstrap apply; everything afterwards can run by impersonating the service account this module creates — no exported keys.
- Project creation with a random numeric suffix appended to the display name, so the project ID is globally unique without manual bookkeeping.
- Optional folder — create a new folder for the project, nest it under an existing
parent_folder, or place the project directly at the organization level. - Baseline APIs enabled by default:
serviceusage.googleapis.comandcloudresourcemanager.googleapis.com. - Automation service account with configurable project roles (defaults to
roles/editor) and a description, optionally created in a disabled state. - Impersonation, not keys — grants chosen principals (
sa_users) the roles needed to impersonate the service account (roles/iam.serviceAccountUserandroles/iam.serviceAccountTokenCreatorby default). - Remote state bucket — a versioned bucket with uniform bucket-level access, via the
FFerrinho/bucket/googlemodule, ready to host the state of everything you build next. - Mandatory labels —
managed = "terraform"andpurpose = "automation"are merged onto the project on top of anylabelsyou supply.
module "bootstrap" {
source = "FFerrinho/bootstrap/google"
version = "~> 1.0"
organization_id = "123456789012"
billing_account = "012345-6789AB-CDEF01"
region = "europe-west1"
project_display_name = "Platform Automation"
# Folder placement (see "Folder placement" below)
create_folder = true
folder_name = "platform"
# Automation service account
service_account_display_name = "terraform-automation"
# Principals allowed to impersonate the service account
sa_users = [
"user:platform-admin@example.com",
"group:platform-team@example.com",
]
}The project's location is driven by create_folder, folder_name, and parent_folder:
create_folder |
parent_folder |
Result |
|---|---|---|
true |
set | A new folder folder_name is created under parent_folder; the project goes inside it. |
true |
null |
A new folder folder_name is created at the organization level; the project goes inside it. |
false |
set | The project is created inside the existing folder referenced by parent_folder. |
false |
null |
The project is created directly at the organization level. |
Supply either organization_id or organization_domain — the module looks the organization
up from whichever you provide.
billing_account accepts either a billing account ID (format XXXXXX-XXXXXX-XXXXXX) or a billing
account display name; a display name is resolved to its ID via a data source.
The principal running the bootstrap apply needs organization- (or folder-) level permissions, since the module creates projects, folders, and IAM bindings. At a minimum:
roles/resourcemanager.projectCreatoron the org or target folderroles/resourcemanager.folderCreator(only whencreate_folder = true)roles/billing.useron the billing account (to associate it with the new project)- Permission to read the organization (
roles/resourcemanager.organizationViewer)
| Name | Version |
|---|---|
| terraform | >= 1.3 |
| ~> 7.0 |
| Name | Version |
|---|---|
| 7.38.0 | |
| random | 3.9.0 |
| Name | Source | Version |
|---|---|---|
| tf_state_bucket | FFerrinho/bucket/google | 1.0.2 |
| Name | Type |
|---|---|
| google_folder.main | resource |
| google_project.main | resource |
| google_project_iam_member.main | resource |
| google_project_service.main | resource |
| google_service_account.main | resource |
| google_service_account_iam_binding.main | resource |
| random_id.main | resource |
| google_billing_account.main | data source |
| google_folder.main | data source |
| google_organization.main | data source |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| auto_create_network | If the project should auto create a network. | bool |
false |
no |
| billing_account | The billing account id. | string |
n/a | yes |
| create_folder | If a folder will be created along the bootstrap. | bool |
false |
no |
| folder_name | The name for the folder. | string |
null |
no |
| labels | Additional labels for the resources. | map(string) |
{} |
no |
| organization_domain | The organization domain. | string |
null |
no |
| organization_id | The organization id. | string |
null |
no |
| parent_folder | The parent folder id. | string |
null |
no |
| project_deletion_policy | The deletion policy for the project. | string |
"DELETE" |
no |
| project_display_name | The project display name. | string |
n/a | yes |
| region | The region to create the resources. | string |
n/a | yes |
| sa_member_roles | SA roles to grant to users. | set(string) |
[ |
no |
| sa_users | A list of users that will be able to impersonate de service account. | set(string) |
n/a | yes |
| service_account_description | The description for the service account. | string |
"Terraform SA for infrastructure automation." |
no |
| service_account_disabled | If the service account should be disabled. Defaults to false. | bool |
false |
no |
| service_account_display_name | The display name for the service account. | string |
n/a | yes |
| service_account_roles | A list of roles to grant to the service account. | set(string) |
[ |
no |
| Name | Description |
|---|---|
| folder_name | The name fo the folder created or used in the bootstrap. |
| project_name | The name of the project created. |
| sa_users | The users that will impersonate the service account. |
| service_account | The service account created. |
| tf_state_bucket | The name of the bucket created for the terraform state. |
MIT — see LICENSE.