A Terraform module for provisioning and installing Terraform Enterprise on Google Compute Engine as described in HashiCorp Validated Designs
MPL-2.0 License
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.
terraform.hclic
)>= 1.9
installed on clients/workstations that will be used to deploy TFEgit
CLI and Visual Studio Code editor installed on workstations are strongly recommendedGCP Secrets Manager "TFE bootstrap" secrets:
One of the following mechanisms for shell access to TFE GC instances:
One of the following logging destinations:
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
sandbox
environment, and one for theirproduction
environment. This is recommended, but not required.
(Optional) Uncomment and update the GCS remote state backend configuration provided in the backend.tf
file 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.example
file that was provided, and remove the .example
file extension such that the file is now named terraform.tfvars
.
Navigate to the directory of your newly created Terraform configuration for your TFE deployment, and run terraform init
, terraform plan
, and terraform apply
.
After your terraform apply
finishes 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
-f
argument is to follow the logs as they append in real-time, and is optional. You may remove the-f
for 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.
Below are links to docs pages related to deployment customizations as well as managing day 2 operations of your TFE instance.
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) |
[ "0.0.0.0/0"] | no |
cidr_ingress_ssh_allow | CIDR ranges to allow SSH traffic inbound to TFE instance(s) via IAP tunnel. | list(string) |
[ "10.0.0.0/16"] | 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 |