What is this Azure VPN Gateway Terraform page?
This is a practical implementation page for engineers who want to create an Azure VPN Gateway using Terraform. It shows how the Azure building blocks fit together in a real site-to-site pattern instead of giving only a tiny sample with no surrounding explanation.
What you will deploy
- Resource group
- Virtual network
- GatewaySubnet
- Public IP for the gateway
- Azure virtual network gateway
- Local network gateway for the remote site
- Site-to-site VPN connection
Why it helps
- Good starting point for hybrid Azure networking
- Easy to expand later with BGP or active-active mode
- Useful for production IaC repositories
- Clearer than clicking resources manually in the portal
Why use Terraform for Azure VPN Gateway?
VPN connectivity is usually part of a larger network story. When gateway settings, remote prefixes, shared keys, and connection settings are scattered across manual steps, drift becomes easy. Terraform gives you repeatability, reviewability, and a cleaner way to keep Azure and network changes aligned.
Repeatable hybrid builds
Create the same gateway pattern in multiple environments without redoing every portal step by hand.
Better change control
Public IPs, local network gateway details, and tunnel settings are versioned like the rest of your infrastructure code.
Production-friendly workflow
Peer review and Terraform plans reduce surprises before changes reach a live gateway.
Azure VPN Gateway explained with the 5 Ws
What
Azure VPN Gateway is an Azure service that creates encrypted IPsec/IKE tunnels between Azure virtual networks and remote networks or clients.
Why
It allows workloads in Azure to talk securely with on-premises networks, partner environments, branches, or remote users without exposing private traffic openly.
When
Use it when you need secure connectivity but do not require a full dedicated private circuit like ExpressRoute, or when VPN acts as a practical hybrid option.
Where
The gateway lives inside an Azure VNet and requires a special subnet named GatewaySubnet. The remote side is represented by a local network gateway object in Azure.
Who
Cloud engineers, platform teams, network engineers, and infrastructure teams who manage Azure hybrid connectivity and secure branch-to-cloud patterns.
How
Azure creates a virtual network gateway in the VNet, the remote site is defined as a local network gateway, and a connection resource builds the encrypted tunnel between them.
Types and modes you should know before writing the code
One reason VPN Gateway pages become confusing is that many connection styles are described together. This page keeps them separate so the Terraform example stays readable.
Site-to-Site
Connects Azure to an office, branch, or data center through a VPN device or edge router. This is the pattern used in the Terraform code below.
Point-to-Site
Connects individual client devices to Azure. It is useful for remote access scenarios and follows a different Terraform shape than a branch tunnel.
VNet-to-VNet
Builds encrypted tunnels between VNets. In some designs, peering may be simpler, but VPN is still valid where encryption or topology requirements differ.
| Setting | What It Means | Why It Matters |
|---|---|---|
| RouteBased VPN | Uses routes in the IP forwarding table to decide where traffic goes. | Required for multi-site designs and widely used in modern Azure VPN deployments. |
| Active-Standby | One gateway instance is active while the other is standby. | Common starting point for simpler deployments. |
| Active-Active | Both gateway instances establish tunnels. | Used for high availability and higher throughput patterns. |
| BGP Enabled | Azure and the remote device exchange routes dynamically. | Important for more advanced hybrid routing and transit designs. |
Core Azure VPN Gateway components in Terraform
| Component | Azure Meaning | Terraform Resource |
|---|---|---|
| Virtual Network | The Azure network that will host workloads and the gateway subnet. | azurerm_virtual_network |
| GatewaySubnet | The dedicated subnet reserved for the Azure virtual network gateway. | azurerm_subnet |
| Public IP | The public endpoint used by the Azure gateway for tunnel establishment. | azurerm_public_ip |
| Virtual Network Gateway | The Azure VPN gateway instance inside the VNet. | azurerm_virtual_network_gateway |
| Local Network Gateway | Represents the remote VPN device public IP and the remote address prefixes. | azurerm_local_network_gateway |
| Connection | The IPsec/IKE tunnel relationship between Azure and the remote network. | azurerm_virtual_network_gateway_connection |
How Azure VPN Gateway works in practice
Think of the deployment as two sides learning to trust each other. Azure publishes one side of the tunnel, the remote device publishes the other, and the connection resource describes how the tunnel should be established.
- Create a VNet for Azure workloads.
- Create a dedicated GatewaySubnet inside that VNet.
- Allocate a public IP for the Azure VPN Gateway.
- Create the Azure virtual network gateway with gateway type Vpn and usually RouteBased VPN type.
- Create a local network gateway representing the remote site's public VPN IP and on-premises address ranges.
- Create the connection resource using a shared key for IPsec/IKE tunnel establishment.
- Once both sides match on policies and routing, encrypted traffic can move between Azure and the remote network.
Simple Azure VPN Gateway site-to-site diagram
This diagram is intentionally different from the Virtual WAN page. It follows the classic per-VNet Azure VPN Gateway model with a remote site on the other side.
On-Premises / Branch Office
+-----------------------------------+
| VPN Device / Edge Router |
| Public IP: 203.0.113.10 |
| Local Prefixes: 192.168.10.0/24 |
+----------------+------------------+
||
|| IPsec / IKE Site-to-Site VPN Tunnel
||
+---------------------++--------------------------------------------------+
| Azure Public Internet Edge |
+---------------------++--------------------------------------------------+
||
||
+----------------vv------------------+
| Azure Public IP |
| Attached to VPN Gateway |
+----------------+-------------------+
|
|
+----------------v-------------------+
| Azure Virtual Network Gateway |
| Type: VPN |
| VPN Type: RouteBased |
| SKU: VpnGw1 / AZ SKU as needed |
+----------------+-------------------+
|
+------v------+
| GatewaySubnet|
| 10.20.255.0/27
+------+- -----+
|
+----------------v-------------------+
| Azure VNet |
| 10.20.0.0/16 |
| Apps / Data / Private workloads |
+------------------------------------+
Azure VPN Gateway Terraform example
This example builds a clean site-to-site design: resource group, VNet, GatewaySubnet, public IP, VPN gateway, local network gateway, and the IPsec connection. It is intentionally production-shaped without becoming overcomplicated.
terraform {
required_version = ">= 1.5.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.100.0"
}
}
}
provider "azurerm" {
features {}
}
locals {
location = "South Africa North"
resource_group_name = "rg-cn-vpngw-san-1"
vnet_name = "vnet-cn-hybrid-san-1"
vnet_cidr = ["10.20.0.0/16"]
gateway_subnet_cidr = "10.20.255.0/27"
gateway_pip_name = "pip-cn-vpngw-san-1"
gateway_name = "vpngw-cn-san-1"
gateway_sku = "VpnGw1"
local_gateway_name = "lng-onprem-hq-1"
remote_gateway_ip = "203.0.113.10"
remote_prefixes = ["192.168.10.0/24", "192.168.20.0/24"]
connection_name = "conn-cn-azure-to-onprem-1"
shared_key = "ReplaceWithStrongSharedKey123!"
tags = {
environment = "lab"
workload = "networking"
owner = "cloudnetworking-io"
managed_by = "terraform"
}
}
resource "azurerm_resource_group" "this" {
name = local.resource_group_name
location = local.location
tags = local.tags
}
resource "azurerm_virtual_network" "this" {
name = local.vnet_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
address_space = local.vnet_cidr
tags = local.tags
}
resource "azurerm_subnet" "gateway" {
name = "GatewaySubnet"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [local.gateway_subnet_cidr]
}
resource "azurerm_public_ip" "gateway" {
name = local.gateway_pip_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
allocation_method = "Static"
sku = "Standard"
tags = local.tags
}
resource "azurerm_virtual_network_gateway" "this" {
name = local.gateway_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
type = "Vpn"
vpn_type = "RouteBased"
sku = local.gateway_sku
ip_configuration {
name = "vpngateway-ipconfig"
public_ip_address_id = azurerm_public_ip.gateway.id
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.gateway.id
}
enable_bgp = false
active_active = false
tags = local.tags
}
resource "azurerm_local_network_gateway" "onprem" {
name = local.local_gateway_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
gateway_address = local.remote_gateway_ip
address_space = local.remote_prefixes
tags = local.tags
}
resource "azurerm_virtual_network_gateway_connection" "s2s" {
name = local.connection_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
type = "IPsec"
virtual_network_gateway_id = azurerm_virtual_network_gateway.this.id
local_network_gateway_id = azurerm_local_network_gateway.onprem.id
shared_key = local.shared_key
tags = local.tags
}
output "resource_group_name" {
value = azurerm_resource_group.this.name
}
output "vpn_gateway_name" {
value = azurerm_virtual_network_gateway.this.name
}
output "local_network_gateway_name" {
value = azurerm_local_network_gateway.onprem.name
}
output "connection_name" {
value = azurerm_virtual_network_gateway_connection.s2s.name
}
output "gateway_public_ip_id" {
value = azurerm_public_ip.gateway.id
}
location = "South Africa North" resource_group_name = "rg-cn-vpngw-san-1" vnet_name = "vnet-cn-hybrid-san-1" gateway_name = "vpngw-cn-san-1" gateway_sku = "VpnGw1" remote_gateway_ip = "203.0.113.10" remote_prefixes = ["192.168.10.0/24", "192.168.20.0/24"]
terraform init terraform fmt terraform validate terraform plan -out tfplan terraform apply tfplan
What the Terraform code is doing
GatewaySubnet first
The gateway cannot be placed in a random subnet. Azure expects a dedicated subnet named GatewaySubnet, so the code creates that explicitly.
Public IP for tunnel establishment
The gateway needs a public-facing IP so the remote VPN device has something to connect to on the Azure side.
Local network gateway as the remote-side model
This object tells Azure what the remote VPN device public IP is and which on-premises prefixes sit behind it.
Connection resource binds both sides
The VPN connection joins the Azure virtual network gateway and the local network gateway using an IPsec shared key.
Real-world Azure VPN Gateway Terraform use cases
Classic VPN Gateway is still highly relevant because not every organization starts with Virtual WAN or ExpressRoute.
One office, one Azure environment
A company has a small head office and wants its servers or users to reach Azure-hosted applications privately over an encrypted tunnel.
Disaster recovery or migration bridge
During cloud migration, teams often use VPN Gateway to securely connect Azure workloads back to existing on-premises systems while applications move in phases.
Secure partner or remote site integration
A business may need to connect one trusted external site into Azure for selected services without exposing the traffic over open paths.
Azure VPN Gateway vs Virtual WAN vs ExpressRoute
The wrong comparison is often the reason teams overbuild or underbuild hybrid networking. This table gives the practical view.
| Option | Best For | Strengths | Trade-Offs |
|---|---|---|---|
| Azure VPN Gateway | Per-VNet secure connectivity to one or more remote sites | Simple hybrid starting point, IPsec/IKE encryption, familiar classic design | Less elegant than vWAN for large-scale transit architectures |
| Azure Virtual WAN | Centralized branch and multi-region transit at enterprise scale | Managed hubs, broad connectivity model, central routing and security potential | Requires broader design planning and may be too much for smaller estates |
| ExpressRoute | Dedicated private connectivity with stronger enterprise network characteristics | Predictable private connectivity model, common in larger regulated environments | Not the same cost or deployment model as VPN and may be unnecessary for smaller needs |
Azure VPN Gateway Terraform best practices
- Plan your address space carefully. Azure prefixes and remote prefixes must not overlap.
- Use a properly sized GatewaySubnet. Do not make it an afterthought, especially if the design may evolve.
- Prefer route-based designs for modern deployments. They fit better with multi-site and advanced routing scenarios.
- Keep shared keys out of plain code. Use secret management or sensitive pipeline variables in real environments.
- Choose the right gateway SKU. Capacity, features, and architecture goals should drive the SKU choice.
- Use active-active where justified. High-availability patterns and more demanding environments often benefit from it.
- Consider BGP early if routing will grow. Dynamic route exchange is often easier than managing many static prefixes later.
- Tag resources consistently. Ownership, cost, and environment tags make later operations easier.
Common mistakes engineers make with Azure VPN Gateway
1. Forgetting the exact GatewaySubnet name
Azure expects the subnet to be named GatewaySubnet. Using another name leads to avoidable deployment trouble.
2. Using overlapping address ranges
If Azure and on-premises use the same or overlapping prefixes, routing becomes confusing or completely breaks.
3. Putting real shared keys directly into public repositories
It works for a quick example, but not for production. Shared secrets should be handled like credentials.
4. Choosing the wrong design for the scale
Some teams use classic VPN Gateway for a network that is already growing into a hub-and-spoke transit problem where Virtual WAN would be cleaner.
5. Ignoring BGP and high availability until later
If the environment is already evolving, leaving BGP and active-active considerations too late can make redesign harder.
Frequently asked questions about Azure VPN Gateway Terraform
What is the difference between a virtual network gateway and a local network gateway?
The virtual network gateway is the Azure-side gateway inside your VNet. The local network gateway represents the remote site details, such as its public IP and internal prefixes.
Does Azure VPN Gateway support BGP?
Yes. Azure supports BGP with VPN Gateway, and it is useful for exchanging routes dynamically with supported remote devices.
Can Azure VPN Gateway run in active-active mode?
Yes. Azure supports both active-standby and active-active gateway configurations, with active-active commonly used in high-availability designs.
Is route-based VPN important?
Yes for many designs. Multi-site patterns especially rely on route-based VPN rather than older policy-based assumptions.
Should I use VPN Gateway or Virtual WAN?
Use classic VPN Gateway for simpler per-VNet hybrid needs. Use Virtual WAN when you want managed transit, broader branch connectivity, and a more centralized WAN design.