Terraform module aligned with HashiCorp Validated Designs (HVD) to deploy Boundary Enterprise Controller(s) on Microsoft Azure using Azure Virtual Machines. This module is designed to work with the complimentary Boundary Enterprise Worker HVD on Azure VM module.
- Terraform CLI
>= 1.9installed on workstation - Azure subscription that Boundary Controller will be hosted in with admin-like permissions to provision resources in via Terraform CLI
- Azure Blob Storage Account for AzureRM Remote State backend is recommended but not required
GitCLI and Visual Studio Code editor installed on workstation are recommended but not required
- Azure VNet ID
- Load balancer subnet ID for cluster lb. API LB will also need one if it is to be internal
- Load balancer static IP address for Cluster LB and for API if api load balancer is to be internal
- Controller subnet ID with service endpoints enabled for
Microsoft.key_vault, andMicrosoft.Sql - Database subnet ID with service delegation configured for
Microsoft.DBforPostgreSQL/flexibleServersfor join action (Microsoft.Network/virtualNetworks/subnets/join/action) - Ability to create private endpoints on the database subnets
- Network Security Group (NSG)/firewall rules:
- Allow
TCP/443ingress from Boundary user clients access subnets to load balancer subnet (if api load balancer is internal) or VM subnet (if load balancer is external) - Allow
TCP/9201ingress from subnets that will contain Boundary Ingress Worker(s) - Allow
TCP/443ingress from load balancer subnet to VM subnet (if load balancer is internal) - Allow
TCP/5432ingress from Controller subnet to database subnet (for PostgreSQL traffic)
- Allow
-
Boundary license - raw contents of Boundary license file (
*.hclic) (ex:cat boundary.hclic) -
Boundary database password - used to create PostgreSQL Flexible Server; randomly generate this yourself (avoid the
$character as Azure PostgreSQL Flexible Server does not like it), fetched from within the module via data source. -
Boundary TLS certificate - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
-
Boundary TLS private key - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
-
Boundary custom CA bundle - file in PEM format, base64-encoded into a string, and stored as a plaintext secret.
📝 Note: see the Boundary cert rotation docs for instructions on how to base64-encode the certificates with proper formatting.
This module supports creating the necessary Key Vaults, Controller and Worker and associated keys, Root, Recovery, and Worker with the variables, create_boundary_controller_key_vault, create_boundary_worker_key_vault, create_boundary_controller_root_key, create_boundary_worker_key_vault, and create_boundary_worker_key. If due to security policy KMS keys have to be provisioned outside this module, these variables can be set to false and the the key vault name for the controller and worker key vaults, the resource group names, and the key names can be provided with these variables: boundary_controller_key_vault_rg_name, boundary_controller_key_vault_name, root_key_name, recovery_key_name, boundary_worker_key_vault_rg_name, boundary_worker_key_vault_name, and worker_key_name.
📝 Note: The Worker Key should be in a separate Key Vault than the Root and Recovery Keys, as Azure IAM does not allow individual permissions to Keys, only to Key Vaults, and the Worker(s) should never have access to the Root and Recovery Keys.
One of the following mechanisms for shell access to Boundary EC2 instances:
- A mechanism for shell access to Azure Linux VMs within VMSS (SSH key pair, bastion host, username/password, etc.)
-
Create/configure/validate the applicable prerequisites.
-
Nested within the examples directory are subdirectories that contain ready-made Terraform configurations of example scenarios for how to call and deploy this module. To get started, choose an example scenario. If you are not sure which example scenario to start with, then we recommend starting with the default example.
-
Copy all of the Terraform files from your example scenario of choice into a new destination directory to create your root Terraform configuration that will manage your Boundary deployment. If you are not sure where to create this new directory, it is common for us to see users create an
environments/directory at the root of this repo, and then a subdirectory for each Boundary instance deployment, like so:. └── 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 Boundary deployments; one for their
sandboxenvironment, and one for theirproductionenvironment. This is recommended, but not required. -
(Optional) Uncomment and update the AzureRM 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 Boundary 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 Boundary Controller deployment, and run
terraform init,terraform plan, andterraform apply. -
After the
terraform applyfinishes successfully, you can monitor the install progress by connecting to the VM in your Boundary Controller Virtual Machine Scaleset (VMSS) via SSH and observing the cloud-init (user_data) logs:Higher-level logs:
tail -f /var/log/boundary-cloud-init.log
Lower-level logs:
journalctl -xu cloud-final -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] boundary_custom_data script finished successfully! -
Once the cloud-init script finishes successfully, while still connected to the VM via SSH you can check the status of the boundary service:
sudo systemctl status boundary
-
After the Boundary Controller is deployed the Boundary system will be partially initialized. To complete the initialization process and setup an initial auth method, username and password, please use the terraform-boundary-bootstrap-hvd module
-
Use the terraform-azurerm-boundary-worker-hvd module to deploy ingress, egress, etc workers as needed.
Below are links to docs pages related to deployment customizations and day 2 operations of your Boundary Controller instance.
- Deployment Customizations
- Upgrading Boundary version
- Rotating Boundary TLS/SSL certificates
- Updating/modifying Boundary configuration settings
- Deploying in Azure GovCloud
- Authenticate to Boundary Cluster with Boundary CLI
This open source software is maintained by the HashiCorp Technical Field Organization, independently of our enterprise products. While our Support Engineering team provides dedicated support for our enterprise offerings, this open source software is not included.
- For help using this open source software, please engage your account team.
- To report bugs/issues with this open source software, please open them directly against this code repository using the GitHub issues feature.
Please note that there is no official Service Level Agreement (SLA) for support of this software as a HashiCorp customer. This software falls under the definition of Community Software/Versions in your Agreement. We appreciate your understanding and collaboration in improving our open source projects.
| Name | Version |
|---|---|
| terraform | >= 1.9 |
| azurerm | ~> 3.101 |
| Name | Version |
|---|---|
| azurerm | ~> 3.101 |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| additional_package_names | List of additional repository package names to install | set(string) |
[] |
no |
| api_lb_is_internal | Boolean to create an internal or external Azure Load Balancer for boundary. | bool |
false |
no |
| api_lb_private_ip | Private IP address for internal Azure Load Balancer. Only valid when lb_is_internal is true. |
string |
null |
no |
| api_lb_subnet_id | Subnet ID for Boundary API load balancer. | string |
null |
no |
| availability_zones | List of Azure Availability Zones to spread boundary resources across. | set(string) |
[ |
no |
| boundary_controller_key_vault_name | Name of the existing Azure Key Vault to use for Boundary Controller keys. | string |
null |
no |
| boundary_controller_key_vault_rg_name | Name of the existing Resource Group containing the Azure Key Vault to use for Boundary Controller keys. | string |
null |
no |
| boundary_database_name | PostgreSQL database name for boundary. | string |
"boundary" |
no |
| boundary_database_paramaters | PostgreSQL server parameters for the connection URI. Used to configure the PostgreSQL connection. | string |
"sslmode=require" |
no |
| boundary_database_password_key_vault_secret_name | Name of the secret in the Key Vault that contains the boundary database password. | string |
n/a | yes |
| boundary_fqdn | Fully qualified domain name of boundary instance. This name should resolve to the load balancer IP address and will be what clients use to access boundary. | string |
n/a | yes |
| boundary_license_key_vault_secret_id | ID of Key Vault secret containing boundary license. | string |
n/a | yes |
| boundary_license_reporting_opt_out | Boolean to opt out of license reporting. | bool |
false |
no |
| boundary_tls_ca_bundle_key_vault_secret_id | ID of Key Vault secret containing boundary TLS custom CA bundle. | string |
n/a | yes |
| boundary_tls_cert_key_vault_secret_id | ID of Key Vault secret containing boundary TLS certificate. | string |
n/a | yes |
| boundary_tls_disable | Boolean to disable TLS for boundary. | bool |
false |
no |
| boundary_tls_privkey_key_vault_secret_id | ID of Key Vault secret containing boundary TLS private key. | string |
n/a | yes |
| boundary_version | Version of Boundary to install. | string |
"0.17.1+ent" |
no |
| boundary_worker_key_vault_name | Name of the existing Azure Key Vault to use for Boundary Worker keys. | string |
null |
no |
| boundary_worker_key_vault_rg_name | Name of the existing Resource Group containing the Azure Key Vault to use for Boundary Worker keys. | string |
null |
no |
| cluster_lb_private_ip | Private IP address for internal Azure Load Balancer. | string |
n/a | yes |
| cluster_lb_subnet_id | Subnet ID for Boundary 1ster load balancer. | string |
null |
no |
| common_tags | Map of common tags for taggable Azure resources. | map(string) |
{} |
no |
| controller_subnet_id | Subnet ID for controller VMs. | string |
n/a | yes |
| create_boundary_controller_key_vault | Boolean to create a Key Vault for Boundary Controller. | bool |
true |
no |
| create_boundary_controller_recovery_key | Boolean to create a recovery key in the Boundary Controller Key Vault. | bool |
true |
no |
| create_boundary_controller_root_key | Boolean to create a root key in the Boundary Controller Key Vault. | bool |
true |
no |
| create_boundary_private_dns_record | Boolean to create a DNS record for boundary in a private Azure DNS zone. private_dns_zone_name must also be provided when true. |
bool |
false |
no |
| create_boundary_public_dns_record | Boolean to create a DNS record for boundary in a public Azure DNS zone. public_dns_zone_name must also be provided when true. |
bool |
false |
no |
| create_boundary_worker_key | Boolean to create the worker key. | bool |
true |
no |
| create_boundary_worker_key_vault | Boolean to create a Key Vault for Boundary Worker. | bool |
true |
no |
| create_postgres_private_endpoint | Boolean to create a private endpoint and private DNS zone for PostgreSQL Flexible Server. | bool |
true |
no |
| create_resource_group | Boolean to create a new Resource Group for this boundary deployment. | bool |
true |
no |
| db_subnet_id | Subnet ID for PostgreSQL database. | string |
n/a | yes |
| friendly_name_prefix | Friendly name prefix for uniquely naming Azure resources. | string |
n/a | yes |
| is_govcloud_region | Boolean indicating whether this boundary deployment is in an Azure Government Cloud region. | bool |
false |
no |
| key_vault_cidr_allow_list | List of CIDR blocks to allow access to the Key Vault. This should be the public IP address of the machine running the Terraform deployment. | list(string) |
[] |
no |
| location | Azure region for this boundary deployment. | string |
n/a | yes |
| postgres_administrator_login | Username for administrator login of PostreSQL database. | string |
"boundary" |
no |
| postgres_backup_retention_days | Number of days to retain backups of PostgreSQL Flexible Server. | number |
35 |
no |
| postgres_cmk_key_vault_id | ID of the Key Vault containing the customer-managed key (CMK) for encrypting the PostgreSQL Flexible Server database. | string |
null |
no |
| postgres_cmk_key_vault_key_id | ID of the Key Vault key to use for customer-managed key (CMK) encryption of PostgreSQL Flexible Server database. | string |
null |
no |
| postgres_create_mode | Determines if the PostgreSQL Flexible Server is being created as a new server or as a replica. | string |
"Default" |
no |
| postgres_enable_high_availability | Boolean to enable ZoneRedundant high availability with PostgreSQL database. |
bool |
false |
no |
| postgres_geo_backup_key_vault_key_id | ID of the Key Vault key to use for customer-managed key (CMK) encryption of PostgreSQL Flexible Server geo-redundant backups. This key must be in the same region as the geo-redundant backup. | string |
null |
no |
| postgres_geo_backup_user_assigned_identity_id | ID of the User-Assigned Identity to use for customer-managed key (CMK) encryption of PostgreSQL Flexible Server geo-redundant backups. This identity must have 'Get', 'WrapKey', and 'UnwrapKey' permissions to the Key Vault. | string |
null |
no |
| postgres_geo_redundant_backup_enabled | Boolean to enable PostreSQL geo-redundant backup configuration in paired Azure region. | bool |
true |
no |
| postgres_maintenance_window | Map of maintenance window settings for PostgreSQL Flexible Server. | map(number) |
{ |
no |
| postgres_primary_availability_zone | Number for the availability zone for the primary PostgreSQL Flexible Server instance to reside in. | number |
1 |
no |
| postgres_secondary_availability_zone | Number for the availability zone for the standby PostgreSQL Flexible Server instance to reside in. | number |
2 |
no |
| postgres_sku | PostgreSQL database SKU. | string |
"GP_Standard_D4ds_v4" |
no |
| postgres_source_server_id | ID of the source PostgreSQL Flexible Server to replicate from. Only valid when is_secondary_region is true and postgres_create_mode is Replica. |
string |
null |
no |
| postgres_storage_mb | Storage capacity of PostgreSQL Flexible Server (unit is megabytes). | number |
65536 |
no |
| postgres_version | PostgreSQL database version. | number |
16 |
no |
| prereqs_key_vault_id | ID of the 'prereqs' Key Vault to use for prereqs boundary deployment. | string |
n/a | yes |
| prereqs_key_vault_name | Name of the 'prereqs' Key Vault to use for prereqs boundary deployment. | string |
n/a | yes |
| prereqs_key_vault_rg_name | Name of the Resource Group where the 'prereqs' Key Vault resides. | string |
n/a | yes |
| private_dns_zone_name | Name of existing private Azure DNS zone to create DNS record in. Required when create_boundary_private_dns_record is true. |
string |
null |
no |
| private_dns_zone_rg | Name of Resource Group where private_dns_zone_name resides. Required when create_boundary_private_dns_record is true. |
string |
null |
no |
| public_dns_zone_name | Name of existing public Azure DNS zone to create DNS record in. Required when create_boundary_public_dns_record is true. |
string |
null |
no |
| public_dns_zone_rg | Name of Resource Group where public_dns_zone_name resides. Required when create_boundary_public_dns_record is true. |
string |
null |
no |
| recovery_key_name | Name of the existing recovery key in the Boundary Controller Key Vault. | string |
null |
no |
| resource_group_name | Name of Resource Group to create. | string |
"boundary-controller-rg" |
no |
| root_key_name | Name of the existing root key in the Boundary Controller Key Vault. | string |
null |
no |
| vm_admin_username | Admin username for VMs in VMSS. | string |
"boundaryadmin" |
no |
| vm_custom_image_name | Name of custom VM image to use for VMSS. If not using a custom image, leave this blank. | string |
null |
no |
| vm_custom_image_rg_name | Resource Group name where the custom VM image resides. Only valid if vm_custom_image_name is not null. |
string |
null |
no |
| vm_disk_encryption_set_name | Name of the Disk Encryption Set to use for VMSS. | string |
null |
no |
| vm_disk_encryption_set_rg | Name of the Resource Group where the Disk Encryption Set to use for VMSS exists. | string |
null |
no |
| vm_enable_boot_diagnostics | Boolean to enable boot diagnostics for VMSS. | bool |
false |
no |
| vm_image_offer | Offer of the VM image. | string |
"0001-com-ubuntu-server-jammy" |
no |
| vm_image_publisher | Publisher of the VM image. | string |
"Canonical" |
no |
| vm_image_sku | SKU of the VM image. | string |
"22_04-lts-gen2" |
no |
| vm_image_version | Version of the VM image. | string |
"latest" |
no |
| vm_sku | SKU for VM size for the VMSS. | string |
"Standard_D2s_v5" |
no |
| vm_ssh_public_key | SSH public key for VMs in VMSS. | string |
null |
no |
| vmss_availability_zones | List of Azure Availability Zones to spread the VMSS VM resources across. | set(string) |
[ |
no |
| vmss_vm_count | Number of VM instances in the VMSS. | number |
1 |
no |
| vnet_id | VNet ID where boundary resources will reside. | string |
n/a | yes |
| worker_key_name | Name of the existing worker key in the Boundary Worker Key Vault. | string |
null |
no |
| worker_subnet_id | Subnet ID for worker VMs. | string |
n/a | yes |
| Name | Description |
|---|---|
| boundary_controller_cluster_lb_private_ip | Private IP address of the Boundary Cluster Load Balancer. |
| boundary_database_host | FQDN and port of PostgreSQL Flexible Server. |
| boundary_database_name | Name of PostgreSQL Flexible Server database. |
| created_boundary_controller_key_vault_name | Name of the created Boundary Controller Key Vault. |
| created_boundary_recovery_key_name | Name of the created Boundary Recovery Key. |
| created_boundary_root_key_name | Name of the created Boundary Root Key. |
| created_boundary_worker_key_name | Name of the created Boundary Worker Key. |
| created_boundary_worker_key_vault_name | Name of the created Boundary Worker Key Vault. |
| provided_boundary_controller_key_vault_name | Name of the provided Boundary Controller Key Vault. |
| provided_boundary_recovery_key_name | Name of the provided Boundary Recovery Key. |
| provided_boundary_root_key_name | Name of the provided Boundary Root Key. |
| provided_boundary_worker_key_name | Name of the provided Boundary Worker Key. |
| provided_boundary_worker_key_vault_name | Name of the provided Boundary Worker Key Vault. |
| resource_group_name | Name of the Resource Group. |
| url | URL of Boundary Controller based on boundary_fqdn input. |