Azure Networking Terraform Guide

Azure NAT Gateway Terraform

This page explains how to deploy Azure NAT Gateway with Terraform using Azure-specific outbound design patterns, including NAT gateway creation, public IP or public IP prefix attachment, subnet association, SNAT behavior, and production-ready outbound architecture for private workloads.

Instead of treating this as just a Terraform snippet page, this guide explains how the Terraform resources map to real Azure outbound connectivity design, what engineers usually get wrong with subnet egress, and how to structure reusable code for clean private-subnet internet access.

Main Terraform resources

The core resources are azurerm_nat_gateway, azurerm_nat_gateway_public_ip_association, azurerm_nat_gateway_public_ip_prefix_association, and azurerm_subnet_nat_gateway_association.

Best fit

Ideal when you want repeatable subnet-level outbound internet access without assigning a public IP to every workload.

Common challenge

Most mistakes come from forgetting subnet association, misunderstanding inbound vs outbound behavior, or not planning the public egress identity deliberately.

Primary resources NAT Gateway + associations Terraform models NAT Gateway and its public IP and subnet relationships explicitly.
Best for Private subnet egress Version-controlled outbound internet design for Azure workloads.
Key building blocks SNAT, subnet, public IP The subnet association is one of the most important parts of the design.
Related services Public IP, Firewall, Subnets NAT Gateway works as part of a broader Azure egress architecture.

What is Azure NAT Gateway Terraform?

Azure NAT Gateway Terraform means defining Azure’s managed outbound internet service as infrastructure as code instead of creating it manually in the portal. Because NAT Gateway works together with public IP resources and subnet associations, Terraform gives teams a clean way to make outbound internet design explicit, reusable, and reviewable.

In simple terms, Terraform lets you define how a private subnet reaches the internet, what public identity it uses, and how that outbound path is managed in Azure.
Infrastructure as Code Subnet-based egress Managed outbound design SNAT translation Public IP identity Repeatable environments

Why Terraform is used for Azure NAT Gateway

NAT Gateway is often simple in diagrams but easy to misconfigure operationally. Terraform helps engineering teams standardize outbound internet access, public IP usage, subnet association, and egress identity across multiple environments.

Consistency

The same outbound architecture can be deployed across development, test, and production without rebuilding subnet egress decisions by hand.

Reviewability

Engineers can review public egress identity, subnet associations, and NAT decisions in pull requests before deployment.

Cleaner private design

Terraform helps keep private workloads private while still giving them controlled outbound internet access.

Azure NAT Gateway Terraform explained with the 5 Ws + How

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

What

Terraform-based deployment of Azure NAT Gateway and its associations using AzureRM provider resources.

Why

To manage outbound internet access for private subnets in a repeatable, safe, and reviewable way.

When

Use it when private subnet workloads need outbound access without assigning public IPs directly to each workload.

Where

Inside Azure resource groups, associated to subnets, using public IP or public IP prefix resources for egress identity.

Who

DevOps engineers, platform teams, network engineers, cloud engineers, and architects designing subnet egress patterns.

How

Terraform creates the NAT Gateway, attaches public IP resources, and associates the NAT Gateway with the target subnet so Azure handles outbound SNAT for that subnet.

Prerequisites before writing the Terraform

NAT Gateway design starts with subnet architecture. A clean deployment needs more than just one Terraform resource. It needs clarity on which subnet should use managed outbound internet access, and why.

Common prerequisites

  • Azure subscription and Terraform AzureRM provider
  • Resource group
  • Virtual network and target subnet
  • Public IP or public IP prefix plan
  • Decision on egress ownership and environment naming
  • Clear distinction between outbound and inbound requirements

Production planning items

  • Whether the subnet needs only egress or also security inspection
  • Partner allow-listing requirements
  • Expected outbound scale and identity design
  • Whether a public IP prefix is better than one public IP
  • Which workloads in the subnet depend on outbound internet
  • Whether Azure Firewall is needed in addition to NAT Gateway
The biggest prerequisite is architectural intent. NAT Gateway is the right tool when the requirement is outbound internet access for a private subnet, not inbound application publishing.

Terraform resource model for Azure NAT Gateway

NAT Gateway Terraform is not just one resource. The actual deployment usually includes the NAT Gateway itself, a public IP or public IP prefix association, and the subnet association that makes the design work.

Terraform resource Azure concept Purpose
azurerm_nat_gateway NAT Gateway resource Creates the managed outbound internet service
azurerm_public_ip Public IP Defines the public egress identity
azurerm_public_ip_prefix Public IP prefix Defines a block of public addresses for larger-scale egress identity
azurerm_nat_gateway_public_ip_association NAT to public IP binding Attaches a public IP resource to the NAT Gateway
azurerm_nat_gateway_public_ip_prefix_association NAT to public IP prefix binding Attaches a public IP prefix to the NAT Gateway
azurerm_subnet_nat_gateway_association Subnet association Applies NAT Gateway behavior to the target subnet

Recommended code structure

For real projects, do not scatter NAT Gateway logic randomly across files. Even if the resource is small, subnet egress design affects security, outbound identity, and application dependencies, so structure matters.

terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── terraform.tfvars
└── modules/
    └── nat-gateway/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

Root module

Connects shared network resources, naming, environment-specific values, and target subnet selection.

Reusable child module

Encapsulates NAT Gateway, public IP association, and subnet association so multiple environments use consistent egress patterns.

Variables and outputs

Keep names, tags, IP strategy, and subnet identifiers separated from the core resource logic.

Terraform example for Azure NAT Gateway

This example shows a practical starter pattern for Azure NAT Gateway using Terraform. It uses Standard public IP, creates the NAT Gateway, associates the public IP, and then associates the NAT Gateway to the application subnet.

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

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 3.100.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-network-prod-san-1"
  location = "South Africa North"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "vnet-app-prod-san-1"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space       = ["10.40.0.0/16"]
}

resource "azurerm_subnet" "app_subnet" {
  name                 = "snet-app-prod-san-1"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.40.10.0/24"]
}

resource "azurerm_public_ip" "nat_ip" {
  name                = "pip-nat-prod-san-1"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  allocation_method = "Static"
  sku               = "Standard"

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

resource "azurerm_nat_gateway" "nat" {
  name                = "nat-prod-san-1"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  sku_name = "Standard"

  idle_timeout_in_minutes = 10

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

resource "azurerm_nat_gateway_public_ip_association" "nat_ip_assoc" {
  nat_gateway_id       = azurerm_nat_gateway.nat.id
  public_ip_address_id = azurerm_public_ip.nat_ip.id
}

resource "azurerm_subnet_nat_gateway_association" "subnet_assoc" {
  subnet_id      = azurerm_subnet.app_subnet.id
  nat_gateway_id = azurerm_nat_gateway.nat.id
}

output "nat_gateway_id" {
  value = azurerm_nat_gateway.nat.id
}

output "nat_public_ip" {
  value = azurerm_public_ip.nat_ip.ip_address
}

Public IP Prefix variation

In larger or more structured designs, some teams attach a public IP prefix instead of only one public IP.

resource "azurerm_public_ip_prefix" "nat_prefix" {
  name                = "pipfx-nat-prod-san-1"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  prefix_length       = 28
  sku                 = "Standard"
}

resource "azurerm_nat_gateway_public_ip_prefix_association" "nat_prefix_assoc" {
  nat_gateway_id      = azurerm_nat_gateway.nat.id
  public_ip_prefix_id = azurerm_public_ip_prefix.nat_prefix.id
}

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.

Public egress identity

azurerm_public_ip defines the public address that external destinations will see for outbound traffic from the subnet.

NAT Gateway service

azurerm_nat_gateway creates the managed Azure service that performs outbound source address translation.

Public IP attachment

azurerm_nat_gateway_public_ip_association binds the public IP to the NAT Gateway so the NAT service has an outbound internet identity.

Subnet behavior change

azurerm_subnet_nat_gateway_association is what makes the subnet actually use NAT Gateway for outbound internet access. Without this, the NAT Gateway resource exists but the subnet does not use it.

Idle timeout

idle_timeout_in_minutes affects how long inactive translated flows can remain before timeout considerations apply.

Outputs

Outputs expose the NAT Gateway ID and public IP so other modules, teams, and integration workflows can consume the deployed resources safely.

SNAT and outbound identity

SNAT is one of the highest-value concepts to understand for NAT Gateway. It explains how private workloads can access the internet without direct public IP assignment.

What SNAT means here

Source network address translation maps private source addresses and ports from the subnet into the NAT Gateway’s public outbound identity when connections leave Azure toward the internet.

Why this matters operationally

It gives teams a known public source address for partner allow-listing, outbound troubleshooting, and cleaner architecture compared with direct per-VM exposure.

If a partner asks which public IP your private Azure application will use to call their API, NAT Gateway is often the cleanest subnet-level answer.

Subnet association model

This is one of the most important NAT Gateway topics. NAT Gateway is a subnet-level outbound design, not a per-VM public exposure pattern.

Private Workloads
(VMs / App Tier / APIs)
          |
          v
+-------------------------------+
| Azure Subnet                  |
| Associated with NAT Gateway   |
+-------------------------------+
          |
          v
+-------------------------------+
| Azure NAT Gateway             |
| - SNAT translation            |
| - Public IP / Prefix          |
+-------------------------------+
          |
          v
+-------------------------------+
| Internet / External Services  |
+-------------------------------+

Why subnet association is powerful

It lets teams make outbound behavior a subnet architecture decision instead of a server-by-server patchwork of public IP settings.

Why engineers forget it

Some engineers create the NAT Gateway and public IP correctly but forget the subnet association, then wonder why outbound behavior never changes.

If you remember only one thing from this page, remember this: the subnet association is what turns NAT Gateway from a created resource into active outbound behavior for your workloads.

Real-world Azure NAT Gateway Terraform use cases

Practical examples make this page useful and avoid generic Terraform content by grounding the design in real Azure networking scenarios.

Private app servers calling external APIs

A private application subnet needs to call payment gateways, SaaS APIs, update services, or package repositories without assigning a public IP to every VM.

Partner allow-listed outbound identity

Terraform creates a known public egress path so external partners can allow-list the subnet’s outbound traffic by the NAT Gateway public IP.

Subnet standardization across environments

A platform team reuses the same NAT Gateway module across dev, test, and prod to keep outbound internet design consistent and reviewable.

Terraform vs manual Azure portal deployment

Both approaches can work, but Terraform becomes more valuable as subnet egress architecture grows and needs to stay 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 quick exploration Hard to reproduce accurately across environments
A strong engineering pattern is to understand the service once in the portal, then move the final design into Terraform so subnet egress 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 private workloads private

Use NAT Gateway when the need is outbound internet access, not direct public exposure of each workload.

Treat subnet egress as architecture

Do not reduce outbound internet design to a last-minute VM setting. Keep it deliberate at the subnet level.

Choose public identity intentionally

Decide whether a single public IP or a public IP prefix is the right fit for scale and allow-listing needs.

Tag resources clearly

Ownership, environment, and purpose should be obvious because NAT Gateway affects real application connectivity.

Use outputs cleanly

Expose NAT Gateway IDs and public identity so other modules and operations workflows can consume them safely.

Know when NAT is not enough

If the design needs filtering, policy enforcement, or inspection, evaluate Azure Firewall instead of assuming NAT Gateway is a security service.

Common mistakes

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

Forgetting subnet association

Engineers sometimes create NAT Gateway and public IP resources correctly but never attach the NAT Gateway to the subnet, so nothing changes operationally.

Using NAT for inbound thinking

NAT Gateway is not an inbound publishing service and should not be treated as a replacement for Application Gateway or public load balancer entry.

Directly assigning public IPs unnecessarily

Some teams expose workloads individually when the real requirement was only outbound internet access from a private subnet.

No egress identity planning

Partner integrations become harder when the outbound public identity is not selected intentionally from the start.

Skipping tags and ownership

Untagged NAT Gateway resources become harder to govern, support, and troubleshoot across larger Azure estates.

Assuming NAT equals firewall

NAT Gateway handles outbound connectivity, not full security policy and traffic inspection.

Frequently asked questions

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

What Terraform resource creates Azure NAT Gateway?

The main Terraform resource is azurerm_nat_gateway.

What resource attaches a public IP to Azure NAT Gateway?

Use azurerm_nat_gateway_public_ip_association. For a prefix, use azurerm_nat_gateway_public_ip_prefix_association.

What resource makes a subnet use Azure NAT Gateway?

Use azurerm_subnet_nat_gateway_association. This is one of the most important resources in the design.

Should I use NAT Gateway instead of assigning public IPs to each VM?

For outbound-only needs, NAT Gateway is usually the cleaner production design because it keeps workloads private while giving them managed internet egress.

Can Azure NAT Gateway be used for inbound internet access?

No. Azure NAT Gateway is for outbound connectivity. Return traffic that is part of an outbound flow can pass back, but internet inbound publishing is not its role.

Why is subnet association so important?

Without the subnet association, the NAT Gateway exists as a resource but the target subnet does not actually use it for outbound traffic.