The gcp:compute/publicAdvertisedPrefix:PublicAdvertisedPrefix resource, part of the Pulumi GCP provider, registers IP address ranges you own with Google Cloud for BYOIP (bring your own IP) scenarios. This guide focuses on three capabilities: IPv4 prefix registration with DNS verification, regional scoping for faster delegation, and IPv6 internal access configuration.
You must own the IP ranges before registering them. IPv4 prefixes require DNS verification to prove ownership. The examples are intentionally small. Combine them with public delegated prefix resources to actually use the addresses.
Advertise an IPv4 prefix with DNS verification
Organizations bringing their own IP addresses start by registering an IPv4 prefix and proving ownership through DNS verification.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const prefixes = new gcp.compute.PublicAdvertisedPrefix("prefixes", {
name: "my-prefix",
description: "description",
dnsVerificationIp: "127.127.0.0",
ipCidrRange: "127.127.0.0/16",
});
import pulumi
import pulumi_gcp as gcp
prefixes = gcp.compute.PublicAdvertisedPrefix("prefixes",
name="my-prefix",
description="description",
dns_verification_ip="127.127.0.0",
ip_cidr_range="127.127.0.0/16")
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 {
_, err := compute.NewPublicAdvertisedPrefix(ctx, "prefixes", &compute.PublicAdvertisedPrefixArgs{
Name: pulumi.String("my-prefix"),
Description: pulumi.String("description"),
DnsVerificationIp: pulumi.String("127.127.0.0"),
IpCidrRange: pulumi.String("127.127.0.0/16"),
})
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 prefixes = new Gcp.Compute.PublicAdvertisedPrefix("prefixes", new()
{
Name = "my-prefix",
Description = "description",
DnsVerificationIp = "127.127.0.0",
IpCidrRange = "127.127.0.0/16",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
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 prefixes = new PublicAdvertisedPrefix("prefixes", PublicAdvertisedPrefixArgs.builder()
.name("my-prefix")
.description("description")
.dnsVerificationIp("127.127.0.0")
.ipCidrRange("127.127.0.0/16")
.build());
}
}
resources:
prefixes:
type: gcp:compute:PublicAdvertisedPrefix
properties:
name: my-prefix
description: description
dnsVerificationIp: 127.127.0.0
ipCidrRange: 127.127.0.0/16
The ipCidrRange defines the address block you’re bringing to Google Cloud. The dnsVerificationIp must be configured in your DNS records to prove you control the range. Google Cloud validates this IP before allowing the prefix to be used.
Set regional scope for delegated prefixes
When delegating portions of your prefix to specific regions, regional scoping reduces provisioning time from weeks to minutes.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const prefixes = new gcp.compute.PublicAdvertisedPrefix("prefixes", {
name: "my-pap",
description: "description",
dnsVerificationIp: "127.127.0.0",
ipCidrRange: "127.127.0.0/16",
pdpScope: "REGIONAL",
});
import pulumi
import pulumi_gcp as gcp
prefixes = gcp.compute.PublicAdvertisedPrefix("prefixes",
name="my-pap",
description="description",
dns_verification_ip="127.127.0.0",
ip_cidr_range="127.127.0.0/16",
pdp_scope="REGIONAL")
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 {
_, err := compute.NewPublicAdvertisedPrefix(ctx, "prefixes", &compute.PublicAdvertisedPrefixArgs{
Name: pulumi.String("my-pap"),
Description: pulumi.String("description"),
DnsVerificationIp: pulumi.String("127.127.0.0"),
IpCidrRange: pulumi.String("127.127.0.0/16"),
PdpScope: pulumi.String("REGIONAL"),
})
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 prefixes = new Gcp.Compute.PublicAdvertisedPrefix("prefixes", new()
{
Name = "my-pap",
Description = "description",
DnsVerificationIp = "127.127.0.0",
IpCidrRange = "127.127.0.0/16",
PdpScope = "REGIONAL",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
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 prefixes = new PublicAdvertisedPrefix("prefixes", PublicAdvertisedPrefixArgs.builder()
.name("my-pap")
.description("description")
.dnsVerificationIp("127.127.0.0")
.ipCidrRange("127.127.0.0/16")
.pdpScope("REGIONAL")
.build());
}
}
resources:
prefixes:
type: gcp:compute:PublicAdvertisedPrefix
properties:
name: my-pap
description: description
dnsVerificationIp: 127.127.0.0
ipCidrRange: 127.127.0.0/16
pdpScope: REGIONAL
The pdpScope property controls how child public delegated prefixes are scoped. Setting it to REGIONAL provisions in minutes rather than the ~4 weeks required for GLOBAL scope. Use REGIONAL when you know which regions will use the prefix.
Configure IPv6 prefix for internal use
IPv6 prefixes can be restricted to internal Google Cloud use, preventing internet announcement.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const prefixes = new gcp.compute.PublicAdvertisedPrefix("prefixes", {
name: "my-pap",
description: "description",
ipCidrRange: "2001:db8::/32",
pdpScope: "REGIONAL",
ipv6AccessType: "INTERNAL",
});
import pulumi
import pulumi_gcp as gcp
prefixes = gcp.compute.PublicAdvertisedPrefix("prefixes",
name="my-pap",
description="description",
ip_cidr_range="2001:db8::/32",
pdp_scope="REGIONAL",
ipv6_access_type="INTERNAL")
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 {
_, err := compute.NewPublicAdvertisedPrefix(ctx, "prefixes", &compute.PublicAdvertisedPrefixArgs{
Name: pulumi.String("my-pap"),
Description: pulumi.String("description"),
IpCidrRange: pulumi.String("2001:db8::/32"),
PdpScope: pulumi.String("REGIONAL"),
Ipv6AccessType: pulumi.String("INTERNAL"),
})
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 prefixes = new Gcp.Compute.PublicAdvertisedPrefix("prefixes", new()
{
Name = "my-pap",
Description = "description",
IpCidrRange = "2001:db8::/32",
PdpScope = "REGIONAL",
Ipv6AccessType = "INTERNAL",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
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 prefixes = new PublicAdvertisedPrefix("prefixes", PublicAdvertisedPrefixArgs.builder()
.name("my-pap")
.description("description")
.ipCidrRange("2001:db8::/32")
.pdpScope("REGIONAL")
.ipv6AccessType("INTERNAL")
.build());
}
}
resources:
prefixes:
type: gcp:compute:PublicAdvertisedPrefix
properties:
name: my-pap
description: description
ipCidrRange: 2001:db8::/32
pdpScope: REGIONAL
ipv6AccessType: INTERNAL
The ipv6AccessType property controls visibility. INTERNAL prevents the prefix from being announced to the internet, keeping it private within Google Cloud. All child delegated prefixes inherit this access type. IPv6 prefixes don’t require dnsVerificationIp.
Beyond these examples
These snippets focus on specific prefix-level features: IPv4 and IPv6 prefix advertisement, regional vs global delegation scoping, and internal vs external access control. They’re intentionally minimal rather than complete BYOIP implementations.
The examples assume you have pre-existing infrastructure such as owned IP address ranges and DNS records for IPv4 verification. They focus on registering the prefix rather than the full BYOIP workflow.
To keep things focused, common prefix patterns are omitted, including:
- Public delegated prefix creation (child resources)
- Prefix lifecycle management (activation, withdrawal)
- Global scope provisioning (4-week timeline)
- DNS verification completion workflow
These omissions are intentional: the goal is to illustrate how each prefix feature is wired, not provide drop-in BYOIP modules. See the PublicAdvertisedPrefix resource reference for all available configuration options.
Let's configure GCP Public Advertised Prefixes
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Provisioning & Timing
pdpScope: REGIONAL scope takes a few minutes, while GLOBAL scope takes approximately 4 weeks.Immutability & Updates
ipCidrRange, ipv6AccessType, name, project, description, dnsVerificationIp, pdpScope) are immutable. Changes require replacing the resource.ipCidrRange and pdpScope are immutable and cannot be modified after creation.IPv4 vs IPv6 Configuration
dnsVerificationIp (an IPv4 address) for reverse DNS verification. IPv6 prefixes require ipv6AccessType instead and use IPv6 CIDR format (e.g., 2001:db8::/32).dnsVerificationIp (an IPv4 address). The output-only sharedSecret field contains the shared secret needed for reverse DNS verification.Access Control & Visibility
[a-z][-a-z0-9]*[a-z0-9]?).Using a different cloud?
Explore networking guides for other cloud providers: