Terraform module aligned with HashiCorp Validated Designs (HVD) to deploy Terraform Enterprise (TFE) on Google Cloud Platform (GCP) using Compute Engine instances with a container runtime. This module defaults to deploying TFE in the active-active operational mode, but external is also supported. Docker is currently the only supported container runtime, but Podman support is being added.
- TFE license file (e.g.
terraform.hclic) - Terraform CLI
>= 1.9installed on clients/workstations that will be used to deploy TFE - General understanding of how to use Terraform (Community Edition)
- General understanding of how to use GCP
gitCLI and Visual Studio Code editor installed on workstations are strongly recommended- GCP projeect that TFE will be deployed in with permissions to provision these resources via Terraform CLI
- (Optional) GCP GCS bucket for GCS remote state backend that will be used to manage the Terraform state of this TFE deployment (out-of-band from the TFE application) via Terraform CLI (Community Edition)
- GCP network VPC and the following subnets:
- Load balancer subnetwork IDS (can be the same as Compute Engine (CE) subnets if desirable).
- (Optional) GCS VPC Endpoint configured within VPC.
- (Optional) GCS Hosted Zone for TFE DNS record creation.
- Security groups. This module will create the:
- necessary security groups and attach them to the applicable resources.
- service accounts and assign them access to the provided secrets
- firewall entries.
- Ensure the TFE ingress requirements are met.
- Ensure the TFE egress requirements are met.
GCP Secrets Manager "TFE bootstrap" secrets:
- TFE license file - raw contents of file stored as a plaintext secret.
- TFE encryption password - random characters stored as plaintext secret.
- RDS (PostgreSQL) database password - random characters stored as plaintext secret.
- (Optional) Redis password - random characters stored as a plaintext secret.
- TFE TLS certificate - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
- TFE TLS certificate private key - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
- TLS CA bundle - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
One of the following mechanisms for shell access to TFE GC instances:
- Ability to enable GCP IAP (this module supports this via a boolean input variable).
- GC SSH Key Pair
One of the following logging destinations:
- Stackdriver
- A custom fluent bit configuration that will forward logs to custom destination.
-
Create/configure/validate the applicable prerequisites.
-
Nested within the examples directory are subdirectories containing ready-made Terraform configurations for example scenarios on how to call and deploy this module. To get started, choose the example scenario that most closely matches your requirements. You can customize your deployment later by adding additional module inputs as you see fit (see the Deployment-Customizations doc for more details).
-
Copy all of the Terraform files from your example scenario of choice into a new destination directory to create your Terraform configuration that will manage your TFE deployment. This is a common directory structure for managing multiple TFE deployments:
. └── environments ├── production │  ├── backend.tf │  ├── main.tf │  ├── outputs.tf │  ├── terraform.tfvars │  └── variables.tf └── sandbox ├── backend.tf ├── main.tf ├── outputs.tf ├── terraform.tfvars └── variables.tf📝 Note: in this example, the user will have two separate TFE deployments; one for their
sandboxenvironment, and one for theirproductionenvironment. This is recommended, but not required. -
(Optional) Uncomment and update the GCS remote state backend configuration provided in the
backend.tffile with your own custom values. While this step is highly recommended, it is technically not required to use a remote backend config for your TFE deployment. -
Populate your own custom values into the
terraform.tfvars.examplefile that was provided, and remove the.examplefile extension such that the file is now namedterraform.tfvars. -
Navigate to the directory of your newly created Terraform configuration for your TFE deployment, and run
terraform init,terraform plan, andterraform apply. -
After your
terraform applyfinishes successfully, you can monitor the installation progress by connecting to your TFE gcp instance shell via SSH or gcp IAP and observing the meta data script(user_data) logs:Higher-level logs:
tail -f /var/log/tfe-cloud-init.log
Lower-level logs:
sudo journalctl -u google-startup-scripts.service -f
📝 Note: the
-fargument is to follow the logs as they append in real-time, and is optional. You may remove the-ffor a static view.The log files should display the following message after the cloud-init (user_data) script finishes successfully:
[INFO] tfe_user_data script finished successfully! -
After the cloud-init (user_data) script finishes successfully, while still connected to the TFE CE instance shell, you can check the health status of TFE:
cd /etc/tfe sudo docker compose exec terraform-enterprise tfe-health-check-status
-
Follow the steps to here to create the TFE initial admin user.
- the module includes outputs for the initial admin user token retrieval.
Below are links to docs pages related to deployment customizations as well as managing day 2 operations of your TFE instance.
- deployment-customizations.md
- operations.md
- tfe-tls-cert-rotation.md
- tfe-config-settings.md
- tfe-version-upgrades.md
- troubleshooting.md
| Name | Version |
|---|---|
| terraform | ~> 1.9 |
| ~> 5.39 | |
| google-beta | ~> 5.39 |
| random | ~> 3.6 |
| Name | Version |
|---|---|
| ~> 5.39 | |
| google-beta | ~> 5.39 |
| random | ~> 3.6 |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| friendly_name_prefix | Friendly name prefix used for uniquely naming resources. | string |
n/a | yes |
| network | The VPC network to host the cluster in | string |
n/a | yes |
| project_id | ID of GCP Project to create resources in. | string |
n/a | yes |
| region | Region of GCP Project to create resources in. | string |
n/a | yes |
| subnet | Existing VPC subnet for TFE instance(s) and optionally TFE frontend load balancer. | string |
n/a | yes |
| tfe_encryption_password_secret_id | ID of Secrets Manager secret for TFE encryption password. | string |
n/a | yes |
| tfe_fqdn | Fully qualified domain name of TFE instance. This name should resolve to the load balancer IP address and will be what clients use to access TFE. | string |
n/a | yes |
| tfe_license_secret_id | ID of Secrets Manager secret for TFE license file. | string |
n/a | yes |
| tfe_tls_ca_bundle_secret_id | ID of Secrets Manager secret for private/custom TLS Certificate Authority (CA) bundle in PEM format. Secret must be stored as a base64-encoded string. | string |
n/a | yes |
| tfe_tls_cert_secret_id | ID of Secrets Manager secret for TFE TLS certificate in PEM format. Secret must be stored as a base64-encoded string. | string |
n/a | yes |
| tfe_tls_privkey_secret_id | ID of Secrets Manager secret for TFE TLS private key in PEM format. Secret must be stored as a base64-encoded string. | string |
n/a | yes |
| cidr_ingress_https_allow | CIDR ranges to allow HTTPS traffic inbound to TFE instance(s). | list(string) |
[ |
no |
| cidr_ingress_ssh_allow | CIDR ranges to allow SSH traffic inbound to TFE instance(s) via IAP tunnel. | list(string) |
[ |
no |
| cloud_dns_managed_zone | Zone name to create TFE Cloud DNS record in if create_cloud_dns_record is set to true. |
string |
null |
no |
| common_labels | Common labels to apply to GCP resources. | map(string) |
{} |
no |
| create_cloud_dns_record | Boolean to create Google Cloud DNS record for tfe_fqdn resolving to load balancer IP. cloud_dns_managed_zone is required when true. |
bool |
false |
no |
| custom_fluent_bit_config | Custom Fluent Bit configuration for log forwarding. Only valid when tfe_log_forwarding_enabled is true and log_fwd_destination_type is custom. |
string |
null |
no |
| disk_size_gb | Size in Gigabytes of root disk of TFE instance(s). | number |
50 |
no |
| docker_version | Full Version version string for OS choice while installing Docker to install on TFE GCP instances. | string |
"26.1.4-1" |
no |
| enable_active_active | Boolean indicating whether to deploy TFE in the Active:Active architecture using external Redis. | bool |
false |
no |
| enable_iap | (Optional bool) Enable https://cloud.google.com/iap/docs/using-tcp-forwarding#console, defaults to true. |
bool |
true |
no |
| extra_no_proxy | A comma-separated string of hostnames or IP addresses to configure for TFE no_proxy list. | string |
"" |
no |
| gcs_bucket_key_name | Name of KMS Key to use for gcs bucket encryption. | string |
null |
no |
| gcs_bucket_keyring_name | Name of KMS Key Ring that contains KMS key to use for gcs bucket encryption. Geographic location of key ring must match gcs_bucket_location. |
string |
null |
no |
| gcs_bucket_location | [Optional one of ca,us, europe, asia,au,nam-eur-asia1] Location for GCS bucket. All regions are multi-region https://cloud.google.com/kms/docs/locations |
string |
"us" |
no |
| gcs_force_destroy | Boolean indicating whether to allow force destroying the gcs bucket. If set to true the gcs bucket can be destroyed if it is not empty. |
bool |
false |
no |
| http_proxy | Proxy address to configure for TFE to use for outbound connections. | string |
"" |
no |
| image_name | VM image for TFE instance(s). | string |
"ubuntu-2404-noble-amd64-v20240607" |
no |
| image_project | ID of project in which the resource belongs. | string |
"ubuntu-os-cloud" |
no |
| initial_delay_sec | The number of seconds that the managed instance group waits before it applies autohealing policies to new instances or recently recreated instances | number |
1200 |
no |
| instance_count | Target size of Managed Instance Group for number of TFE instances to run. Only specify a value greater than 1 if enable_active_active is set to true. |
number |
1 |
no |
| is_secondary_region | Boolean indicating whether this TFE deployment is in the 'primary' region or 'secondary' region. | bool |
false |
no |
| load_balancing_scheme | Determines whether load balancer is internal-facing or external-facing. | string |
"external" |
no |
| log_fwd_destination_type | Type of log forwarding destination. Valid values are stackdriver or custom. |
string |
"stackdriver" |
no |
| machine_type | (Optional string) Size of machine to create. Default n2-standard-4 from https://cloud.google.com/compute/docs/machine-resource. |
string |
"n2-standard-4" |
no |
| network_project_id | ID of GCP Project where the existing VPC resides if it is different than the default project. | string |
null |
no |
| postgres_availability_type | Availability type of Cloud SQL PostgreSQL instance. | string |
"REGIONAL" |
no |
| postgres_backup_start_time | HH:MM time format indicating when daily automatic backups should run. | string |
"00:00" |
no |
| postgres_disk_size | Size in GB of PostgreSQL disk. | number |
50 |
no |
| postgres_extra_params | Parameter keyword/value pairs to support additional PostgreSQL parameters that may be necessary. | string |
"sslmode=require" |
no |
| postgres_key_name | Name of KMS Key to use for Cloud SQL for PostgreSQL encryption. | string |
null |
no |
| postgres_keyring_name | Name of KMS Key Ring that contains KMS key to use for Cloud SQL for PostgreSQL database encryption. Geographic location of key ring must match location of database instance. | string |
null |
no |
| postgres_machine_type | Machine size of Cloud SQL PostgreSQL instance. | string |
"db-custom-4-16384" |
no |
| postgres_version | PostgreSQL version to use. | string |
"POSTGRES_15" |
no |
| redis_auth_enabled | Boolean to enable authentication on Redis instance. | bool |
true |
no |
| redis_connect_mode | Network connection mode for Redis instance. | string |
"PRIVATE_SERVICE_ACCESS" |
no |
| redis_memory_size_gb | The size of the Redis instance in GiB. | number |
6 |
no |
| redis_tier | The service tier of the Redis instance. Set to STANDARD_HA for high availability. |
string |
"STANDARD_HA" |
no |
| redis_transit_encryption_mode | Boolean to enable TLS for Redis instance. | string |
"DISABLED" |
no |
| redis_version | The version of Redis software. | string |
"REDIS_6_X" |
no |
| tfe_capacity_concurrency | Maximum number of concurrent Terraform runs to allow on a TFE node. | number |
10 |
no |
| tfe_capacity_cpu | Maxium number of CPU cores that a Terraform run is allowed to consume in TFE. Set to 0 for no limit. |
number |
0 |
no |
| tfe_capacity_memory | Maximum amount of memory (in MiB) that a Terraform run is allowed to consume in TFE. | number |
2048 |
no |
| tfe_database_password_secret_id | ID of secret stored in GCP Secrets Manager containing TFE install secrets. | string |
null |
no |
| tfe_hairpin_addressing | Boolean to enable hairpin addressing for Layer 4 load balancer with loopback prevention. Only valid when lb_is_internal is false, as hairpin addressing will automatically be enabled when lb_is_internal is true, regardless of this setting. |
bool |
true |
no |
| tfe_iact_subnets | Comma-separated list of subnets in CIDR notation that are allowed to retrieve the initial admin creation token via the API, or GUI | string |
"" |
no |
| tfe_iact_time_limit | Number of minutes that the initial admin creation token can be retrieved via the API after the application starts. Defaults to 60 | string |
"60" |
no |
| tfe_iact_trusted_proxies | Comma-separated list of subnets in CIDR notation that are allowed to retrieve the initial admin creation token via the API, or GUI | string |
"" |
no |
| tfe_image_name | Name of the TFE container image. Only set this if you are hosting the TFE container image in your own custom repository. | string |
"hashicorp/terraform-enterprise" |
no |
| tfe_image_repository_password | Pasword for container registry where TFE container image is hosted. Leave null if using the default TFE registry as the default password is the TFE license file. | string |
null |
no |
| tfe_image_repository_url | Repository for the TFE image. Only set this if you are hosting the TFE container image in your own custom repository. | string |
"images.releases.hashicorp.com" |
no |
| tfe_image_repository_username | Username for container registry where TFE container image is hosted. | string |
"terraform" |
no |
| tfe_image_tag | Tag for the TFE image. This represents the version of TFE to deploy. | string |
"v202402-2" |
no |
| tfe_license_reporting_opt_out | Boolean to opt out of license reporting. | bool |
false |
no |
| tfe_log_forwarding_enabled | Boolean to enable TFE log forwarding feature. | bool |
false |
no |
| tfe_metrics_enable | Boolean to enable metrics. | bool |
false |
no |
| tfe_metrics_http_port | HTTP port for TFE metrics scrape. | number |
9090 |
no |
| tfe_metrics_https_port | HTTPS port for TFE metrics scrape. | number |
9091 |
no |
| tfe_mounted_disk_path | (Optional) Path for mounted disk source, defaults to /opt/hashicorp/terraform-enterprise | string |
"/opt/hashicorp/terraform-enterprise/data" |
no |
| tfe_operational_mode | Operational mode for TFE. | string |
"active-active" |
no |
| tfe_run_pipeline_docker_network | Docker network where the containers that execute Terraform runs will be created. The network must already exist, it will not be created automatically. Leave null to use the default network. | string |
null |
no |
| tfe_run_pipeline_image | Name of the Docker image to use for the run pipeline driver. | string |
null |
no |
| tfe_run_pipeline_image_ecr_repo_name | Name of the ECR repository containing your custom TFE run pipeline image. | string |
null |
no |
| tfe_tls_enforce | Boolean to enforce TLS. | bool |
false |
no |
| tfe_user_data_template | (optional) File name for user_data_template.sh.tpl file in ./templates folder no path required |
string |
"tfe_user_data.sh.tpl" |
no |
| tfe_vault_disable_mlock | Boolean to disable mlock for internal Vault. | bool |
false |
no |
| verbose_template | [Optional bool] Enables the user_data template to be output in full for debug and review purposes. | bool |
false |
no |
| Name | Description |
|---|---|
| gcp_db_instance_ip | Cloud SQL DB instance IP. |
| gcs_bucket_name | Name of TFE gcs bucket. |
| google_sql_database_instance_id | ID of Cloud SQL DB instance. |
| lb_ip_address | IP Address of the Load Balancer. |
| tfe_fqdn | tfe_fqdn input. |
| tfe_initial_user_url | Terraform-Enterprise URL create initial admin user based on the tfe_fqdn input, and tfe_iact_subnets is set |
| tfe_retrieve_iact | Terraform-Enterprise URL to retrieve initial user token based on tfe_fqdn input, and tfe_iact_subnets is set |
| url | URL of TFE application based on tfe_fqdn input. |
| user_data_template | n/a |
