Configure GCP Network Connectivity Hub

The gcp:networkconnectivity/hub:Hub resource, part of the Pulumi GCP provider, defines a Network Connectivity Center hub that serves as the central routing point for connecting VPC networks and hybrid environments. This guide focuses on three capabilities: basic hub creation with labels, Private Service Connect transitivity, and preset topology configuration.

Hubs are global resources that require a GCP project with the Network Connectivity Center API enabled. VPC spokes attach to hubs via separate spoke resources. The examples are intentionally small. Combine them with your own spoke attachments and routing policies.

Create a hub with labels for organization

Most deployments start with a basic hub that connects VPC spokes, using labels to organize hubs across projects.

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

const primary = new gcp.networkconnectivity.Hub("primary", {
    name: "basic",
    description: "A sample hub",
    labels: {
        "label-one": "value-one",
    },
});
import pulumi
import pulumi_gcp as gcp

primary = gcp.networkconnectivity.Hub("primary",
    name="basic",
    description="A sample hub",
    labels={
        "label-one": "value-one",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkconnectivity.NewHub(ctx, "primary", &networkconnectivity.HubArgs{
			Name:        pulumi.String("basic"),
			Description: pulumi.String("A sample hub"),
			Labels: pulumi.StringMap{
				"label-one": pulumi.String("value-one"),
			},
		})
		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 primary = new Gcp.NetworkConnectivity.Hub("primary", new()
    {
        Name = "basic",
        Description = "A sample hub",
        Labels = 
        {
            { "label-one", "value-one" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkconnectivity.Hub;
import com.pulumi.gcp.networkconnectivity.HubArgs;
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 primary = new Hub("primary", HubArgs.builder()
            .name("basic")
            .description("A sample hub")
            .labels(Map.of("label-one", "value-one"))
            .build());

    }
}
resources:
  primary:
    type: gcp:networkconnectivity:Hub
    properties:
      name: basic
      description: A sample hub
      labels:
        label-one: value-one

The name property sets a unique identifier for the hub. The description provides human-readable context. Labels add key-value metadata for organization and cost tracking. Without additional configuration, the hub defaults to MESH topology with PRESET policy mode.

Enable Private Service Connect transitivity

When VPC spokes need to access Private Service Connect endpoints across the hub, you enable PSC transitivity.

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

const primary = new gcp.networkconnectivity.Hub("primary", {
    name: "basic",
    description: "A sample hub with Private Service Connect transitivity is enabled",
    exportPsc: true,
});
import pulumi
import pulumi_gcp as gcp

primary = gcp.networkconnectivity.Hub("primary",
    name="basic",
    description="A sample hub with Private Service Connect transitivity is enabled",
    export_psc=True)
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkconnectivity.NewHub(ctx, "primary", &networkconnectivity.HubArgs{
			Name:        pulumi.String("basic"),
			Description: pulumi.String("A sample hub with Private Service Connect transitivity is enabled"),
			ExportPsc:   pulumi.Bool(true),
		})
		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 primary = new Gcp.NetworkConnectivity.Hub("primary", new()
    {
        Name = "basic",
        Description = "A sample hub with Private Service Connect transitivity is enabled",
        ExportPsc = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkconnectivity.Hub;
import com.pulumi.gcp.networkconnectivity.HubArgs;
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 primary = new Hub("primary", HubArgs.builder()
            .name("basic")
            .description("A sample hub with Private Service Connect transitivity is enabled")
            .exportPsc(true)
            .build());

    }
}
resources:
  primary:
    type: gcp:networkconnectivity:Hub
    properties:
      name: basic
      description: A sample hub with Private Service Connect transitivity is enabled
      exportPsc: true

The exportPsc property makes Private Service Connect endpoints in one spoke accessible to other spokes attached to the hub. When set to true, endpoints are shared across the hub; when false (the default), each spoke can only access its own endpoints.

Configure star topology for hub-and-spoke routing

Star topology routes all traffic through the hub, preventing direct spoke-to-spoke communication.

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

const primary = new gcp.networkconnectivity.Hub("primary", {
    name: "star",
    description: "A sample star hub",
    labels: {
        "label-one": "value-one",
    },
    presetTopology: "STAR",
});
import pulumi
import pulumi_gcp as gcp

primary = gcp.networkconnectivity.Hub("primary",
    name="star",
    description="A sample star hub",
    labels={
        "label-one": "value-one",
    },
    preset_topology="STAR")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkconnectivity.NewHub(ctx, "primary", &networkconnectivity.HubArgs{
			Name:        pulumi.String("star"),
			Description: pulumi.String("A sample star hub"),
			Labels: pulumi.StringMap{
				"label-one": pulumi.String("value-one"),
			},
			PresetTopology: pulumi.String("STAR"),
		})
		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 primary = new Gcp.NetworkConnectivity.Hub("primary", new()
    {
        Name = "star",
        Description = "A sample star hub",
        Labels = 
        {
            { "label-one", "value-one" },
        },
        PresetTopology = "STAR",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkconnectivity.Hub;
import com.pulumi.gcp.networkconnectivity.HubArgs;
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 primary = new Hub("primary", HubArgs.builder()
            .name("star")
            .description("A sample star hub")
            .labels(Map.of("label-one", "value-one"))
            .presetTopology("STAR")
            .build());

    }
}
resources:
  primary:
    type: gcp:networkconnectivity:Hub
    properties:
      name: star
      description: A sample star hub
      labels:
        label-one: value-one
      presetTopology: STAR

The presetTopology property controls routing behavior. STAR topology centralizes traffic inspection and control by routing all spoke-to-spoke traffic through the hub. MESH topology (the default) allows direct spoke-to-spoke communication.

Set policy mode with preset topology

Policy mode controls how routing policies are applied to the hub.

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

const primary = new gcp.networkconnectivity.Hub("primary", {
    name: "policy",
    description: "A sample hub with PRESET policy_mode and STAR topology",
    policyMode: "PRESET",
    presetTopology: "STAR",
    labels: {
        "label-one": "value-one",
    },
});
import pulumi
import pulumi_gcp as gcp

primary = gcp.networkconnectivity.Hub("primary",
    name="policy",
    description="A sample hub with PRESET policy_mode and STAR topology",
    policy_mode="PRESET",
    preset_topology="STAR",
    labels={
        "label-one": "value-one",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkconnectivity.NewHub(ctx, "primary", &networkconnectivity.HubArgs{
			Name:           pulumi.String("policy"),
			Description:    pulumi.String("A sample hub with PRESET policy_mode and STAR topology"),
			PolicyMode:     pulumi.String("PRESET"),
			PresetTopology: pulumi.String("STAR"),
			Labels: pulumi.StringMap{
				"label-one": pulumi.String("value-one"),
			},
		})
		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 primary = new Gcp.NetworkConnectivity.Hub("primary", new()
    {
        Name = "policy",
        Description = "A sample hub with PRESET policy_mode and STAR topology",
        PolicyMode = "PRESET",
        PresetTopology = "STAR",
        Labels = 
        {
            { "label-one", "value-one" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkconnectivity.Hub;
import com.pulumi.gcp.networkconnectivity.HubArgs;
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 primary = new Hub("primary", HubArgs.builder()
            .name("policy")
            .description("A sample hub with PRESET policy_mode and STAR topology")
            .policyMode("PRESET")
            .presetTopology("STAR")
            .labels(Map.of("label-one", "value-one"))
            .build());

    }
}
resources:
  primary:
    type: gcp:networkconnectivity:Hub
    properties:
      name: policy
      description: A sample hub with PRESET policy_mode and STAR topology
      policyMode: PRESET
      presetTopology: STAR
      labels:
        label-one: value-one

The policyMode property determines whether you use predefined topologies (PRESET) or custom routing policies (CUSTOM). When set to PRESET, you must specify a presetTopology (MESH or STAR). The combination of PRESET mode with STAR topology provides centralized routing with predefined policies.

Beyond these examples

These snippets focus on specific hub-level features: hub naming and labeling, Private Service Connect transitivity, and preset topologies. They’re intentionally minimal rather than full network architectures.

The examples assume pre-existing infrastructure such as a GCP project with Network Connectivity Center API enabled. They focus on configuring the hub rather than provisioning VPC spokes or routing policies.

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

  • VPC spoke attachments (separate spoke resources)
  • Custom routing policies (policyMode: CUSTOM)
  • Hybrid inspection topology (HYBRID_INSPECTION)
  • Hub deletion and lifecycle management

These omissions are intentional: the goal is to illustrate how each hub feature is wired, not provide drop-in networking modules. See the Network Connectivity Hub resource reference for all available configuration options.

Let's configure GCP Network Connectivity Hub

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 be changed after creating a hub?
Four properties are immutable: name, policyMode, presetTopology, and project. Changing any of these requires replacing the hub.
Why might my configured labels differ from the actual labels on the hub?
The labels field is non-authoritative and only manages labels in your configuration. Use effectiveLabels to see all labels present on the resource, including those set by other clients or services.
Topology & Policy Mode
What topologies are available for Network Connectivity hubs?
Three preset topologies are available: MESH, STAR, and HYBRID_INSPECTION. These are used when policyMode is set to PRESET.
What's the default topology if I don't specify one?
When policyMode is PRESET (the default), presetTopology defaults to MESH.
What's the difference between PRESET and CUSTOM policy modes?
PRESET mode uses predefined topologies (MESH, STAR, HYBRID_INSPECTION) via presetTopology. CUSTOM mode sets presetTopology to PRESET_TOPOLOGY_UNSPECIFIED and allows custom routing policies. If unspecified, policyMode defaults to PRESET.
Private Service Connect
How do I enable Private Service Connect transitivity?
Set exportPsc to true. This makes Private Service Connect endpoints in VPC spokes attached to the hub accessible to other VPC spokes. The default value is false.
Computed Fields
How is the routingVpcs field populated?
routingVpcs is read-only and automatically populated by Network Connectivity Center based on the VPC networks of attached spokes. You cannot set this field directly.

Using a different cloud?

Explore networking guides for other cloud providers: