The aws:ec2/vpnConnection:VpnConnection resource, part of the Pulumi AWS provider, defines a Site-to-Site VPN connection that establishes IPsec tunnels between AWS and on-premises networks. This guide focuses on three capabilities: Transit Gateway attachment for hub-and-spoke topologies, Virtual Private Gateway attachment for single-VPC connectivity, and private VPN routing over Direct Connect.
VPN connections require Customer Gateways (representing on-premises endpoints) and either a Transit Gateway or Virtual Private Gateway on the AWS side. The examples are intentionally small. Combine them with your own gateway infrastructure and routing configuration.
Connect on-premises networks via Transit Gateway
Organizations building hub-and-spoke network topologies use Transit Gateway to centralize VPN connections, allowing multiple VPCs to share a single VPN connection to on-premises infrastructure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.ec2transitgateway.TransitGateway("example", {});
const exampleCustomerGateway = new aws.ec2.CustomerGateway("example", {
bgpAsn: "65000",
ipAddress: "172.0.0.1",
type: "ipsec.1",
});
const exampleVpnConnection = new aws.ec2.VpnConnection("example", {
customerGatewayId: exampleCustomerGateway.id,
transitGatewayId: example.id,
type: exampleCustomerGateway.type,
});
import pulumi
import pulumi_aws as aws
example = aws.ec2transitgateway.TransitGateway("example")
example_customer_gateway = aws.ec2.CustomerGateway("example",
bgp_asn="65000",
ip_address="172.0.0.1",
type="ipsec.1")
example_vpn_connection = aws.ec2.VpnConnection("example",
customer_gateway_id=example_customer_gateway.id,
transit_gateway_id=example.id,
type=example_customer_gateway.type)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2transitgateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := ec2transitgateway.NewTransitGateway(ctx, "example", nil)
if err != nil {
return err
}
exampleCustomerGateway, err := ec2.NewCustomerGateway(ctx, "example", &ec2.CustomerGatewayArgs{
BgpAsn: pulumi.String("65000"),
IpAddress: pulumi.String("172.0.0.1"),
Type: pulumi.String("ipsec.1"),
})
if err != nil {
return err
}
_, err = ec2.NewVpnConnection(ctx, "example", &ec2.VpnConnectionArgs{
CustomerGatewayId: exampleCustomerGateway.ID(),
TransitGatewayId: example.ID(),
Type: exampleCustomerGateway.Type,
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Ec2TransitGateway.TransitGateway("example");
var exampleCustomerGateway = new Aws.Ec2.CustomerGateway("example", new()
{
BgpAsn = "65000",
IpAddress = "172.0.0.1",
Type = "ipsec.1",
});
var exampleVpnConnection = new Aws.Ec2.VpnConnection("example", new()
{
CustomerGatewayId = exampleCustomerGateway.Id,
TransitGatewayId = example.Id,
Type = exampleCustomerGateway.Type,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2transitgateway.TransitGateway;
import com.pulumi.aws.ec2.CustomerGateway;
import com.pulumi.aws.ec2.CustomerGatewayArgs;
import com.pulumi.aws.ec2.VpnConnection;
import com.pulumi.aws.ec2.VpnConnectionArgs;
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 example = new TransitGateway("example");
var exampleCustomerGateway = new CustomerGateway("exampleCustomerGateway", CustomerGatewayArgs.builder()
.bgpAsn("65000")
.ipAddress("172.0.0.1")
.type("ipsec.1")
.build());
var exampleVpnConnection = new VpnConnection("exampleVpnConnection", VpnConnectionArgs.builder()
.customerGatewayId(exampleCustomerGateway.id())
.transitGatewayId(example.id())
.type(exampleCustomerGateway.type())
.build());
}
}
resources:
example:
type: aws:ec2transitgateway:TransitGateway
exampleCustomerGateway:
type: aws:ec2:CustomerGateway
name: example
properties:
bgpAsn: 65000
ipAddress: 172.0.0.1
type: ipsec.1
exampleVpnConnection:
type: aws:ec2:VpnConnection
name: example
properties:
customerGatewayId: ${exampleCustomerGateway.id}
transitGatewayId: ${example.id}
type: ${exampleCustomerGateway.type}
The connection establishes two IPsec tunnels between your Customer Gateway and the Transit Gateway. The customerGatewayId identifies your on-premises endpoint, while transitGatewayId specifies the AWS hub. The type property must be “ipsec.1”, the only VPN type AWS currently supports.
Connect a single VPC with static routing
Teams connecting a single VPC to on-premises networks often use Virtual Private Gateway with static routes when their customer gateway device doesn’t support BGP.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const vpc = new aws.ec2.Vpc("vpc", {cidrBlock: "10.0.0.0/16"});
const vpnGateway = new aws.ec2.VpnGateway("vpn_gateway", {vpcId: vpc.id});
const customerGateway = new aws.ec2.CustomerGateway("customer_gateway", {
bgpAsn: "65000",
ipAddress: "172.0.0.1",
type: "ipsec.1",
});
const main = new aws.ec2.VpnConnection("main", {
vpnGatewayId: vpnGateway.id,
customerGatewayId: customerGateway.id,
type: "ipsec.1",
staticRoutesOnly: true,
});
import pulumi
import pulumi_aws as aws
vpc = aws.ec2.Vpc("vpc", cidr_block="10.0.0.0/16")
vpn_gateway = aws.ec2.VpnGateway("vpn_gateway", vpc_id=vpc.id)
customer_gateway = aws.ec2.CustomerGateway("customer_gateway",
bgp_asn="65000",
ip_address="172.0.0.1",
type="ipsec.1")
main = aws.ec2.VpnConnection("main",
vpn_gateway_id=vpn_gateway.id,
customer_gateway_id=customer_gateway.id,
type="ipsec.1",
static_routes_only=True)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
vpc, err := ec2.NewVpc(ctx, "vpc", &ec2.VpcArgs{
CidrBlock: pulumi.String("10.0.0.0/16"),
})
if err != nil {
return err
}
vpnGateway, err := ec2.NewVpnGateway(ctx, "vpn_gateway", &ec2.VpnGatewayArgs{
VpcId: vpc.ID(),
})
if err != nil {
return err
}
customerGateway, err := ec2.NewCustomerGateway(ctx, "customer_gateway", &ec2.CustomerGatewayArgs{
BgpAsn: pulumi.String("65000"),
IpAddress: pulumi.String("172.0.0.1"),
Type: pulumi.String("ipsec.1"),
})
if err != nil {
return err
}
_, err = ec2.NewVpnConnection(ctx, "main", &ec2.VpnConnectionArgs{
VpnGatewayId: vpnGateway.ID(),
CustomerGatewayId: customerGateway.ID(),
Type: pulumi.String("ipsec.1"),
StaticRoutesOnly: pulumi.Bool(true),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var vpc = new Aws.Ec2.Vpc("vpc", new()
{
CidrBlock = "10.0.0.0/16",
});
var vpnGateway = new Aws.Ec2.VpnGateway("vpn_gateway", new()
{
VpcId = vpc.Id,
});
var customerGateway = new Aws.Ec2.CustomerGateway("customer_gateway", new()
{
BgpAsn = "65000",
IpAddress = "172.0.0.1",
Type = "ipsec.1",
});
var main = new Aws.Ec2.VpnConnection("main", new()
{
VpnGatewayId = vpnGateway.Id,
CustomerGatewayId = customerGateway.Id,
Type = "ipsec.1",
StaticRoutesOnly = true,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Vpc;
import com.pulumi.aws.ec2.VpcArgs;
import com.pulumi.aws.ec2.VpnGateway;
import com.pulumi.aws.ec2.VpnGatewayArgs;
import com.pulumi.aws.ec2.CustomerGateway;
import com.pulumi.aws.ec2.CustomerGatewayArgs;
import com.pulumi.aws.ec2.VpnConnection;
import com.pulumi.aws.ec2.VpnConnectionArgs;
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 vpc = new Vpc("vpc", VpcArgs.builder()
.cidrBlock("10.0.0.0/16")
.build());
var vpnGateway = new VpnGateway("vpnGateway", VpnGatewayArgs.builder()
.vpcId(vpc.id())
.build());
var customerGateway = new CustomerGateway("customerGateway", CustomerGatewayArgs.builder()
.bgpAsn("65000")
.ipAddress("172.0.0.1")
.type("ipsec.1")
.build());
var main = new VpnConnection("main", VpnConnectionArgs.builder()
.vpnGatewayId(vpnGateway.id())
.customerGatewayId(customerGateway.id())
.type("ipsec.1")
.staticRoutesOnly(true)
.build());
}
}
resources:
vpc:
type: aws:ec2:Vpc
properties:
cidrBlock: 10.0.0.0/16
vpnGateway:
type: aws:ec2:VpnGateway
name: vpn_gateway
properties:
vpcId: ${vpc.id}
customerGateway:
type: aws:ec2:CustomerGateway
name: customer_gateway
properties:
bgpAsn: 65000
ipAddress: 172.0.0.1
type: ipsec.1
main:
type: aws:ec2:VpnConnection
properties:
vpnGatewayId: ${vpnGateway.id}
customerGatewayId: ${customerGateway.id}
type: ipsec.1
staticRoutesOnly: true
The vpnGatewayId attaches the VPN connection to a specific VPC through its Virtual Private Gateway. Setting staticRoutesOnly to true disables BGP and requires you to define routes manually using companion VpnConnectionRoute resources.
Route VPN traffic over Direct Connect
Enterprises with Direct Connect can route VPN traffic over private connections instead of the public internet, improving security and reducing latency.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const exampleGateway = new aws.directconnect.Gateway("example", {
name: "example_ipsec_vpn_example",
amazonSideAsn: "64512",
});
const exampleTransitGateway = new aws.ec2transitgateway.TransitGateway("example", {
amazonSideAsn: 64513,
description: "example_ipsec_vpn_example",
transitGatewayCidrBlocks: ["10.0.0.0/24"],
});
const exampleCustomerGateway = new aws.ec2.CustomerGateway("example", {
bgpAsn: "64514",
ipAddress: "10.0.0.1",
type: "ipsec.1",
tags: {
Name: "example_ipsec_vpn_example",
},
});
const exampleGatewayAssociation = new aws.directconnect.GatewayAssociation("example", {
dxGatewayId: exampleGateway.id,
associatedGatewayId: exampleTransitGateway.id,
allowedPrefixes: ["10.0.0.0/8"],
});
const example = aws.ec2transitgateway.getDirectConnectGatewayAttachmentOutput({
transitGatewayId: exampleTransitGateway.id,
dxGatewayId: exampleGateway.id,
});
const exampleVpnConnection = new aws.ec2.VpnConnection("example", {
customerGatewayId: exampleCustomerGateway.id,
outsideIpAddressType: "PrivateIpv4",
transitGatewayId: exampleTransitGateway.id,
transportTransitGatewayAttachmentId: example.apply(example => example.id),
type: "ipsec.1",
tags: {
Name: "example_ipsec_vpn_example",
},
});
import pulumi
import pulumi_aws as aws
example_gateway = aws.directconnect.Gateway("example",
name="example_ipsec_vpn_example",
amazon_side_asn="64512")
example_transit_gateway = aws.ec2transitgateway.TransitGateway("example",
amazon_side_asn=64513,
description="example_ipsec_vpn_example",
transit_gateway_cidr_blocks=["10.0.0.0/24"])
example_customer_gateway = aws.ec2.CustomerGateway("example",
bgp_asn="64514",
ip_address="10.0.0.1",
type="ipsec.1",
tags={
"Name": "example_ipsec_vpn_example",
})
example_gateway_association = aws.directconnect.GatewayAssociation("example",
dx_gateway_id=example_gateway.id,
associated_gateway_id=example_transit_gateway.id,
allowed_prefixes=["10.0.0.0/8"])
example = aws.ec2transitgateway.get_direct_connect_gateway_attachment_output(transit_gateway_id=example_transit_gateway.id,
dx_gateway_id=example_gateway.id)
example_vpn_connection = aws.ec2.VpnConnection("example",
customer_gateway_id=example_customer_gateway.id,
outside_ip_address_type="PrivateIpv4",
transit_gateway_id=example_transit_gateway.id,
transport_transit_gateway_attachment_id=example.id,
type="ipsec.1",
tags={
"Name": "example_ipsec_vpn_example",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/directconnect"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2transitgateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
exampleGateway, err := directconnect.NewGateway(ctx, "example", &directconnect.GatewayArgs{
Name: pulumi.String("example_ipsec_vpn_example"),
AmazonSideAsn: pulumi.String("64512"),
})
if err != nil {
return err
}
exampleTransitGateway, err := ec2transitgateway.NewTransitGateway(ctx, "example", &ec2transitgateway.TransitGatewayArgs{
AmazonSideAsn: pulumi.Int(64513),
Description: pulumi.String("example_ipsec_vpn_example"),
TransitGatewayCidrBlocks: pulumi.StringArray{
pulumi.String("10.0.0.0/24"),
},
})
if err != nil {
return err
}
exampleCustomerGateway, err := ec2.NewCustomerGateway(ctx, "example", &ec2.CustomerGatewayArgs{
BgpAsn: pulumi.String("64514"),
IpAddress: pulumi.String("10.0.0.1"),
Type: pulumi.String("ipsec.1"),
Tags: pulumi.StringMap{
"Name": pulumi.String("example_ipsec_vpn_example"),
},
})
if err != nil {
return err
}
_, err = directconnect.NewGatewayAssociation(ctx, "example", &directconnect.GatewayAssociationArgs{
DxGatewayId: exampleGateway.ID(),
AssociatedGatewayId: exampleTransitGateway.ID(),
AllowedPrefixes: pulumi.StringArray{
pulumi.String("10.0.0.0/8"),
},
})
if err != nil {
return err
}
example := ec2transitgateway.GetDirectConnectGatewayAttachmentOutput(ctx, ec2transitgateway.GetDirectConnectGatewayAttachmentOutputArgs{
TransitGatewayId: exampleTransitGateway.ID(),
DxGatewayId: exampleGateway.ID(),
}, nil)
_, err = ec2.NewVpnConnection(ctx, "example", &ec2.VpnConnectionArgs{
CustomerGatewayId: exampleCustomerGateway.ID(),
OutsideIpAddressType: pulumi.String("PrivateIpv4"),
TransitGatewayId: exampleTransitGateway.ID(),
TransportTransitGatewayAttachmentId: pulumi.String(example.ApplyT(func(example ec2transitgateway.GetDirectConnectGatewayAttachmentResult) (*string, error) {
return &example.Id, nil
}).(pulumi.StringPtrOutput)),
Type: pulumi.String("ipsec.1"),
Tags: pulumi.StringMap{
"Name": pulumi.String("example_ipsec_vpn_example"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var exampleGateway = new Aws.DirectConnect.Gateway("example", new()
{
Name = "example_ipsec_vpn_example",
AmazonSideAsn = "64512",
});
var exampleTransitGateway = new Aws.Ec2TransitGateway.TransitGateway("example", new()
{
AmazonSideAsn = 64513,
Description = "example_ipsec_vpn_example",
TransitGatewayCidrBlocks = new[]
{
"10.0.0.0/24",
},
});
var exampleCustomerGateway = new Aws.Ec2.CustomerGateway("example", new()
{
BgpAsn = "64514",
IpAddress = "10.0.0.1",
Type = "ipsec.1",
Tags =
{
{ "Name", "example_ipsec_vpn_example" },
},
});
var exampleGatewayAssociation = new Aws.DirectConnect.GatewayAssociation("example", new()
{
DxGatewayId = exampleGateway.Id,
AssociatedGatewayId = exampleTransitGateway.Id,
AllowedPrefixes = new[]
{
"10.0.0.0/8",
},
});
var example = Aws.Ec2TransitGateway.GetDirectConnectGatewayAttachment.Invoke(new()
{
TransitGatewayId = exampleTransitGateway.Id,
DxGatewayId = exampleGateway.Id,
});
var exampleVpnConnection = new Aws.Ec2.VpnConnection("example", new()
{
CustomerGatewayId = exampleCustomerGateway.Id,
OutsideIpAddressType = "PrivateIpv4",
TransitGatewayId = exampleTransitGateway.Id,
TransportTransitGatewayAttachmentId = example.Apply(getDirectConnectGatewayAttachmentResult => getDirectConnectGatewayAttachmentResult.Id),
Type = "ipsec.1",
Tags =
{
{ "Name", "example_ipsec_vpn_example" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.directconnect.Gateway;
import com.pulumi.aws.directconnect.GatewayArgs;
import com.pulumi.aws.ec2transitgateway.TransitGateway;
import com.pulumi.aws.ec2transitgateway.TransitGatewayArgs;
import com.pulumi.aws.ec2.CustomerGateway;
import com.pulumi.aws.ec2.CustomerGatewayArgs;
import com.pulumi.aws.directconnect.GatewayAssociation;
import com.pulumi.aws.directconnect.GatewayAssociationArgs;
import com.pulumi.aws.ec2transitgateway.Ec2transitgatewayFunctions;
import com.pulumi.aws.ec2transitgateway.inputs.GetDirectConnectGatewayAttachmentArgs;
import com.pulumi.aws.ec2.VpnConnection;
import com.pulumi.aws.ec2.VpnConnectionArgs;
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 exampleGateway = new Gateway("exampleGateway", GatewayArgs.builder()
.name("example_ipsec_vpn_example")
.amazonSideAsn("64512")
.build());
var exampleTransitGateway = new TransitGateway("exampleTransitGateway", TransitGatewayArgs.builder()
.amazonSideAsn(64513)
.description("example_ipsec_vpn_example")
.transitGatewayCidrBlocks("10.0.0.0/24")
.build());
var exampleCustomerGateway = new CustomerGateway("exampleCustomerGateway", CustomerGatewayArgs.builder()
.bgpAsn("64514")
.ipAddress("10.0.0.1")
.type("ipsec.1")
.tags(Map.of("Name", "example_ipsec_vpn_example"))
.build());
var exampleGatewayAssociation = new GatewayAssociation("exampleGatewayAssociation", GatewayAssociationArgs.builder()
.dxGatewayId(exampleGateway.id())
.associatedGatewayId(exampleTransitGateway.id())
.allowedPrefixes("10.0.0.0/8")
.build());
final var example = Ec2transitgatewayFunctions.getDirectConnectGatewayAttachment(GetDirectConnectGatewayAttachmentArgs.builder()
.transitGatewayId(exampleTransitGateway.id())
.dxGatewayId(exampleGateway.id())
.build());
var exampleVpnConnection = new VpnConnection("exampleVpnConnection", VpnConnectionArgs.builder()
.customerGatewayId(exampleCustomerGateway.id())
.outsideIpAddressType("PrivateIpv4")
.transitGatewayId(exampleTransitGateway.id())
.transportTransitGatewayAttachmentId(example.applyValue(_example -> _example.id()))
.type("ipsec.1")
.tags(Map.of("Name", "example_ipsec_vpn_example"))
.build());
}
}
resources:
exampleGateway:
type: aws:directconnect:Gateway
name: example
properties:
name: example_ipsec_vpn_example
amazonSideAsn: '64512'
exampleTransitGateway:
type: aws:ec2transitgateway:TransitGateway
name: example
properties:
amazonSideAsn: '64513'
description: example_ipsec_vpn_example
transitGatewayCidrBlocks:
- 10.0.0.0/24
exampleCustomerGateway:
type: aws:ec2:CustomerGateway
name: example
properties:
bgpAsn: 64514
ipAddress: 10.0.0.1
type: ipsec.1
tags:
Name: example_ipsec_vpn_example
exampleGatewayAssociation:
type: aws:directconnect:GatewayAssociation
name: example
properties:
dxGatewayId: ${exampleGateway.id}
associatedGatewayId: ${exampleTransitGateway.id}
allowedPrefixes:
- 10.0.0.0/8
exampleVpnConnection:
type: aws:ec2:VpnConnection
name: example
properties:
customerGatewayId: ${exampleCustomerGateway.id}
outsideIpAddressType: PrivateIpv4
transitGatewayId: ${exampleTransitGateway.id}
transportTransitGatewayAttachmentId: ${example.id}
type: ipsec.1
tags:
Name: example_ipsec_vpn_example
variables:
example:
fn::invoke:
function: aws:ec2transitgateway:getDirectConnectGatewayAttachment
arguments:
transitGatewayId: ${exampleTransitGateway.id}
dxGatewayId: ${exampleGateway.id}
The outsideIpAddressType property set to “PrivateIpv4” routes VPN traffic over Direct Connect rather than the public internet. The transportTransitGatewayAttachmentId references the Direct Connect Gateway attachment, obtained through a data source after associating your Direct Connect Gateway with the Transit Gateway.
Beyond these examples
These snippets focus on specific VPN connection features: Transit Gateway and Virtual Private Gateway attachment, static routing and BGP configuration, and private VPN over Direct Connect. They’re intentionally minimal rather than full network architectures.
The examples reference pre-existing infrastructure such as Customer Gateways (on-premises VPN endpoints), Transit Gateways or Virtual Private Gateways, and VPCs or Direct Connect Gateways for private VPN scenarios. They focus on establishing the VPN connection rather than provisioning the surrounding network infrastructure.
To keep things focused, common VPN patterns are omitted, including:
- Tunnel-specific configuration (inside CIDR blocks, pre-shared keys)
- IKE and IPsec parameters (phase 1/2 encryption, DH groups, lifetimes)
- Dead Peer Detection and tunnel lifecycle controls
- Tunnel bandwidth selection (standard vs large)
- CloudWatch logging configuration (tunnel1LogOptions, tunnel2LogOptions)
These omissions are intentional: the goal is to illustrate how each VPN connection type is wired, not provide drop-in network modules. See the VPN Connection resource reference for all available configuration options.
Let's configure AWS Site-to-Site VPN Connections
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Gateway Types & Architecture
outsideIpAddressType to PrivateIpv4 and provide transportTransitGatewayAttachmentId pointing to your Direct Connect Gateway attachment. This creates a private S2S VPN instead of a public one.staticRoutesOnly: true for devices that don’t support BGP. Otherwise, BGP is recommended for dynamic routing. Note that this setting is immutable after creation.tunnel1 and tunnel2 properties separately, each with its own IP addresses and settings.Tunnel Configuration & Requirements
tunnel1InsideCidr and tunnel2InsideCidr. For IPv6 (Transit Gateway only), use a /126 CIDR block from the fd00::/8 range.standard (up to 1.25 Gbps per tunnel) or large (up to 5 Gbps per tunnel). The tunnelBandwidth property is immutable and cannot be changed after creation.vpnGatewayId is specified or when enableAcceleration is true. Use a Transit Gateway without acceleration to enable large bandwidth.enableAcceleration, staticRoutesOnly, tunnel1InsideCidr, tunnel1InsideIpv6Cidr, tunnel2InsideCidr, tunnel2InsideIpv6Cidr, tunnelBandwidth, tunnelInsideIpVersion, type, and vpnConcentratorId.Security & Authentication
presharedKeyStorage to SecretsManager to store keys in AWS Secrets Manager instead of the default Standard storage in the Site-to-Site VPN service. The presharedKeyArn output will only contain a valid ARN when using Secrets Manager storage.tunnel1Phase1LifetimeSeconds) ranges from 900 to 28,800 seconds. Phase 2 lifetime (tunnel1Phase2LifetimeSeconds) ranges from 900 to 3,600 seconds.Routing & Advanced Settings
tunnelStartupAction: "add"). Set tunnelStartupAction to start to have AWS initiate the IKE negotiation instead.tunnel1DpdTimeoutSeconds or tunnel2DpdTimeoutSeconds.Using a different cloud?
Explore networking guides for other cloud providers: