The aws:lightsail/distribution:Distribution resource, part of the Pulumi AWS provider, defines a Lightsail CDN distribution that caches content at edge locations and routes requests to origin resources. This guide focuses on three capabilities: bucket origins for static content, instance origins for dynamic applications, and load balancer origins for high-availability services.
Distributions reference existing Lightsail resources and may require static IP or load balancer attachments to be in place first. The examples are intentionally small. Combine them with your own SSL certificates, custom cache behaviors, and monitoring.
Cache content from a Lightsail bucket
Most CDN deployments start by caching static assets stored in object storage, reducing latency for users worldwide.
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 or passed through to the origin. The cacheBehaviorSettings block controls TTL values, HTTP methods, and what headers or cookies get forwarded to the origin. Here, GET and HEAD requests are cached for up to 24 hours (defaultTtl: 86400 seconds).
Distribute traffic from a Lightsail instance
Applications running on instances can serve dynamic content through a CDN to improve global performance.
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 property references the instance by name and region. The dependsOn ensures the static IP attachment completes before creating the distribution, since distributions require instances to have stable IP addresses. Without the static IP, the distribution cannot route traffic reliably.
Front a load balancer with edge caching
Load-balanced applications benefit from CDN caching to reduce backend 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 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 property references the load balancer by name and region. The dependsOn ensures instances are attached to the load balancer before creating the distribution. This ordering prevents the distribution from routing to an empty load balancer.
Beyond these examples
These snippets focus on specific distribution-level features: origin configuration (buckets, instances, load balancers) and cache behavior and TTL settings. They’re intentionally minimal rather than full CDN deployments.
The examples reference 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 FREEFrequently Asked Questions
Origins & Dependencies
origin property with the resource’s name and regionName.dependsOn to ensure StaticIpAttachment (for instances) or LbAttachment (for load balancers) finishes first.bundleId, name, origin (with name and regionName), and defaultCacheBehavior. The region property is also required but defaults to the provider’s region.Caching Behavior
allowedHttpMethods defines which HTTP methods the distribution accepts (e.g., GET, POST, DELETE), while cachedHttpMethods specifies which methods have their responses cached (typically just GET and HEAD).cacheBehaviorSettings with defaultTtl, maximumTtl, and minimumTtl (all in seconds). For example, the schema shows defaultTtl: 86400 (1 day), maximumTtl: 31536000 (1 year), and minimumTtl: 0.forwardedCookies), headers (forwardedHeaders), and query strings (forwardedQueryStrings). Each has an option field to specify behavior (e.g., “none”, “default”, true/false).Network & Access
ipAddressType: "dualstack" (supporting both IPv4 and IPv6) and isEnabled: true (distribution is active). You can override these by setting ipAddressType: "ipv4" or isEnabled: false.certificateName property to the name of your Lightsail certificate. This is optional; distributions work without custom certificates.Using a different cloud?
Explore networking guides for other cloud providers: