Configure GCP Compute Target Instances

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

Target instances reference existing Compute Engine VMs and optionally specify 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 starts by creating a target instance that points to a VM, establishing an endpoint for forwarding rules.

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 receives traffic. The target instance acts as a stable endpoint; forwarding rules send packets here, and the target instance routes them to the specified VM. Without an explicit network property, traffic uses the VM’s default network interface.

Specify a custom network for forwarding

When VMs have multiple network interfaces, you can control which network receives forwarded traffic.

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 overrides the default behavior, directing traffic through a specific VPC. This matters when your VM spans multiple networks and you need precise control over routing paths.

Attach DDoS protection with security policies

Production deployments often add 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_34962",
    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_74000",
    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_34962",
    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_74000",
    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_34962"),
			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_74000"),
			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_34962",
        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_74000",
        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_34962")
            .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_74000")
            .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_34962
      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_74000
      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 RegionSecurityPolicy to the target instance. Cloud Armor Network policies (type CLOUD_ARMOR_NETWORK) provide DDoS protection and network-level access controls. The NetworkEdgeSecurityService links the policy to the network edge. All resources must be in the same region.

Beyond these examples

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

The examples reference pre-existing infrastructure such as Compute Engine VM instances to receive traffic. 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)
  • Multi-region or global load balancing setups
  • Health checks and failover configuration

These omissions are intentional: the goal is to illustrate how each target instance feature is wired, not provide drop-in load balancing 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 I change after creating a target instance?
Only securityPolicy can be modified after creation. All other properties (instance, name, zone, project, description, natPolicy, and network) are immutable and require resource replacement to change.
What are the naming requirements for a target instance?
The name must be 1-63 characters long, start with a lowercase letter, contain only lowercase letters, digits, and dashes, and cannot end with a dash. This follows the regex pattern a-z?.
Instance & Network Setup
What formats can I use to reference the compute instance?
You can reference the instance using three formats: the instance self-link, a relative path like projects/project/zones/zone/instances/instance, or just the instance name. If using the name alone, the zone and project default to the provider configuration.
When should I specify the network property?
Specify network when you need to forward traffic to a specific network. If not specified, traffic is forwarded to the network that the default network interface belongs to.
Security & Advanced Features
Can I add or change a security policy after creating the target instance?
Yes, securityPolicy is the only mutable property. You can add or update it by setting the property to the resource URL of a RegionSecurityPolicy.
What is a target instance used for?
Target instances define endpoints that terminate traffic for Protocol Forwarding. They contain a single VM instance that receives and handles traffic from forwarding rules, particularly for non-NAT’ed traffic.

Using a different cloud?

Explore networking guides for other cloud providers: