Azure Networking Terraform Guide

Azure Bastion Terraform

This page explains how to deploy Azure Bastion with Terraform using Azure-specific secure administration patterns, including Bastion host creation, the required AzureBastionSubnet, public IP, Standard SKU, and feature settings used for secure private VM access. Microsoft’s current Terraform quickstart for Bastion uses exactly that core pattern. :contentReference[oaicite:1]{index=1}

Instead of treating this as only a short code page, this guide explains how azurerm_bastion_host maps to Azure’s secure RDP and SSH access design, what engineers usually get wrong, and how to structure reusable infrastructure as code for Bastion in real environments. Microsoft’s Bastion overview and provider docs support this current resource model. :contentReference[oaicite:2]{index=2}

Main Terraform resource

The core resource is azurerm_bastion_host, which is deployed together with a virtual network, the dedicated AzureBastionSubnet, and a public IP in the standard quickstart model. :contentReference[oaicite:3]{index=3}

Best fit

Ideal when you want repeatable secure VM administration without giving target VMs public IPs or opening direct inbound RDP and SSH exposure. :contentReference[oaicite:4]{index=4}

Common challenge

Most mistakes come from wrong subnet setup, missing Bastion subnet requirements, misunderstanding supported feature flags, or confusing Bastion with broader VPN-style connectivity. :contentReference[oaicite:5]{index=5}

Primary resource azurerm_bastion_host Main Terraform resource for Bastion deployment.
Best for Secure private VM administration Version-controlled RDP and SSH access design for Azure VMs.
Key building blocks Bastion host, subnet, public IP The dedicated Bastion subnet is one of the most important requirements.
Related services Public IP, VNet, NSG Bastion works as part of a broader Azure administration-access architecture.

What is Azure Bastion Terraform?

Azure Bastion Terraform means defining Azure’s managed secure VM administration service as infrastructure as code instead of building it manually in the portal. The main resource is azurerm_bastion_host, and Microsoft’s current Bastion Terraform quickstart shows it being deployed with a resource group, virtual network, dedicated Bastion subnet, and public IP. :contentReference[oaicite:6]{index=6}

In simple terms, Terraform lets you define how administrators securely reach private Azure VMs, while keeping the Bastion deployment reusable, reviewable, and consistent across environments.
Infrastructure as Code Secure RDP/SSH design Private VM access Managed Azure service Repeatable environments Production-ready patterns

Why Terraform is used for Azure Bastion

Bastion may look straightforward in the portal, but it is still a security-sensitive architecture component. Terraform helps engineering teams standardize secure VM access, enforce the dedicated subnet model, keep naming and tagging clean, and reuse the same administration-access pattern across development, test, and production environments. Microsoft’s quickstart and resource model make this repeatable approach a good fit for infrastructure as code. :contentReference[oaicite:7]{index=7}

Consistency

The same Bastion architecture can be deployed across multiple environments without rebuilding secure access decisions by hand.

Reviewability

Engineers can review subnet placement, public IP usage, and Bastion feature settings through pull requests before deployment.

Safer operations

Terraform reduces drift and makes it easier to keep administration access aligned with your broader Azure security design.

Azure Bastion Terraform explained with the 5 Ws + How

This keeps the page useful for beginners, working engineers, and interview learners who want practical Azure networking and operations understanding.

What

Terraform-based deployment of Azure Bastion using the AzureRM provider.

Why

To manage secure RDP and SSH access to private VMs in a repeatable and reviewable way.

When

Use it when Azure VMs should remain private but administrators still need secure remote access.

Where

Inside Azure resource groups and VNets, using the dedicated AzureBastionSubnet and a Bastion host resource. :contentReference[oaicite:8]{index=8}

Who

DevOps engineers, platform teams, cloud engineers, operations teams, and architects managing secure Azure VM access.

How

Terraform declares the Bastion host, required networking components, and optional feature settings, and Azure builds the secure VM access layer accordingly. :contentReference[oaicite:9]{index=9}

Prerequisites before writing the Terraform

Bastion design starts with administration-access architecture. A clean Terraform deployment needs more than just the Bastion resource. It needs the right virtual network layout, the correct Bastion subnet, and a clear decision that Bastion is the right operational access pattern for the environment.

Common prerequisites

  • Azure subscription and Terraform AzureRM provider
  • Resource group
  • Virtual network
  • Dedicated AzureBastionSubnet
  • Public IP for the standard Bastion deployment model
  • Clear target VM administration requirements

Production planning items

  • Which Bastion SKU the environment needs
  • Whether features like tunneling or copy/paste should be enabled
  • Whether native client workflows matter for operations
  • Whether private-only Bastion should be evaluated separately
  • How Bastion fits into hub-and-spoke or peered VNet design
  • How administrators will authenticate and operate through Bastion
The biggest prerequisite is architectural intent. Bastion is the right answer when the requirement is secure VM administration, not when the requirement is application publishing or full user-to-network private connectivity.

Terraform resource model for Azure Bastion

Bastion Terraform is centered on the Bastion host resource, but the working deployment also depends on the VNet, required Bastion subnet, and public IP in the standard quickstart pattern. The current AzureRM resource model also supports optional feature flags such as copy/paste, file copy, shareable link, and tunneling. :contentReference[oaicite:10]{index=10}

Terraform resource or block Azure concept Purpose
azurerm_bastion_host Bastion host Creates the managed Bastion service for secure VM administration
azurerm_virtual_network Virtual network Provides the network where Bastion is deployed
azurerm_subnet AzureBastionSubnet Provides the dedicated subnet Bastion requires
azurerm_public_ip Bastion public IP Provides the Bastion endpoint for the standard deployment model
ip_configuration Bastion IP configuration Binds the Bastion host to the required subnet and public IP
tunneling_enabled Native client tunneling support Enables supported native client and tunneling workflows
copy_paste_enabled Clipboard behavior Controls clipboard-related feature behavior for sessions
file_copy_enabled File transfer support Controls file copy capability in supported scenarios

Recommended code structure

For real projects, do not scatter Bastion logic randomly through files. Bastion affects security, operations, and remote access design, so even a relatively small deployment benefits from clean module structure.

terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── terraform.tfvars
└── modules/
    └── bastion/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

Root module

Connects shared network resources, environment naming, and the VNet or hub architecture that Bastion belongs to.

Reusable child module

Encapsulates the Bastion host, required subnet, public IP, and selected feature flags so multiple environments stay consistent.

Variables and outputs

Keep names, tags, SKU, feature settings, and network identifiers separated from the core resource logic.

Terraform example for Azure Bastion

This example follows the current Azure Bastion Terraform quickstart model: resource group, VNet, required AzureBastionSubnet, Standard public IP, and Bastion host. It also shows a few commonly used feature flags supported by the current resource model. :contentReference[oaicite:11]{index=11}

Terraform starter example
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 4.0.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "random_pet" "name" {
  length = 2
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-bastion-${random_pet.name.id}"
  location = "South Africa North"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "vnet-bastion-${random_pet.name.id}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space       = ["10.50.0.0/16"]
}

resource "azurerm_subnet" "bastion_subnet" {
  name                 = "AzureBastionSubnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.50.1.0/26"]
}

resource "azurerm_public_ip" "bastion_pip" {
  name                = "pip-bastion-${random_pet.name.id}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  allocation_method = "Static"
  sku               = "Standard"

  tags = {
    environment = "prod"
    service     = "bastion"
    owner       = "platform-team"
  }
}

resource "azurerm_bastion_host" "bastion" {
  name                = "bas-${random_pet.name.id}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "Standard"

  copy_paste_enabled     = true
  file_copy_enabled      = true
  tunneling_enabled      = true
  shareable_link_enabled = false

  ip_configuration {
    name                 = "bastion-ip-config"
    subnet_id            = azurerm_subnet.bastion_subnet.id
    public_ip_address_id = azurerm_public_ip.bastion_pip.id
  }

  tags = {
    environment = "prod"
    service     = "bastion"
    owner       = "platform-team"
  }
}

output "bastion_host_id" {
  value = azurerm_bastion_host.bastion.id
}

output "bastion_public_ip" {
  value = azurerm_public_ip.bastion_pip.ip_address
}

Basic variation

If you want a simpler Bastion configuration, reduce the feature flags and change the SKU deliberately after validating which capabilities your environment actually needs. Azure’s current quickstart still defaults to Standard in the Terraform example. :contentReference[oaicite:12]{index=12}

How the Terraform code maps to the real Azure service

Many engineers can paste Terraform, but not everyone understands how each resource changes Azure behavior. This section makes the mapping clear.

Virtual network placement

azurerm_virtual_network defines where the Bastion service lives and where it will provide secure administration access to private VMs.

Dedicated Bastion subnet

azurerm_subnet named AzureBastionSubnet is a core requirement in the standard Bastion deployment model. Bastion is not placed into an arbitrary application subnet. :contentReference[oaicite:13]{index=13}

Bastion public endpoint

azurerm_public_ip provides the public endpoint for the Bastion host in the standard deployment design used by the current Terraform quickstart. :contentReference[oaicite:14]{index=14}

Bastion host resource

azurerm_bastion_host creates the managed Azure service that administrators use for secure RDP and SSH access to private VMs.

Feature flags

Resource settings such as tunneling_enabled, copy_paste_enabled, and file_copy_enabled control which supported Bastion features are enabled for the deployment. :contentReference[oaicite:15]{index=15}

Outputs

Outputs expose the Bastion host ID and Bastion public IP so other modules and operations workflows can consume the deployed resources cleanly.

Feature flags and options

One of the reasons Bastion Terraform is more than a one-line resource is that feature settings affect how operations teams actually use the service. The current Bastion resource model includes settings for copy/paste, file copy, tunneling, and shareable link support. :contentReference[oaicite:16]{index=16}

Tunneling

Tunneling is the key setting commonly associated with enabling native client workflows in Bastion. Microsoft’s support answer specifically points to tunneling_enabled = true for native client support in Terraform. :contentReference[oaicite:17]{index=17}

Copy and file options

Clipboard and file transfer related settings should be enabled deliberately based on operational needs and security expectations, not by habit.

Bastion feature flags are not just convenience options. They directly shape the user experience and operational workflow of VM administration in Azure.

AzureBastionSubnet model

This is one of the most important Bastion topics. Bastion is not deployed into your regular application subnet. It uses the dedicated AzureBastionSubnet in the standard architecture model described by Microsoft’s Terraform and Bastion configuration guidance. :contentReference[oaicite:18]{index=18}

Administrator
      |
      v
+-----------------------------------+
| Azure Bastion Host                |
| Public endpoint + managed service |
+-----------------------------------+
                 |
                 v
+-----------------------------------+
| AzureBastionSubnet                |
| Dedicated Bastion subnet          |
+-----------------------------------+
                 |
                 v
+-----------------------------------+
| Private Azure VNet                |
| Target VMs on private IP space    |
+-----------------------------------+

Why the dedicated subnet matters

It keeps the Bastion architecture structured and separate from normal application workloads, which is important for both clarity and supportability.

Why engineers get this wrong

Some teams assume Bastion can just live in any subnet, but the standard Azure Bastion deployment model explicitly expects the dedicated Bastion subnet.

If you remember only one Bastion Terraform requirement, remember this: the dedicated AzureBastionSubnet is a first-class design requirement, not an optional naming preference.

Real-world Azure Bastion Terraform use cases

Practical examples make this page useful and avoid generic Terraform content by grounding Bastion in real Azure administration scenarios.

Private production VM administration

A platform team uses Terraform to deploy Bastion so operations can securely reach production VMs without putting public IPs on those VMs.

Hub-and-spoke administration access

A central Bastion deployment in a shared operations VNet supports private administration across a broader Azure network architecture where peering is part of the design.

Replacing jump hosts

A security-conscious team standardizes Bastion in Terraform to eliminate self-managed jump boxes and keep administration access patterns consistent across environments.

Terraform vs manual Azure portal deployment

Both approaches can work, but Terraform becomes more valuable as secure administration architecture grows and must remain consistent across environments.

Approach Best for Strength Weakness
Terraform Repeatable production deployments Version control, consistency, reviewable changes Requires structure and code discipline
Azure Portal One-off testing or learning Fast for initial exploration Hard to reproduce accurately across environments
A strong engineering pattern is to understand Bastion once in the portal, then move the final design into Terraform so the VM administration access architecture is managed as code.

Best practices

Practical guidance is what turns a Terraform page from a snippet page into a real engineering reference.

Keep target VMs private

Use Bastion when the goal is secure administration without direct public IP exposure on the target VMs.

Choose SKU deliberately

Pick the Bastion tier based on real operational needs, especially if native client workflows or broader production capabilities matter.

Treat AzureBastionSubnet as required architecture

Do not treat the Bastion subnet as a casual implementation detail. It is a core part of the design.

Enable feature flags intentionally

Only enable tunneling, file copy, or related features if they fit your operational and security model.

Tag resources clearly

Bastion affects security and operations, so ownership, environment, and purpose should always be obvious.

Keep Bastion separate from application ingress thinking

Bastion is for VM administration, not application delivery, WAF, or public frontend design.

Common mistakes

Platform-specific mistakes are what make this page practical instead of generic. These are the things teams commonly get wrong with Bastion Terraform.

Using the wrong subnet pattern

Some engineers try to place Bastion into a normal application subnet instead of the dedicated Bastion subnet.

Confusing Bastion with broader VPN connectivity

Bastion is focused on VM administration, not general user-to-network private access across all scenarios.

Enabling features blindly

Teams sometimes enable all feature flags without checking whether those workflows fit the organization’s security expectations.

Keeping public IPs on target VMs anyway

This can weaken the whole point of using Bastion as the secure administration access layer.

Weak naming and tagging

Bastion is security-sensitive infrastructure, so unclear names and missing tags make support and governance harder.

Treating Bastion like a one-off manual setup

In larger environments, Bastion design should be standardized and reusable, not recreated differently each time.

Frequently asked questions

FAQ sections help capture real search intent and make the page more complete for working engineers and learners.

What Terraform resource creates Azure Bastion?

The main Terraform resource is azurerm_bastion_host. :contentReference[oaicite:19]{index=19}

What subnet is required for Azure Bastion in Terraform?

The standard Bastion deployment model uses the dedicated AzureBastionSubnet. :contentReference[oaicite:20]{index=20}

Does the standard Terraform Bastion quickstart use Standard SKU?

Yes. Microsoft’s current Terraform quickstart for Bastion deploys Bastion with the Standard SKU. :contentReference[oaicite:21]{index=21}

How do I enable native client support in Terraform?

Microsoft’s support guidance points to tunneling_enabled = true for native client support in Terraform. :contentReference[oaicite:22]{index=22}

Do target VMs need public IPs when using Bastion?

No. Microsoft’s Bastion overview says Bastion supports secure access to VMs using private IP addresses, without requiring a public IP on the VM. :contentReference[oaicite:23]{index=23}

Can I use file copy and clipboard features with Bastion in Terraform?

The current Bastion resource model includes feature flags such as file_copy_enabled and copy_paste_enabled, subject to supported tier and workflow behavior. :contentReference[oaicite:24]{index=24}