Provisioning a NAT Gateway

Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

Provisioning a NAT Gateway

This guide shows you how to provision a NAT Gateway against Locally and attach it to a subnet. As with the other guides we're going to use the Azure CLI, but the same resources can be provisioned with HashiCorp Terraform, Pulumi or Bicep too.

Before you start

Plugin required

This requires the Microsoft.Network plugin, which you can install with:

$ locally plugin install --name Microsoft.Network

1. Start Locally

Firstly, we need to launch Locally which we can do from a terminal by running:

$ locally build

Once Locally has started, the Locally Dashboard will open automatically:

Screenshot of the Locally Dashboard

2. Create a Resource Group

Next we can create the Resource Group:

$ locally run az group create -n sample-nat -l berlin

There's two things to note here:

  1. The Azure CLI supports Automatic Configuration, meaning that it can automatically be configured to work against Locally just by prefixing commands with locally run.
  2. Locally intentionally uses a different set of locations to Azure as a safety precaution, so that you can be confident you're deploying against Locally rather than regular Azure. You can also configure Locally to use the Azure locations too, but you'll want to be extra sure that you're prefixing commands with locally run when you do.

3. Create a Public IP Address and the NAT Gateway

A NAT Gateway sends outbound traffic from a Standard Public IP Address, so we'll create one of those first:

$ locally run az network public-ip create -g sample-nat -n sample-nat-pip --sku Standard --allocation-method Static

Then the NAT Gateway itself, using that address and dropping idle connections after 10 minutes:

$ locally run az network nat gateway create -g sample-nat -n sample-natgw --public-ip-addresses sample-nat-pip --idle-timeout 10 --query "{name:name, sku:sku.name, idleTimeout:idleTimeoutInMinutes, state:provisioningState}"
{
  "idleTimeout": 10,
  "name": "sample-natgw",
  "sku": "Standard",
  "state": "Succeeded"
}

4. Attach it to a subnet

A NAT Gateway does nothing until a subnet uses it. We'll create a Virtual Network with a single subnet:

$ locally run az network vnet create -g sample-nat -n sample-vnet --address-prefixes 10.0.0.0/16 --subnet-name workloads --subnet-prefixes 10.0.1.0/24

Then point the subnet at the NAT Gateway:

$ locally run az network vnet subnet update -g sample-nat --vnet-name sample-vnet -n workloads --nat-gateway sample-natgw --query "{name:name, prefix:addressPrefix, natGateway:natGateway.id}"
{
  "name": "workloads",
  "natGateway": "/subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/natGateways/sample-natgw",
  "prefix": "10.0.1.0/24"
}

The Public IP Address now shows which NAT Gateway is using it, too:

$ locally run az network public-ip show -g sample-nat -n sample-nat-pip --query "{ip:ipAddress, natGateway:natGateway.id}"
{
  "ip": "127.1.0.4",
  "natGateway": "/subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/natGateways/sample-natgw"
}

Note

Locally records the NAT Gateway and its links to the subnet and Public IP Address, but doesn't route any traffic through it.

5. List the NAT Gateways

To see the NAT Gateways in the Resource Group:

$ locally run az network nat gateway list -g sample-nat --query "[].{Name:name, IdleTimeout:idleTimeoutInMinutes, State:provisioningState}" -o table
Name          IdleTimeout    State
------------  -------------  ---------
sample-natgw  10             Succeeded

We can see the NAT Gateway in the Locally Dashboard too:

Screenshot of the NAT Gateway in the Locally Dashboard

6. Tidy up

As in Azure, a NAT Gateway can't be deleted while a subnet is still using it:

$ locally run az network nat gateway delete -g sample-nat -n sample-natgw
ERROR: (InUseNatGatewayCannotBeDeleted) Resource /subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/natGateways/sample-natgw is in use by /subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/virtualNetworks/sample-vnet/subnets/workloads and cannot be deleted. In order to delete the resource, delete the resources referencing it first.
Code: InUseNatGatewayCannotBeDeleted
Message: Resource /subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/natGateways/sample-natgw is in use by /subscriptions/307d8f52-9719-460e-9f85-aa408e28ee55/resourceGroups/sample-nat/providers/Microsoft.Network/virtualNetworks/sample-vnet/subnets/workloads and cannot be deleted. In order to delete the resource, delete the resources referencing it first.

So we detach it from the subnet first:

$ locally run az network vnet subnet update -g sample-nat --vnet-name sample-vnet -n workloads --remove natGateway --query "{name:name, natGateway:natGateway.id}"
{
  "name": "workloads",
  "natGateway": null
}

After which the NAT Gateway can be deleted:

$ locally run az network nat gateway delete -g sample-nat -n sample-natgw

The same applies to the Public IP Address - it can't be deleted while the NAT Gateway is using it. Or to remove the Resource Group and everything within it in one go:

$ locally run az group delete -n sample-nat --yes

Doing this with other tooling

Whilst this guide used the Azure CLI, NAT Gateways work the same way through any of the tooling that Locally supports - a Microsoft.Network/natGateways resource in HashiCorp Terraform or OpenTofu, Pulumi, Bicep or an ARM Template all provision against Locally in the same way, with only the location changed.

Next steps

To control what traffic the subnet allows, add a Network Security Group. For inbound traffic, see Load Balancer.

Should you encounter any issues, please take a look at the troubleshooting section.

Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

A local cloud for you and your AI agents.

Your Azure infrastructure, running on your machine. Deploy in seconds, break things freely, and ship to Azure when you're ready.