Configure GCP Compute Target Instances

The gcp:compute/targetInstance:TargetInstance resource, part of the Pulumi GCP provider, defines an endpoint that terminates protocol-forwarded traffic by routing it to a single VM instance. This guide focuses on three capabilities: basic target instance creation, custom network routing, and Cloud Armor security policy attachment.

Target instances reference existing Compute Engine VMs and optionally specify VPC networks or security policies. The examples are intentionally small. Combine them with forwarding rules and your own VM infrastructure.

Route traffic to a single VM instance

Protocol forwarding begins by creating a target instance that points to a VM, establishing the endpoint that will receive forwarded packets.

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

const vmimage = gcp.compute.getImage({
    family: "debian-11",
    project: "debian-cloud",
});
const target_vm = new gcp.compute.Instance("target-vm", {
    name: "target-vm",
    machineType: "e2-medium",
    zone: "us-central1-a",
    bootDisk: {
        initializeParams: {
            image: vmimage.then(vmimage => vmimage.selfLink),
        },
    },
    networkInterfaces: [{
        network: "default",
    }],
});
const _default = new gcp.compute.TargetInstance("default", {
    name: "target",
    instance: target_vm.id,
});
import pulumi
import pulumi_gcp as gcp

vmimage = gcp.compute.get_image(family="debian-11",
    project="debian-cloud")
target_vm = gcp.compute.Instance("target-vm",
    name="target-vm",
    machine_type="e2-medium",
    zone="us-central1-a",
    boot_disk={
        "initialize_params": {
            "image": vmimage.self_link,
        },
    },
    network_interfaces=[{
        "network": "default",
    }])
default = gcp.compute.TargetInstance("default",
    name="target",
    instance=target_vm.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 {
		vmimage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
			Family:  pulumi.StringRef("debian-11"),
			Project: pulumi.StringRef("debian-cloud"),
		}, nil)
		if err != nil {
			return err
		}
		target_vm, err := compute.NewInstance(ctx, "target-vm", &compute.InstanceArgs{
			Name:        pulumi.String("target-vm"),
			MachineType: pulumi.String("e2-medium"),
			Zone:        pulumi.String("us-central1-a"),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String(vmimage.SelfLink),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					Network: pulumi.String("default"),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewTargetInstance(ctx, "default", &compute.TargetInstanceArgs{
			Name:     pulumi.String("target"),
			Instance: target_vm.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 vmimage = Gcp.Compute.GetImage.Invoke(new()
    {
        Family = "debian-11",
        Project = "debian-cloud",
    });

    var target_vm = new Gcp.Compute.Instance("target-vm", new()
    {
        Name = "target-vm",
        MachineType = "e2-medium",
        Zone = "us-central1-a",
        BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image = vmimage.Apply(getImageResult => getImageResult.SelfLink),
            },
        },
        NetworkInterfaces = new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                Network = "default",
            },
        },
    });

    var @default = new Gcp.Compute.TargetInstance("default", new()
    {
        Name = "target",
        Instance = target_vm.Id,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetImageArgs;
import com.pulumi.gcp.compute.Instance;
import com.pulumi.gcp.compute.InstanceArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskInitializeParamsArgs;
import com.pulumi.gcp.compute.inputs.InstanceNetworkInterfaceArgs;
import com.pulumi.gcp.compute.TargetInstance;
import com.pulumi.gcp.compute.TargetInstanceArgs;
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) {
        final var vmimage = ComputeFunctions.getImage(GetImageArgs.builder()
            .family("debian-11")
            .project("debian-cloud")
            .build());

        var target_vm = new Instance("target-vm", InstanceArgs.builder()
            .name("target-vm")
            .machineType("e2-medium")
            .zone("us-central1-a")
            .bootDisk(InstanceBootDiskArgs.builder()
                .initializeParams(InstanceBootDiskInitializeParamsArgs.builder()
                    .image(vmimage.selfLink())
                    .build())
                .build())
            .networkInterfaces(InstanceNetworkInterfaceArgs.builder()
                .network("default")
                .build())
            .build());

        var default_ = new TargetInstance("default", TargetInstanceArgs.builder()
            .name("target")
            .instance(target_vm.id())
            .build());

    }
}
resources:
  default:
    type: gcp:compute:TargetInstance
    properties:
      name: target
      instance: ${["target-vm"].id}
  target-vm:
    type: gcp:compute:Instance
    properties:
      name: target-vm
      machineType: e2-medium
      zone: us-central1-a
      bootDisk:
        initializeParams:
          image: ${vmimage.selfLink}
      networkInterfaces:
        - network: default
variables:
  vmimage:
    fn::invoke:
      function: gcp:compute:getImage
      arguments:
        family: debian-11
        project: debian-cloud

The instance property references the VM that handles traffic. The target instance acts as a named endpoint; forwarding rules later direct traffic to this target. Without an explicit network property, the target instance uses the network from the VM’s default interface.

Specify a custom network for forwarding

When VMs run in non-default networks, you can explicitly control which network handles forwarded packets.

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

const target_vm = gcp.compute.getNetwork({
    name: "default",
});
const vmimage = gcp.compute.getImage({
    family: "debian-12",
    project: "debian-cloud",
});
const target_vmInstance = new gcp.compute.Instance("target-vm", {
    name: "custom-network-target-vm",
    machineType: "e2-medium",
    zone: "us-central1-a",
    bootDisk: {
        initializeParams: {
            image: vmimage.then(vmimage => vmimage.selfLink),
        },
    },
    networkInterfaces: [{
        network: "default",
    }],
});
const customNetwork = new gcp.compute.TargetInstance("custom_network", {
    name: "custom-network",
    instance: target_vmInstance.id,
    network: target_vm.then(target_vm => target_vm.selfLink),
});
import pulumi
import pulumi_gcp as gcp

target_vm = gcp.compute.get_network(name="default")
vmimage = gcp.compute.get_image(family="debian-12",
    project="debian-cloud")
target_vm_instance = gcp.compute.Instance("target-vm",
    name="custom-network-target-vm",
    machine_type="e2-medium",
    zone="us-central1-a",
    boot_disk={
        "initialize_params": {
            "image": vmimage.self_link,
        },
    },
    network_interfaces=[{
        "network": "default",
    }])
custom_network = gcp.compute.TargetInstance("custom_network",
    name="custom-network",
    instance=target_vm_instance.id,
    network=target_vm.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 {
		target_vm, err := compute.LookupNetwork(ctx, &compute.LookupNetworkArgs{
			Name: "default",
		}, nil)
		if err != nil {
			return err
		}
		vmimage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
			Family:  pulumi.StringRef("debian-12"),
			Project: pulumi.StringRef("debian-cloud"),
		}, nil)
		if err != nil {
			return err
		}
		target_vmInstance, err := compute.NewInstance(ctx, "target-vm", &compute.InstanceArgs{
			Name:        pulumi.String("custom-network-target-vm"),
			MachineType: pulumi.String("e2-medium"),
			Zone:        pulumi.String("us-central1-a"),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String(vmimage.SelfLink),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					Network: pulumi.String("default"),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewTargetInstance(ctx, "custom_network", &compute.TargetInstanceArgs{
			Name:     pulumi.String("custom-network"),
			Instance: target_vmInstance.ID(),
			Network:  pulumi.String(target_vm.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 target_vm = Gcp.Compute.GetNetwork.Invoke(new()
    {
        Name = "default",
    });

    var vmimage = Gcp.Compute.GetImage.Invoke(new()
    {
        Family = "debian-12",
        Project = "debian-cloud",
    });

    var target_vmInstance = new Gcp.Compute.Instance("target-vm", new()
    {
        Name = "custom-network-target-vm",
        MachineType = "e2-medium",
        Zone = "us-central1-a",
        BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image = vmimage.Apply(getImageResult => getImageResult.SelfLink),
            },
        },
        NetworkInterfaces = new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                Network = "default",
            },
        },
    });

    var customNetwork = new Gcp.Compute.TargetInstance("custom_network", new()
    {
        Name = "custom-network",
        Instance = target_vmInstance.Id,
        Network = target_vm.Apply(target_vm => target_vm.Apply(getNetworkResult => getNetworkResult.SelfLink)),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetNetworkArgs;
import com.pulumi.gcp.compute.inputs.GetImageArgs;
import com.pulumi.gcp.compute.Instance;
import com.pulumi.gcp.compute.InstanceArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskInitializeParamsArgs;
import com.pulumi.gcp.compute.inputs.InstanceNetworkInterfaceArgs;
import com.pulumi.gcp.compute.TargetInstance;
import com.pulumi.gcp.compute.TargetInstanceArgs;
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) {
        final var target-vm = ComputeFunctions.getNetwork(GetNetworkArgs.builder()
            .name("default")
            .build());

        final var vmimage = ComputeFunctions.getImage(GetImageArgs.builder()
            .family("debian-12")
            .project("debian-cloud")
            .build());

        var target_vmInstance = new Instance("target-vmInstance", InstanceArgs.builder()
            .name("custom-network-target-vm")
            .machineType("e2-medium")
            .zone("us-central1-a")
            .bootDisk(InstanceBootDiskArgs.builder()
                .initializeParams(InstanceBootDiskInitializeParamsArgs.builder()
                    .image(vmimage.selfLink())
                    .build())
                .build())
            .networkInterfaces(InstanceNetworkInterfaceArgs.builder()
                .network("default")
                .build())
            .build());

        var customNetwork = new TargetInstance("customNetwork", TargetInstanceArgs.builder()
            .name("custom-network")
            .instance(target_vmInstance.id())
            .network(target_vm.selfLink())
            .build());

    }
}
resources:
  customNetwork:
    type: gcp:compute:TargetInstance
    name: custom_network
    properties:
      name: custom-network
      instance: ${["target-vmInstance"].id}
      network: ${["target-vm"].selfLink}
  target-vmInstance:
    type: gcp:compute:Instance
    name: target-vm
    properties:
      name: custom-network-target-vm
      machineType: e2-medium
      zone: us-central1-a
      bootDisk:
        initializeParams:
          image: ${vmimage.selfLink}
      networkInterfaces:
        - network: default
variables:
  target-vm:
    fn::invoke:
      function: gcp:compute:getNetwork
      arguments:
        name: default
  vmimage:
    fn::invoke:
      function: gcp:compute:getImage
      arguments:
        family: debian-12
        project: debian-cloud

The network property sets which VPC network the target instance uses for forwarding. This matters when your VM has multiple network interfaces or when you need to route traffic through a specific network path. The selfLink provides the full resource URL that GCP requires.

Attach DDoS protection with security policies

Production deployments often require Cloud Armor network security policies to protect against DDoS attacks.

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

const _default = new gcp.compute.Network("default", {
    name: "custom-default-network",
    autoCreateSubnetworks: false,
    routingMode: "REGIONAL",
});
const defaultSubnetwork = new gcp.compute.Subnetwork("default", {
    name: "custom-default-subnet",
    ipCidrRange: "10.1.2.0/24",
    network: _default.id,
    privateIpv6GoogleAccess: "DISABLE_GOOGLE_ACCESS",
    purpose: "PRIVATE",
    region: "southamerica-west1",
    stackType: "IPV4_ONLY",
});
const vmimage = gcp.compute.getImage({
    family: "debian-11",
    project: "debian-cloud",
});
const target_vm = new gcp.compute.Instance("target-vm", {
    networkInterfaces: [{
        accessConfigs: [{}],
        network: _default.selfLink,
        subnetwork: defaultSubnetwork.selfLink,
    }],
    name: "target-vm",
    machineType: "e2-medium",
    zone: "southamerica-west1-a",
    bootDisk: {
        initializeParams: {
            image: vmimage.then(vmimage => vmimage.selfLink),
        },
    },
});
const policyddosprotection = new gcp.compute.RegionSecurityPolicy("policyddosprotection", {
    region: "southamerica-west1",
    name: "tf-test-policyddos_52865",
    description: "ddos protection security policy to set target instance",
    type: "CLOUD_ARMOR_NETWORK",
    ddosProtectionConfig: {
        ddosProtection: "ADVANCED_PREVIEW",
    },
});
const edgeSecService = new gcp.compute.NetworkEdgeSecurityService("edge_sec_service", {
    region: "southamerica-west1",
    name: "tf-test-edgesec_85840",
    securityPolicy: policyddosprotection.selfLink,
});
const regionsecuritypolicy = new gcp.compute.RegionSecurityPolicy("regionsecuritypolicy", {
    name: "region-secpolicy",
    region: "southamerica-west1",
    description: "basic security policy for target instance",
    type: "CLOUD_ARMOR_NETWORK",
}, {
    dependsOn: [edgeSecService],
});
const defaultTargetInstance = new gcp.compute.TargetInstance("default", {
    name: "target-instance",
    zone: "southamerica-west1-a",
    instance: target_vm.id,
    securityPolicy: regionsecuritypolicy.selfLink,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.Network("default",
    name="custom-default-network",
    auto_create_subnetworks=False,
    routing_mode="REGIONAL")
default_subnetwork = gcp.compute.Subnetwork("default",
    name="custom-default-subnet",
    ip_cidr_range="10.1.2.0/24",
    network=default.id,
    private_ipv6_google_access="DISABLE_GOOGLE_ACCESS",
    purpose="PRIVATE",
    region="southamerica-west1",
    stack_type="IPV4_ONLY")
vmimage = gcp.compute.get_image(family="debian-11",
    project="debian-cloud")
target_vm = gcp.compute.Instance("target-vm",
    network_interfaces=[{
        "access_configs": [{}],
        "network": default.self_link,
        "subnetwork": default_subnetwork.self_link,
    }],
    name="target-vm",
    machine_type="e2-medium",
    zone="southamerica-west1-a",
    boot_disk={
        "initialize_params": {
            "image": vmimage.self_link,
        },
    })
policyddosprotection = gcp.compute.RegionSecurityPolicy("policyddosprotection",
    region="southamerica-west1",
    name="tf-test-policyddos_52865",
    description="ddos protection security policy to set target instance",
    type="CLOUD_ARMOR_NETWORK",
    ddos_protection_config={
        "ddos_protection": "ADVANCED_PREVIEW",
    })
edge_sec_service = gcp.compute.NetworkEdgeSecurityService("edge_sec_service",
    region="southamerica-west1",
    name="tf-test-edgesec_85840",
    security_policy=policyddosprotection.self_link)
regionsecuritypolicy = gcp.compute.RegionSecurityPolicy("regionsecuritypolicy",
    name="region-secpolicy",
    region="southamerica-west1",
    description="basic security policy for target instance",
    type="CLOUD_ARMOR_NETWORK",
    opts = pulumi.ResourceOptions(depends_on=[edge_sec_service]))
default_target_instance = gcp.compute.TargetInstance("default",
    name="target-instance",
    zone="southamerica-west1-a",
    instance=target_vm.id,
    security_policy=regionsecuritypolicy.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 {
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name:                  pulumi.String("custom-default-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
			RoutingMode:           pulumi.String("REGIONAL"),
		})
		if err != nil {
			return err
		}
		defaultSubnetwork, err := compute.NewSubnetwork(ctx, "default", &compute.SubnetworkArgs{
			Name:                    pulumi.String("custom-default-subnet"),
			IpCidrRange:             pulumi.String("10.1.2.0/24"),
			Network:                 _default.ID(),
			PrivateIpv6GoogleAccess: pulumi.String("DISABLE_GOOGLE_ACCESS"),
			Purpose:                 pulumi.String("PRIVATE"),
			Region:                  pulumi.String("southamerica-west1"),
			StackType:               pulumi.String("IPV4_ONLY"),
		})
		if err != nil {
			return err
		}
		vmimage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
			Family:  pulumi.StringRef("debian-11"),
			Project: pulumi.StringRef("debian-cloud"),
		}, nil)
		if err != nil {
			return err
		}
		target_vm, err := compute.NewInstance(ctx, "target-vm", &compute.InstanceArgs{
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					AccessConfigs: compute.InstanceNetworkInterfaceAccessConfigArray{
						&compute.InstanceNetworkInterfaceAccessConfigArgs{},
					},
					Network:    _default.SelfLink,
					Subnetwork: defaultSubnetwork.SelfLink,
				},
			},
			Name:        pulumi.String("target-vm"),
			MachineType: pulumi.String("e2-medium"),
			Zone:        pulumi.String("southamerica-west1-a"),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String(vmimage.SelfLink),
				},
			},
		})
		if err != nil {
			return err
		}
		policyddosprotection, err := compute.NewRegionSecurityPolicy(ctx, "policyddosprotection", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("southamerica-west1"),
			Name:        pulumi.String("tf-test-policyddos_52865"),
			Description: pulumi.String("ddos protection security policy to set target instance"),
			Type:        pulumi.String("CLOUD_ARMOR_NETWORK"),
			DdosProtectionConfig: &compute.RegionSecurityPolicyDdosProtectionConfigArgs{
				DdosProtection: pulumi.String("ADVANCED_PREVIEW"),
			},
		})
		if err != nil {
			return err
		}
		edgeSecService, err := compute.NewNetworkEdgeSecurityService(ctx, "edge_sec_service", &compute.NetworkEdgeSecurityServiceArgs{
			Region:         pulumi.String("southamerica-west1"),
			Name:           pulumi.String("tf-test-edgesec_85840"),
			SecurityPolicy: policyddosprotection.SelfLink,
		})
		if err != nil {
			return err
		}
		regionsecuritypolicy, err := compute.NewRegionSecurityPolicy(ctx, "regionsecuritypolicy", &compute.RegionSecurityPolicyArgs{
			Name:        pulumi.String("region-secpolicy"),
			Region:      pulumi.String("southamerica-west1"),
			Description: pulumi.String("basic security policy for target instance"),
			Type:        pulumi.String("CLOUD_ARMOR_NETWORK"),
		}, pulumi.DependsOn([]pulumi.Resource{
			edgeSecService,
		}))
		if err != nil {
			return err
		}
		_, err = compute.NewTargetInstance(ctx, "default", &compute.TargetInstanceArgs{
			Name:           pulumi.String("target-instance"),
			Zone:           pulumi.String("southamerica-west1-a"),
			Instance:       target_vm.ID(),
			SecurityPolicy: regionsecuritypolicy.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 @default = new Gcp.Compute.Network("default", new()
    {
        Name = "custom-default-network",
        AutoCreateSubnetworks = false,
        RoutingMode = "REGIONAL",
    });

    var defaultSubnetwork = new Gcp.Compute.Subnetwork("default", new()
    {
        Name = "custom-default-subnet",
        IpCidrRange = "10.1.2.0/24",
        Network = @default.Id,
        PrivateIpv6GoogleAccess = "DISABLE_GOOGLE_ACCESS",
        Purpose = "PRIVATE",
        Region = "southamerica-west1",
        StackType = "IPV4_ONLY",
    });

    var vmimage = Gcp.Compute.GetImage.Invoke(new()
    {
        Family = "debian-11",
        Project = "debian-cloud",
    });

    var target_vm = new Gcp.Compute.Instance("target-vm", new()
    {
        NetworkInterfaces = new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                AccessConfigs = new[]
                {
                    null,
                },
                Network = @default.SelfLink,
                Subnetwork = defaultSubnetwork.SelfLink,
            },
        },
        Name = "target-vm",
        MachineType = "e2-medium",
        Zone = "southamerica-west1-a",
        BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image = vmimage.Apply(getImageResult => getImageResult.SelfLink),
            },
        },
    });

    var policyddosprotection = new Gcp.Compute.RegionSecurityPolicy("policyddosprotection", new()
    {
        Region = "southamerica-west1",
        Name = "tf-test-policyddos_52865",
        Description = "ddos protection security policy to set target instance",
        Type = "CLOUD_ARMOR_NETWORK",
        DdosProtectionConfig = new Gcp.Compute.Inputs.RegionSecurityPolicyDdosProtectionConfigArgs
        {
            DdosProtection = "ADVANCED_PREVIEW",
        },
    });

    var edgeSecService = new Gcp.Compute.NetworkEdgeSecurityService("edge_sec_service", new()
    {
        Region = "southamerica-west1",
        Name = "tf-test-edgesec_85840",
        SecurityPolicy = policyddosprotection.SelfLink,
    });

    var regionsecuritypolicy = new Gcp.Compute.RegionSecurityPolicy("regionsecuritypolicy", new()
    {
        Name = "region-secpolicy",
        Region = "southamerica-west1",
        Description = "basic security policy for target instance",
        Type = "CLOUD_ARMOR_NETWORK",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            edgeSecService,
        },
    });

    var defaultTargetInstance = new Gcp.Compute.TargetInstance("default", new()
    {
        Name = "target-instance",
        Zone = "southamerica-west1-a",
        Instance = target_vm.Id,
        SecurityPolicy = regionsecuritypolicy.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.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetImageArgs;
import com.pulumi.gcp.compute.Instance;
import com.pulumi.gcp.compute.InstanceArgs;
import com.pulumi.gcp.compute.inputs.InstanceNetworkInterfaceArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskInitializeParamsArgs;
import com.pulumi.gcp.compute.RegionSecurityPolicy;
import com.pulumi.gcp.compute.RegionSecurityPolicyArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyDdosProtectionConfigArgs;
import com.pulumi.gcp.compute.NetworkEdgeSecurityService;
import com.pulumi.gcp.compute.NetworkEdgeSecurityServiceArgs;
import com.pulumi.gcp.compute.TargetInstance;
import com.pulumi.gcp.compute.TargetInstanceArgs;
import com.pulumi.resources.CustomResourceOptions;
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 default_ = new Network("default", NetworkArgs.builder()
            .name("custom-default-network")
            .autoCreateSubnetworks(false)
            .routingMode("REGIONAL")
            .build());

        var defaultSubnetwork = new Subnetwork("defaultSubnetwork", SubnetworkArgs.builder()
            .name("custom-default-subnet")
            .ipCidrRange("10.1.2.0/24")
            .network(default_.id())
            .privateIpv6GoogleAccess("DISABLE_GOOGLE_ACCESS")
            .purpose("PRIVATE")
            .region("southamerica-west1")
            .stackType("IPV4_ONLY")
            .build());

        final var vmimage = ComputeFunctions.getImage(GetImageArgs.builder()
            .family("debian-11")
            .project("debian-cloud")
            .build());

        var target_vm = new Instance("target-vm", InstanceArgs.builder()
            .networkInterfaces(InstanceNetworkInterfaceArgs.builder()
                .accessConfigs(InstanceNetworkInterfaceAccessConfigArgs.builder()
                    .build())
                .network(default_.selfLink())
                .subnetwork(defaultSubnetwork.selfLink())
                .build())
            .name("target-vm")
            .machineType("e2-medium")
            .zone("southamerica-west1-a")
            .bootDisk(InstanceBootDiskArgs.builder()
                .initializeParams(InstanceBootDiskInitializeParamsArgs.builder()
                    .image(vmimage.selfLink())
                    .build())
                .build())
            .build());

        var policyddosprotection = new RegionSecurityPolicy("policyddosprotection", RegionSecurityPolicyArgs.builder()
            .region("southamerica-west1")
            .name("tf-test-policyddos_52865")
            .description("ddos protection security policy to set target instance")
            .type("CLOUD_ARMOR_NETWORK")
            .ddosProtectionConfig(RegionSecurityPolicyDdosProtectionConfigArgs.builder()
                .ddosProtection("ADVANCED_PREVIEW")
                .build())
            .build());

        var edgeSecService = new NetworkEdgeSecurityService("edgeSecService", NetworkEdgeSecurityServiceArgs.builder()
            .region("southamerica-west1")
            .name("tf-test-edgesec_85840")
            .securityPolicy(policyddosprotection.selfLink())
            .build());

        var regionsecuritypolicy = new RegionSecurityPolicy("regionsecuritypolicy", RegionSecurityPolicyArgs.builder()
            .name("region-secpolicy")
            .region("southamerica-west1")
            .description("basic security policy for target instance")
            .type("CLOUD_ARMOR_NETWORK")
            .build(), CustomResourceOptions.builder()
                .dependsOn(edgeSecService)
                .build());

        var defaultTargetInstance = new TargetInstance("defaultTargetInstance", TargetInstanceArgs.builder()
            .name("target-instance")
            .zone("southamerica-west1-a")
            .instance(target_vm.id())
            .securityPolicy(regionsecuritypolicy.selfLink())
            .build());

    }
}
resources:
  default:
    type: gcp:compute:Network
    properties:
      name: custom-default-network
      autoCreateSubnetworks: false
      routingMode: REGIONAL
  defaultSubnetwork:
    type: gcp:compute:Subnetwork
    name: default
    properties:
      name: custom-default-subnet
      ipCidrRange: 10.1.2.0/24
      network: ${default.id}
      privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS
      purpose: PRIVATE
      region: southamerica-west1
      stackType: IPV4_ONLY
  target-vm:
    type: gcp:compute:Instance
    properties:
      networkInterfaces:
        - accessConfigs:
            - {}
          network: ${default.selfLink}
          subnetwork: ${defaultSubnetwork.selfLink}
      name: target-vm
      machineType: e2-medium
      zone: southamerica-west1-a
      bootDisk:
        initializeParams:
          image: ${vmimage.selfLink}
  policyddosprotection:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: southamerica-west1
      name: tf-test-policyddos_52865
      description: ddos protection security policy to set target instance
      type: CLOUD_ARMOR_NETWORK
      ddosProtectionConfig:
        ddosProtection: ADVANCED_PREVIEW
  edgeSecService:
    type: gcp:compute:NetworkEdgeSecurityService
    name: edge_sec_service
    properties:
      region: southamerica-west1
      name: tf-test-edgesec_85840
      securityPolicy: ${policyddosprotection.selfLink}
  regionsecuritypolicy:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      name: region-secpolicy
      region: southamerica-west1
      description: basic security policy for target instance
      type: CLOUD_ARMOR_NETWORK
    options:
      dependsOn:
        - ${edgeSecService}
  defaultTargetInstance:
    type: gcp:compute:TargetInstance
    name: default
    properties:
      name: target-instance
      zone: southamerica-west1-a
      instance: ${["target-vm"].id}
      securityPolicy: ${regionsecuritypolicy.selfLink}
variables:
  vmimage:
    fn::invoke:
      function: gcp:compute:getImage
      arguments:
        family: debian-11
        project: debian-cloud

The securityPolicy property attaches a regional security policy to the target instance. Cloud Armor policies must be type CLOUD_ARMOR_NETWORK and exist in the same region as the target instance. The example shows both DDoS protection configuration and the NetworkEdgeSecurityService that connects policies to network resources.

Beyond these examples

These snippets focus on specific target instance features: basic creation, custom network routing, and Cloud Armor security policies. They’re intentionally minimal rather than complete forwarding configurations.

The examples reference pre-existing infrastructure such as Compute Engine VM instances to receive traffic and VPC networks (default or custom). They focus on configuring the target instance rather than provisioning the complete forwarding path.

To keep things focused, common target instance patterns are omitted, including:

  • Forwarding rules that send traffic to target instances
  • NAT policy configuration (only NO_NAT is supported)
  • Description metadata (description property)
  • Multi-region or global forwarding setups

These omissions are intentional: the goal is to illustrate how each target instance feature is wired, not provide drop-in forwarding modules. See the TargetInstance resource reference for all available configuration options.

Let's configure GCP Compute Target Instances

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 a target instance?
Most properties are immutable and force replacement: instance, name, zone, project, description, natPolicy, and network. Only securityPolicy can be updated in-place.
Can I update the security policy without recreating the target instance?
Yes, securityPolicy is the only mutable property. You can update it without forcing resource replacement.
Instance & Network Setup
What formats can I use for the instance property?
You can provide the instance self-link, relative path like projects/project/zones/zone/instances/instance, or just the instance name. When using only the name, zone and project default to your provider configuration.
Do I need to specify a network for my target instance?
No, the network property is optional. If not specified, traffic forwards to the network that the instance’s default network interface belongs to.
How do I use a custom network with my target instance?
Set the network property to the network’s self-link, as shown in the custom network example.
Naming & Constraints
What are the naming requirements for a target instance?
The name must be 1-63 characters long and match the regex a-z?. This means it starts with a lowercase letter, followed by dashes, lowercase letters, or digits, and cannot end with a dash.
What NAT options are available for target instances?
Only NO_NAT is supported, which is also the default value. The natPolicy property is immutable.
Use Cases & Purpose
What's the purpose of a target instance?
Target instances define endpoints that terminate traffic for protocol forwarding. They contain a single VM that receives and handles traffic from forwarding rules, enabling non-NAT’ed packet forwarding.
How do I attach a security policy to my target instance?
Set the securityPolicy property to the resource URL of your regional security policy, as demonstrated in the security policy example.

Using a different cloud?

Explore networking guides for other cloud providers: