Configure GCP HA VPN Gateways

The gcp:compute/haVpnGateway:HaVpnGateway resource, part of the Pulumi GCP provider, provisions a Google-managed HA VPN gateway that terminates VPN tunnels with automatic failover. This guide focuses on three capabilities: basic gateway creation, dual-stack IPv4/IPv6 support, and encrypted Cloud Interconnect integration.

HA VPN gateways attach to VPC networks and provide higher availability than classic Target VPN Gateways through redundant interfaces. The examples are intentionally small. Combine them with VPN tunnel resources, peer gateway configuration, and BGP routing for complete connectivity.

Create a basic HA VPN gateway

Most VPN deployments start with a gateway attached to a VPC network, providing automatic failover through redundant interfaces.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const network1 = new gcp.compute.Network("network1", {
    name: "network1",
    autoCreateSubnetworks: false,
});
const haGateway1 = new gcp.compute.HaVpnGateway("ha_gateway1", {
    region: "us-central1",
    name: "ha-vpn-1",
    network: network1.id,
});
import pulumi
import pulumi_gcp as gcp

network1 = gcp.compute.Network("network1",
    name="network1",
    auto_create_subnetworks=False)
ha_gateway1 = gcp.compute.HaVpnGateway("ha_gateway1",
    region="us-central1",
    name="ha-vpn-1",
    network=network1.id)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network1, err := compute.NewNetwork(ctx, "network1", &compute.NetworkArgs{
			Name:                  pulumi.String("network1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewHaVpnGateway(ctx, "ha_gateway1", &compute.HaVpnGatewayArgs{
			Region:  pulumi.String("us-central1"),
			Name:    pulumi.String("ha-vpn-1"),
			Network: network1.ID(),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var network1 = new Gcp.Compute.Network("network1", new()
    {
        Name = "network1",
        AutoCreateSubnetworks = false,
    });

    var haGateway1 = new Gcp.Compute.HaVpnGateway("ha_gateway1", new()
    {
        Region = "us-central1",
        Name = "ha-vpn-1",
        Network = network1.Id,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.HaVpnGateway;
import com.pulumi.gcp.compute.HaVpnGatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var network1 = new Network("network1", NetworkArgs.builder()
            .name("network1")
            .autoCreateSubnetworks(false)
            .build());

        var haGateway1 = new HaVpnGateway("haGateway1", HaVpnGatewayArgs.builder()
            .region("us-central1")
            .name("ha-vpn-1")
            .network(network1.id())
            .build());

    }
}
resources:
  haGateway1:
    type: gcp:compute:HaVpnGateway
    name: ha_gateway1
    properties:
      region: us-central1
      name: ha-vpn-1
      network: ${network1.id}
  network1:
    type: gcp:compute:Network
    properties:
      name: network1
      autoCreateSubnetworks: false

The gateway sits in a specific region and attaches to your VPC network. The network property references the VPC where VPN traffic will flow. Google manages the gateway infrastructure; you configure tunnels separately to establish actual connectivity.

Enable dual-stack IPv4 and IPv6 support

Networks supporting both IPv4 and IPv6 clients configure the gateway’s stack type to handle both IP families.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const network1 = new gcp.compute.Network("network1", {
    name: "network1",
    autoCreateSubnetworks: false,
});
const haGateway1 = new gcp.compute.HaVpnGateway("ha_gateway1", {
    region: "us-central1",
    name: "ha-vpn-1",
    network: network1.id,
    stackType: "IPV4_IPV6",
    labels: {
        mykey: "myvalue",
    },
});
import pulumi
import pulumi_gcp as gcp

network1 = gcp.compute.Network("network1",
    name="network1",
    auto_create_subnetworks=False)
ha_gateway1 = gcp.compute.HaVpnGateway("ha_gateway1",
    region="us-central1",
    name="ha-vpn-1",
    network=network1.id,
    stack_type="IPV4_IPV6",
    labels={
        "mykey": "myvalue",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network1, err := compute.NewNetwork(ctx, "network1", &compute.NetworkArgs{
			Name:                  pulumi.String("network1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewHaVpnGateway(ctx, "ha_gateway1", &compute.HaVpnGatewayArgs{
			Region:    pulumi.String("us-central1"),
			Name:      pulumi.String("ha-vpn-1"),
			Network:   network1.ID(),
			StackType: pulumi.String("IPV4_IPV6"),
			Labels: pulumi.StringMap{
				"mykey": pulumi.String("myvalue"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var network1 = new Gcp.Compute.Network("network1", new()
    {
        Name = "network1",
        AutoCreateSubnetworks = false,
    });

    var haGateway1 = new Gcp.Compute.HaVpnGateway("ha_gateway1", new()
    {
        Region = "us-central1",
        Name = "ha-vpn-1",
        Network = network1.Id,
        StackType = "IPV4_IPV6",
        Labels = 
        {
            { "mykey", "myvalue" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.HaVpnGateway;
import com.pulumi.gcp.compute.HaVpnGatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var network1 = new Network("network1", NetworkArgs.builder()
            .name("network1")
            .autoCreateSubnetworks(false)
            .build());

        var haGateway1 = new HaVpnGateway("haGateway1", HaVpnGatewayArgs.builder()
            .region("us-central1")
            .name("ha-vpn-1")
            .network(network1.id())
            .stackType("IPV4_IPV6")
            .labels(Map.of("mykey", "myvalue"))
            .build());

    }
}
resources:
  haGateway1:
    type: gcp:compute:HaVpnGateway
    name: ha_gateway1
    properties:
      region: us-central1
      name: ha-vpn-1
      network: ${network1.id}
      stackType: IPV4_IPV6
      labels:
        mykey: myvalue
  network1:
    type: gcp:compute:Network
    properties:
      name: network1
      autoCreateSubnetworks: false

The stackType property controls which IP protocols the gateway supports. Setting it to IPV4_IPV6 enables dual-stack operation, allowing the gateway to terminate both IPv4 and IPv6 VPN tunnels. The labels property adds metadata for organization and cost tracking.

Connect to Cloud Interconnect with IPsec encryption

Organizations using Cloud Interconnect can layer IPsec encryption over dedicated links by attaching the VPN gateway to Interconnect attachments.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const network = new gcp.compute.Network("network", {
    name: "test-network",
    autoCreateSubnetworks: false,
});
const address1 = new gcp.compute.Address("address1", {
    name: "test-address1",
    addressType: "INTERNAL",
    purpose: "IPSEC_INTERCONNECT",
    address: "192.168.1.0",
    prefixLength: 29,
    network: network.selfLink,
});
const router = new gcp.compute.Router("router", {
    name: "test-router",
    network: network.name,
    encryptedInterconnectRouter: true,
    bgp: {
        asn: 16550,
    },
});
const attachment1 = new gcp.compute.InterconnectAttachment("attachment1", {
    name: "test-interconnect-attachment1",
    edgeAvailabilityDomain: "AVAILABILITY_DOMAIN_1",
    type: "PARTNER",
    router: router.id,
    encryption: "IPSEC",
    ipsecInternalAddresses: [address1.selfLink],
});
const address2 = new gcp.compute.Address("address2", {
    name: "test-address2",
    addressType: "INTERNAL",
    purpose: "IPSEC_INTERCONNECT",
    address: "192.168.2.0",
    prefixLength: 29,
    network: network.selfLink,
});
const attachment2 = new gcp.compute.InterconnectAttachment("attachment2", {
    name: "test-interconnect-attachment2",
    edgeAvailabilityDomain: "AVAILABILITY_DOMAIN_2",
    type: "PARTNER",
    router: router.id,
    encryption: "IPSEC",
    ipsecInternalAddresses: [address2.selfLink],
});
const vpn_gateway = new gcp.compute.HaVpnGateway("vpn-gateway", {
    name: "test-ha-vpngw",
    network: network.id,
    vpnInterfaces: [
        {
            id: 0,
            interconnectAttachment: attachment1.selfLink,
        },
        {
            id: 1,
            interconnectAttachment: attachment2.selfLink,
        },
    ],
});
import pulumi
import pulumi_gcp as gcp

network = gcp.compute.Network("network",
    name="test-network",
    auto_create_subnetworks=False)
address1 = gcp.compute.Address("address1",
    name="test-address1",
    address_type="INTERNAL",
    purpose="IPSEC_INTERCONNECT",
    address="192.168.1.0",
    prefix_length=29,
    network=network.self_link)
router = gcp.compute.Router("router",
    name="test-router",
    network=network.name,
    encrypted_interconnect_router=True,
    bgp={
        "asn": 16550,
    })
attachment1 = gcp.compute.InterconnectAttachment("attachment1",
    name="test-interconnect-attachment1",
    edge_availability_domain="AVAILABILITY_DOMAIN_1",
    type="PARTNER",
    router=router.id,
    encryption="IPSEC",
    ipsec_internal_addresses=[address1.self_link])
address2 = gcp.compute.Address("address2",
    name="test-address2",
    address_type="INTERNAL",
    purpose="IPSEC_INTERCONNECT",
    address="192.168.2.0",
    prefix_length=29,
    network=network.self_link)
attachment2 = gcp.compute.InterconnectAttachment("attachment2",
    name="test-interconnect-attachment2",
    edge_availability_domain="AVAILABILITY_DOMAIN_2",
    type="PARTNER",
    router=router.id,
    encryption="IPSEC",
    ipsec_internal_addresses=[address2.self_link])
vpn_gateway = gcp.compute.HaVpnGateway("vpn-gateway",
    name="test-ha-vpngw",
    network=network.id,
    vpn_interfaces=[
        {
            "id": 0,
            "interconnect_attachment": attachment1.self_link,
        },
        {
            "id": 1,
            "interconnect_attachment": attachment2.self_link,
        },
    ])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network, err := compute.NewNetwork(ctx, "network", &compute.NetworkArgs{
			Name:                  pulumi.String("test-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		address1, err := compute.NewAddress(ctx, "address1", &compute.AddressArgs{
			Name:         pulumi.String("test-address1"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("IPSEC_INTERCONNECT"),
			Address:      pulumi.String("192.168.1.0"),
			PrefixLength: pulumi.Int(29),
			Network:      network.SelfLink,
		})
		if err != nil {
			return err
		}
		router, err := compute.NewRouter(ctx, "router", &compute.RouterArgs{
			Name:                        pulumi.String("test-router"),
			Network:                     network.Name,
			EncryptedInterconnectRouter: pulumi.Bool(true),
			Bgp: &compute.RouterBgpArgs{
				Asn: pulumi.Int(16550),
			},
		})
		if err != nil {
			return err
		}
		attachment1, err := compute.NewInterconnectAttachment(ctx, "attachment1", &compute.InterconnectAttachmentArgs{
			Name:                   pulumi.String("test-interconnect-attachment1"),
			EdgeAvailabilityDomain: pulumi.String("AVAILABILITY_DOMAIN_1"),
			Type:                   pulumi.String("PARTNER"),
			Router:                 router.ID(),
			Encryption:             pulumi.String("IPSEC"),
			IpsecInternalAddresses: pulumi.StringArray{
				address1.SelfLink,
			},
		})
		if err != nil {
			return err
		}
		address2, err := compute.NewAddress(ctx, "address2", &compute.AddressArgs{
			Name:         pulumi.String("test-address2"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("IPSEC_INTERCONNECT"),
			Address:      pulumi.String("192.168.2.0"),
			PrefixLength: pulumi.Int(29),
			Network:      network.SelfLink,
		})
		if err != nil {
			return err
		}
		attachment2, err := compute.NewInterconnectAttachment(ctx, "attachment2", &compute.InterconnectAttachmentArgs{
			Name:                   pulumi.String("test-interconnect-attachment2"),
			EdgeAvailabilityDomain: pulumi.String("AVAILABILITY_DOMAIN_2"),
			Type:                   pulumi.String("PARTNER"),
			Router:                 router.ID(),
			Encryption:             pulumi.String("IPSEC"),
			IpsecInternalAddresses: pulumi.StringArray{
				address2.SelfLink,
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewHaVpnGateway(ctx, "vpn-gateway", &compute.HaVpnGatewayArgs{
			Name:    pulumi.String("test-ha-vpngw"),
			Network: network.ID(),
			VpnInterfaces: compute.HaVpnGatewayVpnInterfaceArray{
				&compute.HaVpnGatewayVpnInterfaceArgs{
					Id:                     pulumi.Int(0),
					InterconnectAttachment: attachment1.SelfLink,
				},
				&compute.HaVpnGatewayVpnInterfaceArgs{
					Id:                     pulumi.Int(1),
					InterconnectAttachment: attachment2.SelfLink,
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var network = new Gcp.Compute.Network("network", new()
    {
        Name = "test-network",
        AutoCreateSubnetworks = false,
    });

    var address1 = new Gcp.Compute.Address("address1", new()
    {
        Name = "test-address1",
        AddressType = "INTERNAL",
        Purpose = "IPSEC_INTERCONNECT",
        IPAddress = "192.168.1.0",
        PrefixLength = 29,
        Network = network.SelfLink,
    });

    var router = new Gcp.Compute.Router("router", new()
    {
        Name = "test-router",
        Network = network.Name,
        EncryptedInterconnectRouter = true,
        Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
        {
            Asn = 16550,
        },
    });

    var attachment1 = new Gcp.Compute.InterconnectAttachment("attachment1", new()
    {
        Name = "test-interconnect-attachment1",
        EdgeAvailabilityDomain = "AVAILABILITY_DOMAIN_1",
        Type = "PARTNER",
        Router = router.Id,
        Encryption = "IPSEC",
        IpsecInternalAddresses = new[]
        {
            address1.SelfLink,
        },
    });

    var address2 = new Gcp.Compute.Address("address2", new()
    {
        Name = "test-address2",
        AddressType = "INTERNAL",
        Purpose = "IPSEC_INTERCONNECT",
        IPAddress = "192.168.2.0",
        PrefixLength = 29,
        Network = network.SelfLink,
    });

    var attachment2 = new Gcp.Compute.InterconnectAttachment("attachment2", new()
    {
        Name = "test-interconnect-attachment2",
        EdgeAvailabilityDomain = "AVAILABILITY_DOMAIN_2",
        Type = "PARTNER",
        Router = router.Id,
        Encryption = "IPSEC",
        IpsecInternalAddresses = new[]
        {
            address2.SelfLink,
        },
    });

    var vpn_gateway = new Gcp.Compute.HaVpnGateway("vpn-gateway", new()
    {
        Name = "test-ha-vpngw",
        Network = network.Id,
        VpnInterfaces = new[]
        {
            new Gcp.Compute.Inputs.HaVpnGatewayVpnInterfaceArgs
            {
                Id = 0,
                InterconnectAttachment = attachment1.SelfLink,
            },
            new Gcp.Compute.Inputs.HaVpnGatewayVpnInterfaceArgs
            {
                Id = 1,
                InterconnectAttachment = attachment2.SelfLink,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.Address;
import com.pulumi.gcp.compute.AddressArgs;
import com.pulumi.gcp.compute.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.InterconnectAttachment;
import com.pulumi.gcp.compute.InterconnectAttachmentArgs;
import com.pulumi.gcp.compute.HaVpnGateway;
import com.pulumi.gcp.compute.HaVpnGatewayArgs;
import com.pulumi.gcp.compute.inputs.HaVpnGatewayVpnInterfaceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var network = new Network("network", NetworkArgs.builder()
            .name("test-network")
            .autoCreateSubnetworks(false)
            .build());

        var address1 = new Address("address1", AddressArgs.builder()
            .name("test-address1")
            .addressType("INTERNAL")
            .purpose("IPSEC_INTERCONNECT")
            .address("192.168.1.0")
            .prefixLength(29)
            .network(network.selfLink())
            .build());

        var router = new Router("router", RouterArgs.builder()
            .name("test-router")
            .network(network.name())
            .encryptedInterconnectRouter(true)
            .bgp(RouterBgpArgs.builder()
                .asn(16550)
                .build())
            .build());

        var attachment1 = new InterconnectAttachment("attachment1", InterconnectAttachmentArgs.builder()
            .name("test-interconnect-attachment1")
            .edgeAvailabilityDomain("AVAILABILITY_DOMAIN_1")
            .type("PARTNER")
            .router(router.id())
            .encryption("IPSEC")
            .ipsecInternalAddresses(address1.selfLink())
            .build());

        var address2 = new Address("address2", AddressArgs.builder()
            .name("test-address2")
            .addressType("INTERNAL")
            .purpose("IPSEC_INTERCONNECT")
            .address("192.168.2.0")
            .prefixLength(29)
            .network(network.selfLink())
            .build());

        var attachment2 = new InterconnectAttachment("attachment2", InterconnectAttachmentArgs.builder()
            .name("test-interconnect-attachment2")
            .edgeAvailabilityDomain("AVAILABILITY_DOMAIN_2")
            .type("PARTNER")
            .router(router.id())
            .encryption("IPSEC")
            .ipsecInternalAddresses(address2.selfLink())
            .build());

        var vpn_gateway = new HaVpnGateway("vpn-gateway", HaVpnGatewayArgs.builder()
            .name("test-ha-vpngw")
            .network(network.id())
            .vpnInterfaces(            
                HaVpnGatewayVpnInterfaceArgs.builder()
                    .id(0)
                    .interconnectAttachment(attachment1.selfLink())
                    .build(),
                HaVpnGatewayVpnInterfaceArgs.builder()
                    .id(1)
                    .interconnectAttachment(attachment2.selfLink())
                    .build())
            .build());

    }
}
resources:
  vpn-gateway:
    type: gcp:compute:HaVpnGateway
    properties:
      name: test-ha-vpngw
      network: ${network.id}
      vpnInterfaces:
        - id: 0
          interconnectAttachment: ${attachment1.selfLink}
        - id: 1
          interconnectAttachment: ${attachment2.selfLink}
  attachment1:
    type: gcp:compute:InterconnectAttachment
    properties:
      name: test-interconnect-attachment1
      edgeAvailabilityDomain: AVAILABILITY_DOMAIN_1
      type: PARTNER
      router: ${router.id}
      encryption: IPSEC
      ipsecInternalAddresses:
        - ${address1.selfLink}
  attachment2:
    type: gcp:compute:InterconnectAttachment
    properties:
      name: test-interconnect-attachment2
      edgeAvailabilityDomain: AVAILABILITY_DOMAIN_2
      type: PARTNER
      router: ${router.id}
      encryption: IPSEC
      ipsecInternalAddresses:
        - ${address2.selfLink}
  address1:
    type: gcp:compute:Address
    properties:
      name: test-address1
      addressType: INTERNAL
      purpose: IPSEC_INTERCONNECT
      address: 192.168.1.0
      prefixLength: 29
      network: ${network.selfLink}
  address2:
    type: gcp:compute:Address
    properties:
      name: test-address2
      addressType: INTERNAL
      purpose: IPSEC_INTERCONNECT
      address: 192.168.2.0
      prefixLength: 29
      network: ${network.selfLink}
  router:
    type: gcp:compute:Router
    properties:
      name: test-router
      network: ${network.name}
      encryptedInterconnectRouter: true
      bgp:
        asn: 16550
  network:
    type: gcp:compute:Network
    properties:
      name: test-network
      autoCreateSubnetworks: false

The vpnInterfaces array maps gateway interfaces to Interconnect attachments, enabling IPsec encryption over dedicated connectivity. Each interface references an InterconnectAttachment configured with IPSEC encryption and internal IP addresses allocated for the IPSEC_INTERCONNECT purpose. The router must have encryptedInterconnectRouter enabled to support this configuration.

Beyond these examples

These snippets focus on specific HA VPN gateway features: basic gateway provisioning, dual-stack IPv4/IPv6 configuration, and encrypted Interconnect integration. They’re intentionally minimal rather than full VPN solutions.

The examples may reference pre-existing infrastructure such as VPC networks (examples create inline, but typically reference existing) and Cloud Interconnect partner connections for encrypted Interconnect scenarios. They focus on gateway configuration rather than complete VPN connectivity.

To keep things focused, common VPN patterns are omitted, including:

  • VPN tunnel configuration (separate resource)
  • Peer gateway setup and external VPN endpoints
  • BGP session configuration for dynamic routing
  • Custom gateway IP version settings (gatewayIpVersion)

These omissions are intentional: the goal is to illustrate how each gateway feature is wired, not provide drop-in VPN modules. See the HA VPN Gateway resource reference for all available configuration options.

Let's configure GCP HA VPN Gateways

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
What properties can't I change after creating an HA VPN Gateway?
Most properties are immutable: name, network, region, vpnInterfaces, description, params, gatewayIpVersion, and stackType. Changes to these require resource replacement.
What are the naming requirements for an HA VPN Gateway?
Names must be 1-63 characters, start with a lowercase letter, contain only lowercase letters, digits, and dashes, and cannot end with a dash. The pattern is [a-z][-a-z0-9]*[a-z0-9]?.
IP Protocol Support
What's the difference between stackType and gatewayIpVersion?
stackType identifies which IP protocols are enabled on the gateway (IPV4_ONLY, IPV4_IPV6, or IPV6_ONLY), defaulting to IPV4_ONLY. gatewayIpVersion specifies the IP family of the gateway IPs for interfaces (IPV4 or IPV6), defaulting to IPV4. Both are immutable.
How do I enable IPv6 support for my HA VPN Gateway?
Set stackType to IPV4_IPV6 when creating the gateway. You can also optionally set gatewayIpVersion to IPV6.
Advanced Features
Why aren't all labels showing in my Pulumi configuration?
The labels field is non-authoritative and only manages labels present in your configuration. Use effectiveLabels to see all labels on the resource in GCP, including those set by other clients and services.
How do I use HA VPN Gateway with encrypted interconnect attachments?
Configure vpnInterfaces with interconnectAttachment references pointing to IPSEC-encrypted interconnect attachments, as shown in the encrypted interconnect example.
Import & Management
What formats can I use to import an existing HA VPN Gateway?
You can import using any of these formats: projects/{{project}}/regions/{{region}}/vpnGateways/{{name}}, {{project}}/{{region}}/{{name}}, {{region}}/{{name}}, or just {{name}}.

Using a different cloud?

Explore networking guides for other cloud providers: