Configure GCP OS Config Guest Policies

The gcp:osconfig/guestPolicies:GuestPolicies resource, part of the Pulumi GCP provider, defines OS Config guest policies that declare desired package states and software installations across VM instances. This guide focuses on three capabilities: VM targeting strategies, package management with custom repositories, and recipe-based software installation from Cloud Storage.

Guest policies reference existing Compute Engine instances and may require Cloud Storage buckets for recipe artifacts. The examples are intentionally small. Combine them with your own VM infrastructure and artifact storage.

Assign a policy to specific VM instances

When you need to ensure specific instances maintain certain package states, guest policies let you target individual VMs by ID.

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

const myImage = gcp.compute.getImage({
    family: "debian-11",
    project: "debian-cloud",
});
const foobar = new gcp.compute.Instance("foobar", {
    name: "guest-policy-inst",
    machineType: "e2-medium",
    zone: "us-central1-a",
    canIpForward: false,
    tags: [
        "foo",
        "bar",
    ],
    bootDisk: {
        initializeParams: {
            image: myImage.then(myImage => myImage.selfLink),
        },
    },
    networkInterfaces: [{
        network: "default",
    }],
    metadata: {
        foo: "bar",
    },
});
const guestPolicies = new gcp.osconfig.GuestPolicies("guest_policies", {
    guestPolicyId: "guest-policy",
    assignment: {
        instances: [foobar.id],
    },
    packages: [{
        name: "my-package",
        desiredState: "UPDATED",
    }],
});
import pulumi
import pulumi_gcp as gcp

my_image = gcp.compute.get_image(family="debian-11",
    project="debian-cloud")
foobar = gcp.compute.Instance("foobar",
    name="guest-policy-inst",
    machine_type="e2-medium",
    zone="us-central1-a",
    can_ip_forward=False,
    tags=[
        "foo",
        "bar",
    ],
    boot_disk={
        "initialize_params": {
            "image": my_image.self_link,
        },
    },
    network_interfaces=[{
        "network": "default",
    }],
    metadata={
        "foo": "bar",
    })
guest_policies = gcp.osconfig.GuestPolicies("guest_policies",
    guest_policy_id="guest-policy",
    assignment={
        "instances": [foobar.id],
    },
    packages=[{
        "name": "my-package",
        "desired_state": "UPDATED",
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myImage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
			Family:  pulumi.StringRef("debian-11"),
			Project: pulumi.StringRef("debian-cloud"),
		}, nil)
		if err != nil {
			return err
		}
		foobar, err := compute.NewInstance(ctx, "foobar", &compute.InstanceArgs{
			Name:         pulumi.String("guest-policy-inst"),
			MachineType:  pulumi.String("e2-medium"),
			Zone:         pulumi.String("us-central1-a"),
			CanIpForward: pulumi.Bool(false),
			Tags: pulumi.StringArray{
				pulumi.String("foo"),
				pulumi.String("bar"),
			},
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String(myImage.SelfLink),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					Network: pulumi.String("default"),
				},
			},
			Metadata: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		if err != nil {
			return err
		}
		_, err = osconfig.NewGuestPolicies(ctx, "guest_policies", &osconfig.GuestPoliciesArgs{
			GuestPolicyId: pulumi.String("guest-policy"),
			Assignment: &osconfig.GuestPoliciesAssignmentArgs{
				Instances: pulumi.StringArray{
					foobar.ID(),
				},
			},
			Packages: osconfig.GuestPoliciesPackageArray{
				&osconfig.GuestPoliciesPackageArgs{
					Name:         pulumi.String("my-package"),
					DesiredState: pulumi.String("UPDATED"),
				},
			},
		})
		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 myImage = Gcp.Compute.GetImage.Invoke(new()
    {
        Family = "debian-11",
        Project = "debian-cloud",
    });

    var foobar = new Gcp.Compute.Instance("foobar", new()
    {
        Name = "guest-policy-inst",
        MachineType = "e2-medium",
        Zone = "us-central1-a",
        CanIpForward = false,
        Tags = new[]
        {
            "foo",
            "bar",
        },
        BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image = myImage.Apply(getImageResult => getImageResult.SelfLink),
            },
        },
        NetworkInterfaces = new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                Network = "default",
            },
        },
        Metadata = 
        {
            { "foo", "bar" },
        },
    });

    var guestPolicies = new Gcp.OsConfig.GuestPolicies("guest_policies", new()
    {
        GuestPolicyId = "guest-policy",
        Assignment = new Gcp.OsConfig.Inputs.GuestPoliciesAssignmentArgs
        {
            Instances = new[]
            {
                foobar.Id,
            },
        },
        Packages = new[]
        {
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageArgs
            {
                Name = "my-package",
                DesiredState = "UPDATED",
            },
        },
    });

});
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.osconfig.GuestPolicies;
import com.pulumi.gcp.osconfig.GuestPoliciesArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesAssignmentArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesPackageArgs;
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 myImage = ComputeFunctions.getImage(GetImageArgs.builder()
            .family("debian-11")
            .project("debian-cloud")
            .build());

        var foobar = new Instance("foobar", InstanceArgs.builder()
            .name("guest-policy-inst")
            .machineType("e2-medium")
            .zone("us-central1-a")
            .canIpForward(false)
            .tags(            
                "foo",
                "bar")
            .bootDisk(InstanceBootDiskArgs.builder()
                .initializeParams(InstanceBootDiskInitializeParamsArgs.builder()
                    .image(myImage.selfLink())
                    .build())
                .build())
            .networkInterfaces(InstanceNetworkInterfaceArgs.builder()
                .network("default")
                .build())
            .metadata(Map.of("foo", "bar"))
            .build());

        var guestPolicies = new GuestPolicies("guestPolicies", GuestPoliciesArgs.builder()
            .guestPolicyId("guest-policy")
            .assignment(GuestPoliciesAssignmentArgs.builder()
                .instances(foobar.id())
                .build())
            .packages(GuestPoliciesPackageArgs.builder()
                .name("my-package")
                .desiredState("UPDATED")
                .build())
            .build());

    }
}
resources:
  foobar:
    type: gcp:compute:Instance
    properties:
      name: guest-policy-inst
      machineType: e2-medium
      zone: us-central1-a
      canIpForward: false
      tags:
        - foo
        - bar
      bootDisk:
        initializeParams:
          image: ${myImage.selfLink}
      networkInterfaces:
        - network: default
      metadata:
        foo: bar
  guestPolicies:
    type: gcp:osconfig:GuestPolicies
    name: guest_policies
    properties:
      guestPolicyId: guest-policy
      assignment:
        instances:
          - ${foobar.id}
      packages:
        - name: my-package
          desiredState: UPDATED
variables:
  myImage:
    fn::invoke:
      function: gcp:compute:getImage
      arguments:
        family: debian-11
        project: debian-cloud

The assignment block controls which VMs receive this policy. Setting instances to a list of VM IDs targets those specific machines. The packages array declares desired states: UPDATED ensures the package stays current, while INSTALLED and REMOVED control presence.

Target VMs by labels and configure package repositories

Label-based targeting applies policies across VM groups without listing individual instances, and custom repositories enable package installation from non-default sources.

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

const guestPolicies = new gcp.osconfig.GuestPolicies("guest_policies", {
    guestPolicyId: "guest-policy",
    assignment: {
        groupLabels: [
            {
                labels: {
                    color: "red",
                    env: "test",
                },
            },
            {
                labels: {
                    color: "blue",
                    env: "test",
                },
            },
        ],
    },
    packages: [
        {
            name: "my-package",
            desiredState: "INSTALLED",
        },
        {
            name: "bad-package-1",
            desiredState: "REMOVED",
        },
        {
            name: "bad-package-2",
            desiredState: "REMOVED",
            manager: "APT",
        },
    ],
    packageRepositories: [
        {
            apt: {
                uri: "https://packages.cloud.google.com/apt",
                archiveType: "DEB",
                distribution: "cloud-sdk-stretch",
                components: ["main"],
            },
        },
        {
            yum: {
                id: "google-cloud-sdk",
                displayName: "Google Cloud SDK",
                baseUrl: "https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64",
                gpgKeys: [
                    "https://packages.cloud.google.com/yum/doc/yum-key.gpg",
                    "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
                ],
            },
        },
    ],
});
import pulumi
import pulumi_gcp as gcp

guest_policies = gcp.osconfig.GuestPolicies("guest_policies",
    guest_policy_id="guest-policy",
    assignment={
        "group_labels": [
            {
                "labels": {
                    "color": "red",
                    "env": "test",
                },
            },
            {
                "labels": {
                    "color": "blue",
                    "env": "test",
                },
            },
        ],
    },
    packages=[
        {
            "name": "my-package",
            "desired_state": "INSTALLED",
        },
        {
            "name": "bad-package-1",
            "desired_state": "REMOVED",
        },
        {
            "name": "bad-package-2",
            "desired_state": "REMOVED",
            "manager": "APT",
        },
    ],
    package_repositories=[
        {
            "apt": {
                "uri": "https://packages.cloud.google.com/apt",
                "archive_type": "DEB",
                "distribution": "cloud-sdk-stretch",
                "components": ["main"],
            },
        },
        {
            "yum": {
                "id": "google-cloud-sdk",
                "display_name": "Google Cloud SDK",
                "base_url": "https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64",
                "gpg_keys": [
                    "https://packages.cloud.google.com/yum/doc/yum-key.gpg",
                    "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
                ],
            },
        },
    ])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := osconfig.NewGuestPolicies(ctx, "guest_policies", &osconfig.GuestPoliciesArgs{
			GuestPolicyId: pulumi.String("guest-policy"),
			Assignment: &osconfig.GuestPoliciesAssignmentArgs{
				GroupLabels: osconfig.GuestPoliciesAssignmentGroupLabelArray{
					&osconfig.GuestPoliciesAssignmentGroupLabelArgs{
						Labels: pulumi.StringMap{
							"color": pulumi.String("red"),
							"env":   pulumi.String("test"),
						},
					},
					&osconfig.GuestPoliciesAssignmentGroupLabelArgs{
						Labels: pulumi.StringMap{
							"color": pulumi.String("blue"),
							"env":   pulumi.String("test"),
						},
					},
				},
			},
			Packages: osconfig.GuestPoliciesPackageArray{
				&osconfig.GuestPoliciesPackageArgs{
					Name:         pulumi.String("my-package"),
					DesiredState: pulumi.String("INSTALLED"),
				},
				&osconfig.GuestPoliciesPackageArgs{
					Name:         pulumi.String("bad-package-1"),
					DesiredState: pulumi.String("REMOVED"),
				},
				&osconfig.GuestPoliciesPackageArgs{
					Name:         pulumi.String("bad-package-2"),
					DesiredState: pulumi.String("REMOVED"),
					Manager:      pulumi.String("APT"),
				},
			},
			PackageRepositories: osconfig.GuestPoliciesPackageRepositoryArray{
				&osconfig.GuestPoliciesPackageRepositoryArgs{
					Apt: &osconfig.GuestPoliciesPackageRepositoryAptArgs{
						Uri:          pulumi.String("https://packages.cloud.google.com/apt"),
						ArchiveType:  pulumi.String("DEB"),
						Distribution: pulumi.String("cloud-sdk-stretch"),
						Components: pulumi.StringArray{
							pulumi.String("main"),
						},
					},
				},
				&osconfig.GuestPoliciesPackageRepositoryArgs{
					Yum: &osconfig.GuestPoliciesPackageRepositoryYumArgs{
						Id:          pulumi.String("google-cloud-sdk"),
						DisplayName: pulumi.String("Google Cloud SDK"),
						BaseUrl:     pulumi.String("https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64"),
						GpgKeys: pulumi.StringArray{
							pulumi.String("https://packages.cloud.google.com/yum/doc/yum-key.gpg"),
							pulumi.String("https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg"),
						},
					},
				},
			},
		})
		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 guestPolicies = new Gcp.OsConfig.GuestPolicies("guest_policies", new()
    {
        GuestPolicyId = "guest-policy",
        Assignment = new Gcp.OsConfig.Inputs.GuestPoliciesAssignmentArgs
        {
            GroupLabels = new[]
            {
                new Gcp.OsConfig.Inputs.GuestPoliciesAssignmentGroupLabelArgs
                {
                    Labels = 
                    {
                        { "color", "red" },
                        { "env", "test" },
                    },
                },
                new Gcp.OsConfig.Inputs.GuestPoliciesAssignmentGroupLabelArgs
                {
                    Labels = 
                    {
                        { "color", "blue" },
                        { "env", "test" },
                    },
                },
            },
        },
        Packages = new[]
        {
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageArgs
            {
                Name = "my-package",
                DesiredState = "INSTALLED",
            },
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageArgs
            {
                Name = "bad-package-1",
                DesiredState = "REMOVED",
            },
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageArgs
            {
                Name = "bad-package-2",
                DesiredState = "REMOVED",
                Manager = "APT",
            },
        },
        PackageRepositories = new[]
        {
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageRepositoryArgs
            {
                Apt = new Gcp.OsConfig.Inputs.GuestPoliciesPackageRepositoryAptArgs
                {
                    Uri = "https://packages.cloud.google.com/apt",
                    ArchiveType = "DEB",
                    Distribution = "cloud-sdk-stretch",
                    Components = new[]
                    {
                        "main",
                    },
                },
            },
            new Gcp.OsConfig.Inputs.GuestPoliciesPackageRepositoryArgs
            {
                Yum = new Gcp.OsConfig.Inputs.GuestPoliciesPackageRepositoryYumArgs
                {
                    Id = "google-cloud-sdk",
                    DisplayName = "Google Cloud SDK",
                    BaseUrl = "https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64",
                    GpgKeys = new[]
                    {
                        "https://packages.cloud.google.com/yum/doc/yum-key.gpg",
                        "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.osconfig.GuestPolicies;
import com.pulumi.gcp.osconfig.GuestPoliciesArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesAssignmentArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesPackageArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesPackageRepositoryArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesPackageRepositoryAptArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesPackageRepositoryYumArgs;
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 guestPolicies = new GuestPolicies("guestPolicies", GuestPoliciesArgs.builder()
            .guestPolicyId("guest-policy")
            .assignment(GuestPoliciesAssignmentArgs.builder()
                .groupLabels(                
                    GuestPoliciesAssignmentGroupLabelArgs.builder()
                        .labels(Map.ofEntries(
                            Map.entry("color", "red"),
                            Map.entry("env", "test")
                        ))
                        .build(),
                    GuestPoliciesAssignmentGroupLabelArgs.builder()
                        .labels(Map.ofEntries(
                            Map.entry("color", "blue"),
                            Map.entry("env", "test")
                        ))
                        .build())
                .build())
            .packages(            
                GuestPoliciesPackageArgs.builder()
                    .name("my-package")
                    .desiredState("INSTALLED")
                    .build(),
                GuestPoliciesPackageArgs.builder()
                    .name("bad-package-1")
                    .desiredState("REMOVED")
                    .build(),
                GuestPoliciesPackageArgs.builder()
                    .name("bad-package-2")
                    .desiredState("REMOVED")
                    .manager("APT")
                    .build())
            .packageRepositories(            
                GuestPoliciesPackageRepositoryArgs.builder()
                    .apt(GuestPoliciesPackageRepositoryAptArgs.builder()
                        .uri("https://packages.cloud.google.com/apt")
                        .archiveType("DEB")
                        .distribution("cloud-sdk-stretch")
                        .components("main")
                        .build())
                    .build(),
                GuestPoliciesPackageRepositoryArgs.builder()
                    .yum(GuestPoliciesPackageRepositoryYumArgs.builder()
                        .id("google-cloud-sdk")
                        .displayName("Google Cloud SDK")
                        .baseUrl("https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64")
                        .gpgKeys(                        
                            "https://packages.cloud.google.com/yum/doc/yum-key.gpg",
                            "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg")
                        .build())
                    .build())
            .build());

    }
}
resources:
  guestPolicies:
    type: gcp:osconfig:GuestPolicies
    name: guest_policies
    properties:
      guestPolicyId: guest-policy
      assignment:
        groupLabels:
          - labels:
              color: red
              env: test
          - labels:
              color: blue
              env: test
      packages:
        - name: my-package
          desiredState: INSTALLED
        - name: bad-package-1
          desiredState: REMOVED
        - name: bad-package-2
          desiredState: REMOVED
          manager: APT
      packageRepositories:
        - apt:
            uri: https://packages.cloud.google.com/apt
            archiveType: DEB
            distribution: cloud-sdk-stretch
            components:
              - main
        - yum:
            id: google-cloud-sdk
            displayName: Google Cloud SDK
            baseUrl: https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
            gpgKeys:
              - https://packages.cloud.google.com/yum/doc/yum-key.gpg
              - https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

The groupLabels array defines multiple label sets; VMs matching any set receive the policy. Each labels map specifies key-value pairs that must all match. The packageRepositories block configures apt and yum repositories before package installation, allowing you to use packages from custom sources like the Google Cloud SDK repository.

Install software from GCS artifacts using recipes

For software that requires custom installation steps beyond package managers, recipes define multi-step procedures that fetch artifacts from Cloud Storage.

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

const guestPolicies = new gcp.osconfig.GuestPolicies("guest_policies", {
    guestPolicyId: "guest-policy",
    assignment: {
        zones: [
            "us-east1-b",
            "us-east1-d",
        ],
    },
    recipes: [{
        name: "guest-policy-recipe",
        desiredState: "INSTALLED",
        artifacts: [{
            id: "guest-policy-artifact-id",
            gcs: {
                bucket: "my-bucket",
                object: "executable.msi",
                generation: 1546030865175603,
            },
        }],
        installSteps: [{
            msiInstallation: {
                artifactId: "guest-policy-artifact-id",
            },
        }],
    }],
});
import pulumi
import pulumi_gcp as gcp

guest_policies = gcp.osconfig.GuestPolicies("guest_policies",
    guest_policy_id="guest-policy",
    assignment={
        "zones": [
            "us-east1-b",
            "us-east1-d",
        ],
    },
    recipes=[{
        "name": "guest-policy-recipe",
        "desired_state": "INSTALLED",
        "artifacts": [{
            "id": "guest-policy-artifact-id",
            "gcs": {
                "bucket": "my-bucket",
                "object": "executable.msi",
                "generation": 1546030865175603,
            },
        }],
        "install_steps": [{
            "msi_installation": {
                "artifact_id": "guest-policy-artifact-id",
            },
        }],
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := osconfig.NewGuestPolicies(ctx, "guest_policies", &osconfig.GuestPoliciesArgs{
			GuestPolicyId: pulumi.String("guest-policy"),
			Assignment: &osconfig.GuestPoliciesAssignmentArgs{
				Zones: pulumi.StringArray{
					pulumi.String("us-east1-b"),
					pulumi.String("us-east1-d"),
				},
			},
			Recipes: osconfig.GuestPoliciesRecipeArray{
				&osconfig.GuestPoliciesRecipeArgs{
					Name:         pulumi.String("guest-policy-recipe"),
					DesiredState: pulumi.String("INSTALLED"),
					Artifacts: osconfig.GuestPoliciesRecipeArtifactArray{
						&osconfig.GuestPoliciesRecipeArtifactArgs{
							Id: pulumi.String("guest-policy-artifact-id"),
							Gcs: &osconfig.GuestPoliciesRecipeArtifactGcsArgs{
								Bucket:     pulumi.String("my-bucket"),
								Object:     pulumi.String("executable.msi"),
								Generation: pulumi.Int(1546030865175603),
							},
						},
					},
					InstallSteps: osconfig.GuestPoliciesRecipeInstallStepArray{
						&osconfig.GuestPoliciesRecipeInstallStepArgs{
							MsiInstallation: &osconfig.GuestPoliciesRecipeInstallStepMsiInstallationArgs{
								ArtifactId: pulumi.String("guest-policy-artifact-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 guestPolicies = new Gcp.OsConfig.GuestPolicies("guest_policies", new()
    {
        GuestPolicyId = "guest-policy",
        Assignment = new Gcp.OsConfig.Inputs.GuestPoliciesAssignmentArgs
        {
            Zones = new[]
            {
                "us-east1-b",
                "us-east1-d",
            },
        },
        Recipes = new[]
        {
            new Gcp.OsConfig.Inputs.GuestPoliciesRecipeArgs
            {
                Name = "guest-policy-recipe",
                DesiredState = "INSTALLED",
                Artifacts = new[]
                {
                    new Gcp.OsConfig.Inputs.GuestPoliciesRecipeArtifactArgs
                    {
                        Id = "guest-policy-artifact-id",
                        Gcs = new Gcp.OsConfig.Inputs.GuestPoliciesRecipeArtifactGcsArgs
                        {
                            Bucket = "my-bucket",
                            Object = "executable.msi",
                            Generation = 1546030865175603,
                        },
                    },
                },
                InstallSteps = new[]
                {
                    new Gcp.OsConfig.Inputs.GuestPoliciesRecipeInstallStepArgs
                    {
                        MsiInstallation = new Gcp.OsConfig.Inputs.GuestPoliciesRecipeInstallStepMsiInstallationArgs
                        {
                            ArtifactId = "guest-policy-artifact-id",
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.osconfig.GuestPolicies;
import com.pulumi.gcp.osconfig.GuestPoliciesArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesAssignmentArgs;
import com.pulumi.gcp.osconfig.inputs.GuestPoliciesRecipeArgs;
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 guestPolicies = new GuestPolicies("guestPolicies", GuestPoliciesArgs.builder()
            .guestPolicyId("guest-policy")
            .assignment(GuestPoliciesAssignmentArgs.builder()
                .zones(                
                    "us-east1-b",
                    "us-east1-d")
                .build())
            .recipes(GuestPoliciesRecipeArgs.builder()
                .name("guest-policy-recipe")
                .desiredState("INSTALLED")
                .artifacts(GuestPoliciesRecipeArtifactArgs.builder()
                    .id("guest-policy-artifact-id")
                    .gcs(GuestPoliciesRecipeArtifactGcsArgs.builder()
                        .bucket("my-bucket")
                        .object("executable.msi")
                        .generation(1546030865175603)
                        .build())
                    .build())
                .installSteps(GuestPoliciesRecipeInstallStepArgs.builder()
                    .msiInstallation(GuestPoliciesRecipeInstallStepMsiInstallationArgs.builder()
                        .artifactId("guest-policy-artifact-id")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  guestPolicies:
    type: gcp:osconfig:GuestPolicies
    name: guest_policies
    properties:
      guestPolicyId: guest-policy
      assignment:
        zones:
          - us-east1-b
          - us-east1-d
      recipes:
        - name: guest-policy-recipe
          desiredState: INSTALLED
          artifacts:
            - id: guest-policy-artifact-id
              gcs:
                bucket: my-bucket
                object: executable.msi
                generation: 1.546030865175603e+15
          installSteps:
            - msiInstallation:
                artifactId: guest-policy-artifact-id

The assignment targets VMs by zone rather than instance ID or labels. Each recipe defines artifacts (stored in GCS with bucket, object, and generation) and installSteps that reference those artifacts. The msiInstallation step executes Windows MSI installers; other step types support shell scripts and file operations.

Beyond these examples

These snippets focus on specific guest policy features: VM targeting (instances, labels, zones), package management and repository configuration, and recipe-based software installation. They’re intentionally minimal rather than full VM configuration management solutions.

The examples reference pre-existing infrastructure such as Compute Engine VM instances and Cloud Storage buckets with installation artifacts. They focus on policy configuration rather than provisioning the underlying infrastructure.

To keep things focused, common guest policy patterns are omitted, including:

  • OS family and version targeting (osShortName)
  • Instance name prefix/suffix matching
  • Recipe update and removal workflows
  • Artifact verification and checksums

These omissions are intentional: the goal is to illustrate how each guest policy feature is wired, not provide drop-in configuration management modules. See the OS Config GuestPolicies resource reference for all available configuration options.

Let's configure GCP OS Config Guest Policies

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Setup & Requirements
Why do I need to use the beta provider for guest policies?
Guest policies are a beta resource and require the terraform-provider-google-beta provider. They won’t work with the standard GCP provider.
What are the naming rules for guest policy IDs?
The guestPolicyId must contain only lowercase letters, numbers, and hyphens; start with a letter; be 1-63 characters long; end with a number or letter; and be unique within the project.
VM Targeting & Assignment
How do I target specific VMs with a guest policy?
Use the assignment field with one of three methods: instances for specific VM IDs, groupLabels for label-based targeting, or zones for zone-based targeting. You can combine multiple criteria within the same assignment.
What happens if my guest policies conflict with each other?
The service prevents creating multiple policies that conflict at the same level in the resource hierarchy (within a project). Review your assignment criteria to avoid overlapping VM targets.
Package Management
How do I manage packages with guest policies?
Use the packages array with name and desiredState. Available states are INSTALLED (ensure present), UPDATED (keep current), or REMOVED (uninstall). Optionally specify manager (like APT) to target specific package managers.
Can I configure both APT and YUM repositories in the same policy?
Yes, add multiple entries to the packageRepositories array with different repository types. Package repositories are configured before other configs and only apply if the corresponding package manager is available on the VM.
Why isn't my package repository being configured?
Package repositories are only configured if the corresponding package manager is available on the target VM. Ensure your VMs have the appropriate package manager (APT, YUM, etc.) installed.
Recipes & Software Installation
What's the difference between packages and recipes?
packages manage system packages through package managers (APT, YUM), while recipes install software from artifacts stored in GCS using custom installation steps like MSI installations.
How do I install software from a GCS bucket using recipes?
Define a recipe with an artifacts entry containing a gcs source (bucket, object, generation), then reference the artifact ID in installSteps using the appropriate installation method like msiInstallation.
Updates & Immutability
What can't I change after creating a guest policy?
The project field is immutable and cannot be changed after creation.

Using a different cloud?

Explore compute guides for other cloud providers: