Create AWS Lightsail CDN Distributions

The aws:lightsail/distribution:Distribution resource, part of the Pulumi AWS provider, defines a Lightsail CDN distribution that caches content at edge locations to reduce latency for users accessing your content. This guide focuses on three capabilities: bucket origins for static assets, instance origins for application content, and load balancer origins for high-availability applications.

Distributions require an existing Lightsail origin resource and may depend on static IP or load balancer attachments being configured first. The examples are intentionally small. Combine them with your own SSL certificates, custom cache behaviors, and monitoring.

Distribute content from a Lightsail bucket

Most CDN deployments cache static assets stored in object storage, reducing latency for users accessing images, videos, or other files.

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

const example = new aws.lightsail.Bucket("example", {
    name: "example-bucket",
    bundleId: "small_1_0",
});
const exampleDistribution = new aws.lightsail.Distribution("example", {
    name: "example-distribution",
    bundleId: "small_1_0",
    origin: {
        name: example.name,
        regionName: example.region,
    },
    defaultCacheBehavior: {
        behavior: "cache",
    },
    cacheBehaviorSettings: {
        allowedHttpMethods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
        cachedHttpMethods: "GET,HEAD",
        defaultTtl: 86400,
        maximumTtl: 31536000,
        minimumTtl: 0,
        forwardedCookies: {
            option: "none",
        },
        forwardedHeaders: {
            option: "default",
        },
        forwardedQueryStrings: {
            option: false,
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.lightsail.Bucket("example",
    name="example-bucket",
    bundle_id="small_1_0")
example_distribution = aws.lightsail.Distribution("example",
    name="example-distribution",
    bundle_id="small_1_0",
    origin={
        "name": example.name,
        "region_name": example.region,
    },
    default_cache_behavior={
        "behavior": "cache",
    },
    cache_behavior_settings={
        "allowed_http_methods": "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
        "cached_http_methods": "GET,HEAD",
        "default_ttl": 86400,
        "maximum_ttl": 31536000,
        "minimum_ttl": 0,
        "forwarded_cookies": {
            "option": "none",
        },
        "forwarded_headers": {
            "option": "default",
        },
        "forwarded_query_strings": {
            "option": False,
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lightsail"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := lightsail.NewBucket(ctx, "example", &lightsail.BucketArgs{
			Name:     pulumi.String("example-bucket"),
			BundleId: pulumi.String("small_1_0"),
		})
		if err != nil {
			return err
		}
		_, err = lightsail.NewDistribution(ctx, "example", &lightsail.DistributionArgs{
			Name:     pulumi.String("example-distribution"),
			BundleId: pulumi.String("small_1_0"),
			Origin: &lightsail.DistributionOriginArgs{
				Name:       example.Name,
				RegionName: example.Region,
			},
			DefaultCacheBehavior: &lightsail.DistributionDefaultCacheBehaviorArgs{
				Behavior: pulumi.String("cache"),
			},
			CacheBehaviorSettings: &lightsail.DistributionCacheBehaviorSettingsArgs{
				AllowedHttpMethods: pulumi.String("GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE"),
				CachedHttpMethods:  pulumi.String("GET,HEAD"),
				DefaultTtl:         pulumi.Int(86400),
				MaximumTtl:         pulumi.Int(31536000),
				MinimumTtl:         pulumi.Int(0),
				ForwardedCookies: &lightsail.DistributionCacheBehaviorSettingsForwardedCookiesArgs{
					Option: pulumi.String("none"),
				},
				ForwardedHeaders: &lightsail.DistributionCacheBehaviorSettingsForwardedHeadersArgs{
					Option: pulumi.String("default"),
				},
				ForwardedQueryStrings: &lightsail.DistributionCacheBehaviorSettingsForwardedQueryStringsArgs{
					Option: pulumi.Bool(false),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.LightSail.Bucket("example", new()
    {
        Name = "example-bucket",
        BundleId = "small_1_0",
    });

    var exampleDistribution = new Aws.LightSail.Distribution("example", new()
    {
        Name = "example-distribution",
        BundleId = "small_1_0",
        Origin = new Aws.LightSail.Inputs.DistributionOriginArgs
        {
            Name = example.Name,
            RegionName = example.Region,
        },
        DefaultCacheBehavior = new Aws.LightSail.Inputs.DistributionDefaultCacheBehaviorArgs
        {
            Behavior = "cache",
        },
        CacheBehaviorSettings = new Aws.LightSail.Inputs.DistributionCacheBehaviorSettingsArgs
        {
            AllowedHttpMethods = "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
            CachedHttpMethods = "GET,HEAD",
            DefaultTtl = 86400,
            MaximumTtl = 31536000,
            MinimumTtl = 0,
            ForwardedCookies = new Aws.LightSail.Inputs.DistributionCacheBehaviorSettingsForwardedCookiesArgs
            {
                Option = "none",
            },
            ForwardedHeaders = new Aws.LightSail.Inputs.DistributionCacheBehaviorSettingsForwardedHeadersArgs
            {
                Option = "default",
            },
            ForwardedQueryStrings = new Aws.LightSail.Inputs.DistributionCacheBehaviorSettingsForwardedQueryStringsArgs
            {
                Option = false,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lightsail.Bucket;
import com.pulumi.aws.lightsail.BucketArgs;
import com.pulumi.aws.lightsail.Distribution;
import com.pulumi.aws.lightsail.DistributionArgs;
import com.pulumi.aws.lightsail.inputs.DistributionOriginArgs;
import com.pulumi.aws.lightsail.inputs.DistributionDefaultCacheBehaviorArgs;
import com.pulumi.aws.lightsail.inputs.DistributionCacheBehaviorSettingsArgs;
import com.pulumi.aws.lightsail.inputs.DistributionCacheBehaviorSettingsForwardedCookiesArgs;
import com.pulumi.aws.lightsail.inputs.DistributionCacheBehaviorSettingsForwardedHeadersArgs;
import com.pulumi.aws.lightsail.inputs.DistributionCacheBehaviorSettingsForwardedQueryStringsArgs;
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 example = new Bucket("example", BucketArgs.builder()
            .name("example-bucket")
            .bundleId("small_1_0")
            .build());

        var exampleDistribution = new Distribution("exampleDistribution", DistributionArgs.builder()
            .name("example-distribution")
            .bundleId("small_1_0")
            .origin(DistributionOriginArgs.builder()
                .name(example.name())
                .regionName(example.region())
                .build())
            .defaultCacheBehavior(DistributionDefaultCacheBehaviorArgs.builder()
                .behavior("cache")
                .build())
            .cacheBehaviorSettings(DistributionCacheBehaviorSettingsArgs.builder()
                .allowedHttpMethods("GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE")
                .cachedHttpMethods("GET,HEAD")
                .defaultTtl(86400)
                .maximumTtl(31536000)
                .minimumTtl(0)
                .forwardedCookies(DistributionCacheBehaviorSettingsForwardedCookiesArgs.builder()
                    .option("none")
                    .build())
                .forwardedHeaders(DistributionCacheBehaviorSettingsForwardedHeadersArgs.builder()
                    .option("default")
                    .build())
                .forwardedQueryStrings(DistributionCacheBehaviorSettingsForwardedQueryStringsArgs.builder()
                    .option(false)
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:lightsail:Bucket
    properties:
      name: example-bucket
      bundleId: small_1_0
  exampleDistribution:
    type: aws:lightsail:Distribution
    name: example
    properties:
      name: example-distribution
      bundleId: small_1_0
      origin:
        name: ${example.name}
        regionName: ${example.region}
      defaultCacheBehavior:
        behavior: cache
      cacheBehaviorSettings:
        allowedHttpMethods: GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE
        cachedHttpMethods: GET,HEAD
        defaultTtl: 86400
        maximumTtl: 3.1536e+07
        minimumTtl: 0
        forwardedCookies:
          option: none
        forwardedHeaders:
          option: default
        forwardedQueryStrings:
          option: false

The origin property points to your Lightsail bucket by name and region. The defaultCacheBehavior sets whether content is cached at edge locations. The cacheBehaviorSettings block controls HTTP methods, TTL values, and what headers or cookies are forwarded to the origin. Here, GET and HEAD requests are cached for up to 24 hours (86400 seconds), with a maximum TTL of one year.

Distribute content from a Lightsail instance

Applications running on instances can benefit from CDN caching to reduce origin load and improve response times.

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

const available = aws.getAvailabilityZones({
    state: "available",
    filters: [{
        name: "opt-in-status",
        values: ["opt-in-not-required"],
    }],
});
const exampleStaticIp = new aws.lightsail.StaticIp("example", {name: "example-static-ip"});
const exampleInstance = new aws.lightsail.Instance("example", {
    name: "example-instance",
    availabilityZone: available.then(available => available.names?.[0]),
    blueprintId: "amazon_linux_2",
    bundleId: "micro_1_0",
});
const example = new aws.lightsail.StaticIpAttachment("example", {
    staticIpName: exampleStaticIp.name,
    instanceName: exampleInstance.name,
});
const exampleDistribution = new aws.lightsail.Distribution("example", {
    name: "example-distribution",
    bundleId: "small_1_0",
    origin: {
        name: exampleInstance.name,
        regionName: available.then(available => available.id),
    },
    defaultCacheBehavior: {
        behavior: "cache",
    },
}, {
    dependsOn: [example],
});
import pulumi
import pulumi_aws as aws

available = aws.get_availability_zones(state="available",
    filters=[{
        "name": "opt-in-status",
        "values": ["opt-in-not-required"],
    }])
example_static_ip = aws.lightsail.StaticIp("example", name="example-static-ip")
example_instance = aws.lightsail.Instance("example",
    name="example-instance",
    availability_zone=available.names[0],
    blueprint_id="amazon_linux_2",
    bundle_id="micro_1_0")
example = aws.lightsail.StaticIpAttachment("example",
    static_ip_name=example_static_ip.name,
    instance_name=example_instance.name)
example_distribution = aws.lightsail.Distribution("example",
    name="example-distribution",
    bundle_id="small_1_0",
    origin={
        "name": example_instance.name,
        "region_name": available.id,
    },
    default_cache_behavior={
        "behavior": "cache",
    },
    opts = pulumi.ResourceOptions(depends_on=[example]))
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lightsail"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		available, err := aws.GetAvailabilityZones(ctx, &aws.GetAvailabilityZonesArgs{
			State: pulumi.StringRef("available"),
			Filters: []aws.GetAvailabilityZonesFilter{
				{
					Name: "opt-in-status",
					Values: []string{
						"opt-in-not-required",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		exampleStaticIp, err := lightsail.NewStaticIp(ctx, "example", &lightsail.StaticIpArgs{
			Name: pulumi.String("example-static-ip"),
		})
		if err != nil {
			return err
		}
		exampleInstance, err := lightsail.NewInstance(ctx, "example", &lightsail.InstanceArgs{
			Name:             pulumi.String("example-instance"),
			AvailabilityZone: pulumi.String(available.Names[0]),
			BlueprintId:      pulumi.String("amazon_linux_2"),
			BundleId:         pulumi.String("micro_1_0"),
		})
		if err != nil {
			return err
		}
		example, err := lightsail.NewStaticIpAttachment(ctx, "example", &lightsail.StaticIpAttachmentArgs{
			StaticIpName: exampleStaticIp.Name,
			InstanceName: exampleInstance.Name,
		})
		if err != nil {
			return err
		}
		_, err = lightsail.NewDistribution(ctx, "example", &lightsail.DistributionArgs{
			Name:     pulumi.String("example-distribution"),
			BundleId: pulumi.String("small_1_0"),
			Origin: &lightsail.DistributionOriginArgs{
				Name:       exampleInstance.Name,
				RegionName: pulumi.String(available.Id),
			},
			DefaultCacheBehavior: &lightsail.DistributionDefaultCacheBehaviorArgs{
				Behavior: pulumi.String("cache"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			example,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var available = Aws.GetAvailabilityZones.Invoke(new()
    {
        State = "available",
        Filters = new[]
        {
            new Aws.Inputs.GetAvailabilityZonesFilterInputArgs
            {
                Name = "opt-in-status",
                Values = new[]
                {
                    "opt-in-not-required",
                },
            },
        },
    });

    var exampleStaticIp = new Aws.LightSail.StaticIp("example", new()
    {
        Name = "example-static-ip",
    });

    var exampleInstance = new Aws.LightSail.Instance("example", new()
    {
        Name = "example-instance",
        AvailabilityZone = available.Apply(getAvailabilityZonesResult => getAvailabilityZonesResult.Names[0]),
        BlueprintId = "amazon_linux_2",
        BundleId = "micro_1_0",
    });

    var example = new Aws.LightSail.StaticIpAttachment("example", new()
    {
        StaticIpName = exampleStaticIp.Name,
        InstanceName = exampleInstance.Name,
    });

    var exampleDistribution = new Aws.LightSail.Distribution("example", new()
    {
        Name = "example-distribution",
        BundleId = "small_1_0",
        Origin = new Aws.LightSail.Inputs.DistributionOriginArgs
        {
            Name = exampleInstance.Name,
            RegionName = available.Apply(getAvailabilityZonesResult => getAvailabilityZonesResult.Id),
        },
        DefaultCacheBehavior = new Aws.LightSail.Inputs.DistributionDefaultCacheBehaviorArgs
        {
            Behavior = "cache",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            example,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetAvailabilityZonesArgs;
import com.pulumi.aws.lightsail.StaticIp;
import com.pulumi.aws.lightsail.StaticIpArgs;
import com.pulumi.aws.lightsail.Instance;
import com.pulumi.aws.lightsail.InstanceArgs;
import com.pulumi.aws.lightsail.StaticIpAttachment;
import com.pulumi.aws.lightsail.StaticIpAttachmentArgs;
import com.pulumi.aws.lightsail.Distribution;
import com.pulumi.aws.lightsail.DistributionArgs;
import com.pulumi.aws.lightsail.inputs.DistributionOriginArgs;
import com.pulumi.aws.lightsail.inputs.DistributionDefaultCacheBehaviorArgs;
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) {
        final var available = AwsFunctions.getAvailabilityZones(GetAvailabilityZonesArgs.builder()
            .state("available")
            .filters(GetAvailabilityZonesFilterArgs.builder()
                .name("opt-in-status")
                .values("opt-in-not-required")
                .build())
            .build());

        var exampleStaticIp = new StaticIp("exampleStaticIp", StaticIpArgs.builder()
            .name("example-static-ip")
            .build());

        var exampleInstance = new Instance("exampleInstance", InstanceArgs.builder()
            .name("example-instance")
            .availabilityZone(available.names()[0])
            .blueprintId("amazon_linux_2")
            .bundleId("micro_1_0")
            .build());

        var example = new StaticIpAttachment("example", StaticIpAttachmentArgs.builder()
            .staticIpName(exampleStaticIp.name())
            .instanceName(exampleInstance.name())
            .build());

        var exampleDistribution = new Distribution("exampleDistribution", DistributionArgs.builder()
            .name("example-distribution")
            .bundleId("small_1_0")
            .origin(DistributionOriginArgs.builder()
                .name(exampleInstance.name())
                .regionName(available.id())
                .build())
            .defaultCacheBehavior(DistributionDefaultCacheBehaviorArgs.builder()
                .behavior("cache")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(example)
                .build());

    }
}
resources:
  example:
    type: aws:lightsail:StaticIpAttachment
    properties:
      staticIpName: ${exampleStaticIp.name}
      instanceName: ${exampleInstance.name}
  exampleStaticIp:
    type: aws:lightsail:StaticIp
    name: example
    properties:
      name: example-static-ip
  exampleInstance:
    type: aws:lightsail:Instance
    name: example
    properties:
      name: example-instance
      availabilityZone: ${available.names[0]}
      blueprintId: amazon_linux_2
      bundleId: micro_1_0
  exampleDistribution:
    type: aws:lightsail:Distribution
    name: example
    properties:
      name: example-distribution
      bundleId: small_1_0
      origin:
        name: ${exampleInstance.name}
        regionName: ${available.id}
      defaultCacheBehavior:
        behavior: cache
    options:
      dependsOn:
        - ${example}
variables:
  available:
    fn::invoke:
      function: aws:getAvailabilityZones
      arguments:
        state: available
        filters:
          - name: opt-in-status
            values:
              - opt-in-not-required

The origin references your instance by name and region. The dependsOn property ensures the static IP attachment completes before creating the distribution, since distributions require a stable IP address for the origin. Without this dependency, the distribution might attempt to reference an instance without a static IP.

Distribute content from a load balancer

Load-balanced applications use distributions to cache responses while maintaining high availability across multiple backend instances.

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

const available = aws.getAvailabilityZones({
    state: "available",
    filters: [{
        name: "opt-in-status",
        values: ["opt-in-not-required"],
    }],
});
const example = new aws.lightsail.Lb("example", {
    name: "example-load-balancer",
    healthCheckPath: "/",
    instancePort: 80,
    tags: {
        foo: "bar",
    },
});
const exampleInstance = new aws.lightsail.Instance("example", {
    name: "example-instance",
    availabilityZone: available.then(available => available.names?.[0]),
    blueprintId: "amazon_linux_2",
    bundleId: "nano_3_0",
});
const exampleLbAttachment = new aws.lightsail.LbAttachment("example", {
    lbName: example.name,
    instanceName: exampleInstance.name,
});
const exampleDistribution = new aws.lightsail.Distribution("example", {
    name: "example-distribution",
    bundleId: "small_1_0",
    origin: {
        name: example.name,
        regionName: available.then(available => available.id),
    },
    defaultCacheBehavior: {
        behavior: "cache",
    },
}, {
    dependsOn: [exampleLbAttachment],
});
import pulumi
import pulumi_aws as aws

available = aws.get_availability_zones(state="available",
    filters=[{
        "name": "opt-in-status",
        "values": ["opt-in-not-required"],
    }])
example = aws.lightsail.Lb("example",
    name="example-load-balancer",
    health_check_path="/",
    instance_port=80,
    tags={
        "foo": "bar",
    })
example_instance = aws.lightsail.Instance("example",
    name="example-instance",
    availability_zone=available.names[0],
    blueprint_id="amazon_linux_2",
    bundle_id="nano_3_0")
example_lb_attachment = aws.lightsail.LbAttachment("example",
    lb_name=example.name,
    instance_name=example_instance.name)
example_distribution = aws.lightsail.Distribution("example",
    name="example-distribution",
    bundle_id="small_1_0",
    origin={
        "name": example.name,
        "region_name": available.id,
    },
    default_cache_behavior={
        "behavior": "cache",
    },
    opts = pulumi.ResourceOptions(depends_on=[example_lb_attachment]))
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lightsail"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		available, err := aws.GetAvailabilityZones(ctx, &aws.GetAvailabilityZonesArgs{
			State: pulumi.StringRef("available"),
			Filters: []aws.GetAvailabilityZonesFilter{
				{
					Name: "opt-in-status",
					Values: []string{
						"opt-in-not-required",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		example, err := lightsail.NewLb(ctx, "example", &lightsail.LbArgs{
			Name:            pulumi.String("example-load-balancer"),
			HealthCheckPath: pulumi.String("/"),
			InstancePort:    pulumi.Int(80),
			Tags: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		if err != nil {
			return err
		}
		exampleInstance, err := lightsail.NewInstance(ctx, "example", &lightsail.InstanceArgs{
			Name:             pulumi.String("example-instance"),
			AvailabilityZone: pulumi.String(available.Names[0]),
			BlueprintId:      pulumi.String("amazon_linux_2"),
			BundleId:         pulumi.String("nano_3_0"),
		})
		if err != nil {
			return err
		}
		exampleLbAttachment, err := lightsail.NewLbAttachment(ctx, "example", &lightsail.LbAttachmentArgs{
			LbName:       example.Name,
			InstanceName: exampleInstance.Name,
		})
		if err != nil {
			return err
		}
		_, err = lightsail.NewDistribution(ctx, "example", &lightsail.DistributionArgs{
			Name:     pulumi.String("example-distribution"),
			BundleId: pulumi.String("small_1_0"),
			Origin: &lightsail.DistributionOriginArgs{
				Name:       example.Name,
				RegionName: pulumi.String(available.Id),
			},
			DefaultCacheBehavior: &lightsail.DistributionDefaultCacheBehaviorArgs{
				Behavior: pulumi.String("cache"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			exampleLbAttachment,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var available = Aws.GetAvailabilityZones.Invoke(new()
    {
        State = "available",
        Filters = new[]
        {
            new Aws.Inputs.GetAvailabilityZonesFilterInputArgs
            {
                Name = "opt-in-status",
                Values = new[]
                {
                    "opt-in-not-required",
                },
            },
        },
    });

    var example = new Aws.LightSail.Lb("example", new()
    {
        Name = "example-load-balancer",
        HealthCheckPath = "/",
        InstancePort = 80,
        Tags = 
        {
            { "foo", "bar" },
        },
    });

    var exampleInstance = new Aws.LightSail.Instance("example", new()
    {
        Name = "example-instance",
        AvailabilityZone = available.Apply(getAvailabilityZonesResult => getAvailabilityZonesResult.Names[0]),
        BlueprintId = "amazon_linux_2",
        BundleId = "nano_3_0",
    });

    var exampleLbAttachment = new Aws.LightSail.LbAttachment("example", new()
    {
        LbName = example.Name,
        InstanceName = exampleInstance.Name,
    });

    var exampleDistribution = new Aws.LightSail.Distribution("example", new()
    {
        Name = "example-distribution",
        BundleId = "small_1_0",
        Origin = new Aws.LightSail.Inputs.DistributionOriginArgs
        {
            Name = example.Name,
            RegionName = available.Apply(getAvailabilityZonesResult => getAvailabilityZonesResult.Id),
        },
        DefaultCacheBehavior = new Aws.LightSail.Inputs.DistributionDefaultCacheBehaviorArgs
        {
            Behavior = "cache",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            exampleLbAttachment,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetAvailabilityZonesArgs;
import com.pulumi.aws.lightsail.Lb;
import com.pulumi.aws.lightsail.LbArgs;
import com.pulumi.aws.lightsail.Instance;
import com.pulumi.aws.lightsail.InstanceArgs;
import com.pulumi.aws.lightsail.LbAttachment;
import com.pulumi.aws.lightsail.LbAttachmentArgs;
import com.pulumi.aws.lightsail.Distribution;
import com.pulumi.aws.lightsail.DistributionArgs;
import com.pulumi.aws.lightsail.inputs.DistributionOriginArgs;
import com.pulumi.aws.lightsail.inputs.DistributionDefaultCacheBehaviorArgs;
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) {
        final var available = AwsFunctions.getAvailabilityZones(GetAvailabilityZonesArgs.builder()
            .state("available")
            .filters(GetAvailabilityZonesFilterArgs.builder()
                .name("opt-in-status")
                .values("opt-in-not-required")
                .build())
            .build());

        var example = new Lb("example", LbArgs.builder()
            .name("example-load-balancer")
            .healthCheckPath("/")
            .instancePort(80)
            .tags(Map.of("foo", "bar"))
            .build());

        var exampleInstance = new Instance("exampleInstance", InstanceArgs.builder()
            .name("example-instance")
            .availabilityZone(available.names()[0])
            .blueprintId("amazon_linux_2")
            .bundleId("nano_3_0")
            .build());

        var exampleLbAttachment = new LbAttachment("exampleLbAttachment", LbAttachmentArgs.builder()
            .lbName(example.name())
            .instanceName(exampleInstance.name())
            .build());

        var exampleDistribution = new Distribution("exampleDistribution", DistributionArgs.builder()
            .name("example-distribution")
            .bundleId("small_1_0")
            .origin(DistributionOriginArgs.builder()
                .name(example.name())
                .regionName(available.id())
                .build())
            .defaultCacheBehavior(DistributionDefaultCacheBehaviorArgs.builder()
                .behavior("cache")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(exampleLbAttachment)
                .build());

    }
}
resources:
  example:
    type: aws:lightsail:Lb
    properties:
      name: example-load-balancer
      healthCheckPath: /
      instancePort: '80'
      tags:
        foo: bar
  exampleInstance:
    type: aws:lightsail:Instance
    name: example
    properties:
      name: example-instance
      availabilityZone: ${available.names[0]}
      blueprintId: amazon_linux_2
      bundleId: nano_3_0
  exampleLbAttachment:
    type: aws:lightsail:LbAttachment
    name: example
    properties:
      lbName: ${example.name}
      instanceName: ${exampleInstance.name}
  exampleDistribution:
    type: aws:lightsail:Distribution
    name: example
    properties:
      name: example-distribution
      bundleId: small_1_0
      origin:
        name: ${example.name}
        regionName: ${available.id}
      defaultCacheBehavior:
        behavior: cache
    options:
      dependsOn:
        - ${exampleLbAttachment}
variables:
  available:
    fn::invoke:
      function: aws:getAvailabilityZones
      arguments:
        state: available
        filters:
          - name: opt-in-status
            values:
              - opt-in-not-required

The origin references your load balancer by name and region. The dependsOn property ensures the instance is attached to the load balancer before creating the distribution. This prevents the distribution from pointing to a load balancer with no healthy backends.

Beyond these examples

These snippets focus on specific distribution-level features: origin configuration for buckets, instances, and load balancers, and cache behavior and TTL settings. They’re intentionally minimal rather than full CDN deployments.

The examples require pre-existing infrastructure such as Lightsail buckets, instances, or load balancers, and static IP attachments or load balancer attachments. They focus on configuring the distribution rather than provisioning the origin resources.

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

  • Custom SSL/TLS certificates (certificateName)
  • Per-path cache behaviors (cacheBehaviors)
  • IP address type selection (ipAddressType)
  • Distribution enable/disable controls (isEnabled)

These omissions are intentional: the goal is to illustrate how each distribution feature is wired, not provide drop-in CDN modules. See the Lightsail Distribution resource reference for all available configuration options.

Let's create AWS Lightsail CDN Distributions

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Origins & Dependencies
What can I use as an origin for my Lightsail distribution?
You can use three origin types: Lightsail Bucket, Lightsail Instance, or Lightsail Load Balancer. Configure the origin property with the resource’s name and regionName.
Why do I need dependsOn when using an Instance or Load Balancer origin?
Instance origins require dependsOn for the StaticIpAttachment, and Load Balancer origins require dependsOn for the LbAttachment. This ensures attachments complete before the distribution is created.
How do I get my distribution's domain name?
The domainName is a computed output property that becomes available after the distribution is created.
Caching Configuration
What's the difference between cacheBehaviorSettings and cacheBehaviors?
cacheBehaviorSettings applies globally to all paths, while cacheBehaviors allows per-path overrides for specific URL patterns.
What are the TTL values in cacheBehaviorSettings?
TTL values are specified in seconds: defaultTtl (e.g., 86400 for 1 day), maximumTtl (e.g., 31536000 for 1 year), and minimumTtl (e.g., 0 for no minimum).
What's the difference between allowedHttpMethods and cachedHttpMethods?
allowedHttpMethods specifies which HTTP methods the distribution accepts (e.g., GET, HEAD, OPTIONS, PUT, PATCH, POST, DELETE), while cachedHttpMethods specifies which methods have their responses cached (typically GET, HEAD).
Network & Security
What's the default IP address type for distributions?
Distributions default to dualstack (IPv4 and IPv6). You can set ipAddressType to ipv4 for IPv4-only.
How do I attach a custom SSL/TLS certificate to my distribution?
Set the certificateName property to the name of your SSL/TLS certificate.
General Configuration
Is my distribution enabled by default?
Yes, distributions are enabled by default (isEnabled: true). Set isEnabled to false to create a disabled distribution.

Using a different cloud?

Explore networking guides for other cloud providers: