Configure AWS Load Balancer Listeners

The aws:lb/listener:Listener resource, part of the Pulumi AWS provider, defines how a load balancer accepts and routes incoming traffic: its protocol, port, TLS configuration, and default actions. This guide focuses on four capabilities: HTTPS termination and forwarding, HTTP-to-HTTPS redirects, Cognito and OIDC authentication, and mutual TLS client verification.

Listeners attach to existing load balancers and reference target groups, TLS certificates, and authentication providers. The examples are intentionally small. Combine them with your own load balancers, target groups, and security infrastructure.

Route HTTPS traffic to a target group

Most deployments accept HTTPS traffic on port 443 and forward requests to backend instances in a target group.

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

const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndTargetGroup = new aws.lb.TargetGroup("front_end", {});
const frontEndListener = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEnd.arn,
    port: 443,
    protocol: "HTTPS",
    sslPolicy: "ELBSecurityPolicy-2016-08",
    certificateArn: "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    defaultActions: [{
        type: "forward",
        targetGroupArn: frontEndTargetGroup.arn,
    }],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.LoadBalancer("front_end")
front_end_target_group = aws.lb.TargetGroup("front_end")
front_end_listener = aws.lb.Listener("front_end",
    load_balancer_arn=front_end.arn,
    port=443,
    protocol="HTTPS",
    ssl_policy="ELBSecurityPolicy-2016-08",
    certificate_arn="arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    default_actions=[{
        "type": "forward",
        "target_group_arn": front_end_target_group.arn,
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		frontEndTargetGroup, err := lb.NewTargetGroup(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: frontEnd.Arn,
			Port:            pulumi.Int(443),
			Protocol:        pulumi.String("HTTPS"),
			SslPolicy:       pulumi.String("ELBSecurityPolicy-2016-08"),
			CertificateArn:  pulumi.String("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type:           pulumi.String("forward"),
					TargetGroupArn: frontEndTargetGroup.Arn,
				},
			},
		})
		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 frontEnd = new Aws.LB.LoadBalancer("front_end");

    var frontEndTargetGroup = new Aws.LB.TargetGroup("front_end");

    var frontEndListener = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEnd.Arn,
        Port = 443,
        Protocol = "HTTPS",
        SslPolicy = "ELBSecurityPolicy-2016-08",
        CertificateArn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                TargetGroupArn = frontEndTargetGroup.Arn,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
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 frontEnd = new LoadBalancer("frontEnd");

        var frontEndTargetGroup = new TargetGroup("frontEndTargetGroup");

        var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
            .loadBalancerArn(frontEnd.arn())
            .port(443)
            .protocol("HTTPS")
            .sslPolicy("ELBSecurityPolicy-2016-08")
            .certificateArn("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4")
            .defaultActions(ListenerDefaultActionArgs.builder()
                .type("forward")
                .targetGroupArn(frontEndTargetGroup.arn())
                .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:LoadBalancer
    name: front_end
  frontEndTargetGroup:
    type: aws:lb:TargetGroup
    name: front_end
  frontEndListener:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEnd.arn}
      port: '443'
      protocol: HTTPS
      sslPolicy: ELBSecurityPolicy-2016-08
      certificateArn: arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4
      defaultActions:
        - type: forward
          targetGroupArn: ${frontEndTargetGroup.arn}

The listener terminates TLS using the certificateArn and sslPolicy, then forwards decrypted requests to the target group. The protocol and port define what clients connect to; the defaultActions array specifies where traffic goes. The sslPolicy controls which TLS versions and cipher suites are allowed.

Redirect HTTP to HTTPS automatically

Applications requiring encryption redirect HTTP traffic to HTTPS rather than serving unencrypted content.

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

const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndListener = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEnd.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [{
        type: "redirect",
        redirect: {
            port: "443",
            protocol: "HTTPS",
            statusCode: "HTTP_301",
        },
    }],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.LoadBalancer("front_end")
front_end_listener = aws.lb.Listener("front_end",
    load_balancer_arn=front_end.arn,
    port=80,
    protocol="HTTP",
    default_actions=[{
        "type": "redirect",
        "redirect": {
            "port": "443",
            "protocol": "HTTPS",
            "status_code": "HTTP_301",
        },
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: frontEnd.Arn,
			Port:            pulumi.Int(80),
			Protocol:        pulumi.String("HTTP"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type: pulumi.String("redirect"),
					Redirect: &lb.ListenerDefaultActionRedirectArgs{
						Port:       pulumi.String("443"),
						Protocol:   pulumi.String("HTTPS"),
						StatusCode: pulumi.String("HTTP_301"),
					},
				},
			},
		})
		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 frontEnd = new Aws.LB.LoadBalancer("front_end");

    var frontEndListener = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEnd.Arn,
        Port = 80,
        Protocol = "HTTP",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "redirect",
                Redirect = new Aws.LB.Inputs.ListenerDefaultActionRedirectArgs
                {
                    Port = "443",
                    Protocol = "HTTPS",
                    StatusCode = "HTTP_301",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionRedirectArgs;
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 frontEnd = new LoadBalancer("frontEnd");

        var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
            .loadBalancerArn(frontEnd.arn())
            .port(80)
            .protocol("HTTP")
            .defaultActions(ListenerDefaultActionArgs.builder()
                .type("redirect")
                .redirect(ListenerDefaultActionRedirectArgs.builder()
                    .port("443")
                    .protocol("HTTPS")
                    .statusCode("HTTP_301")
                    .build())
                .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:LoadBalancer
    name: front_end
  frontEndListener:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEnd.arn}
      port: '80'
      protocol: HTTP
      defaultActions:
        - type: redirect
          redirect:
            port: '443'
            protocol: HTTPS
            statusCode: HTTP_301

The redirect action sends a 301 permanent redirect to clients, instructing them to retry the request over HTTPS on port 443. The statusCode determines whether browsers cache the redirect (HTTP_301) or treat it as temporary (HTTP_302).

Split traffic between target groups with weights

Blue-green deployments and canary releases route traffic to multiple target groups with configurable weights.

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

const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndBlue = new aws.lb.TargetGroup("front_end_blue", {});
const frontEndGreen = new aws.lb.TargetGroup("front_end_green", {});
const frontEndListener = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEnd.arn,
    port: 443,
    protocol: "HTTPS",
    sslPolicy: "ELBSecurityPolicy-2016-08",
    certificateArn: "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    defaultActions: [{
        type: "forward",
        forward: {
            targetGroups: [
                {
                    arn: frontEndBlue.arn,
                    weight: 100,
                },
                {
                    arn: frontEndGreen.arn,
                    weight: 0,
                },
            ],
        },
    }],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.LoadBalancer("front_end")
front_end_blue = aws.lb.TargetGroup("front_end_blue")
front_end_green = aws.lb.TargetGroup("front_end_green")
front_end_listener = aws.lb.Listener("front_end",
    load_balancer_arn=front_end.arn,
    port=443,
    protocol="HTTPS",
    ssl_policy="ELBSecurityPolicy-2016-08",
    certificate_arn="arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    default_actions=[{
        "type": "forward",
        "forward": {
            "target_groups": [
                {
                    "arn": front_end_blue.arn,
                    "weight": 100,
                },
                {
                    "arn": front_end_green.arn,
                    "weight": 0,
                },
            ],
        },
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		frontEndBlue, err := lb.NewTargetGroup(ctx, "front_end_blue", nil)
		if err != nil {
			return err
		}
		frontEndGreen, err := lb.NewTargetGroup(ctx, "front_end_green", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: frontEnd.Arn,
			Port:            pulumi.Int(443),
			Protocol:        pulumi.String("HTTPS"),
			SslPolicy:       pulumi.String("ELBSecurityPolicy-2016-08"),
			CertificateArn:  pulumi.String("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type: pulumi.String("forward"),
					Forward: &lb.ListenerDefaultActionForwardArgs{
						TargetGroups: lb.ListenerDefaultActionForwardTargetGroupArray{
							&lb.ListenerDefaultActionForwardTargetGroupArgs{
								Arn:    frontEndBlue.Arn,
								Weight: pulumi.Int(100),
							},
							&lb.ListenerDefaultActionForwardTargetGroupArgs{
								Arn:    frontEndGreen.Arn,
								Weight: pulumi.Int(0),
							},
						},
					},
				},
			},
		})
		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 frontEnd = new Aws.LB.LoadBalancer("front_end");

    var frontEndBlue = new Aws.LB.TargetGroup("front_end_blue");

    var frontEndGreen = new Aws.LB.TargetGroup("front_end_green");

    var frontEndListener = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEnd.Arn,
        Port = 443,
        Protocol = "HTTPS",
        SslPolicy = "ELBSecurityPolicy-2016-08",
        CertificateArn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                Forward = new Aws.LB.Inputs.ListenerDefaultActionForwardArgs
                {
                    TargetGroups = new[]
                    {
                        new Aws.LB.Inputs.ListenerDefaultActionForwardTargetGroupArgs
                        {
                            Arn = frontEndBlue.Arn,
                            Weight = 100,
                        },
                        new Aws.LB.Inputs.ListenerDefaultActionForwardTargetGroupArgs
                        {
                            Arn = frontEndGreen.Arn,
                            Weight = 0,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionForwardArgs;
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 frontEnd = new LoadBalancer("frontEnd");

        var frontEndBlue = new TargetGroup("frontEndBlue");

        var frontEndGreen = new TargetGroup("frontEndGreen");

        var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
            .loadBalancerArn(frontEnd.arn())
            .port(443)
            .protocol("HTTPS")
            .sslPolicy("ELBSecurityPolicy-2016-08")
            .certificateArn("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4")
            .defaultActions(ListenerDefaultActionArgs.builder()
                .type("forward")
                .forward(ListenerDefaultActionForwardArgs.builder()
                    .targetGroups(                    
                        ListenerDefaultActionForwardTargetGroupArgs.builder()
                            .arn(frontEndBlue.arn())
                            .weight(100)
                            .build(),
                        ListenerDefaultActionForwardTargetGroupArgs.builder()
                            .arn(frontEndGreen.arn())
                            .weight(0)
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:LoadBalancer
    name: front_end
  frontEndBlue:
    type: aws:lb:TargetGroup
    name: front_end_blue
  frontEndGreen:
    type: aws:lb:TargetGroup
    name: front_end_green
  frontEndListener:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEnd.arn}
      port: '443'
      protocol: HTTPS
      sslPolicy: ELBSecurityPolicy-2016-08
      certificateArn: arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4
      defaultActions:
        - type: forward
          forward:
            targetGroups:
              - arn: ${frontEndBlue.arn}
                weight: 100
              - arn: ${frontEndGreen.arn}
                weight: 0

The forward block with targetGroups distributes traffic proportionally based on weight values. Here, 100% goes to the blue target group while green receives 0%, allowing you to shift traffic gradually by adjusting weights. This extends basic forwarding with traffic splitting for controlled rollouts.

Authenticate users with Cognito before forwarding

Applications needing user authentication can delegate to Cognito User Pools, verifying identity before routing requests.

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

const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndTargetGroup = new aws.lb.TargetGroup("front_end", {});
const pool = new aws.cognito.UserPool("pool", {});
const client = new aws.cognito.UserPoolClient("client", {});
const domain = new aws.cognito.UserPoolDomain("domain", {});
const frontEndListener = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEnd.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [
        {
            type: "authenticate-cognito",
            authenticateCognito: {
                userPoolArn: pool.arn,
                userPoolClientId: client.id,
                userPoolDomain: domain.domain,
            },
        },
        {
            type: "forward",
            targetGroupArn: frontEndTargetGroup.arn,
        },
    ],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.LoadBalancer("front_end")
front_end_target_group = aws.lb.TargetGroup("front_end")
pool = aws.cognito.UserPool("pool")
client = aws.cognito.UserPoolClient("client")
domain = aws.cognito.UserPoolDomain("domain")
front_end_listener = aws.lb.Listener("front_end",
    load_balancer_arn=front_end.arn,
    port=80,
    protocol="HTTP",
    default_actions=[
        {
            "type": "authenticate-cognito",
            "authenticate_cognito": {
                "user_pool_arn": pool.arn,
                "user_pool_client_id": client.id,
                "user_pool_domain": domain.domain,
            },
        },
        {
            "type": "forward",
            "target_group_arn": front_end_target_group.arn,
        },
    ])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		frontEndTargetGroup, err := lb.NewTargetGroup(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		pool, err := cognito.NewUserPool(ctx, "pool", nil)
		if err != nil {
			return err
		}
		client, err := cognito.NewUserPoolClient(ctx, "client", nil)
		if err != nil {
			return err
		}
		domain, err := cognito.NewUserPoolDomain(ctx, "domain", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: frontEnd.Arn,
			Port:            pulumi.Int(80),
			Protocol:        pulumi.String("HTTP"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type: pulumi.String("authenticate-cognito"),
					AuthenticateCognito: &lb.ListenerDefaultActionAuthenticateCognitoArgs{
						UserPoolArn:      pool.Arn,
						UserPoolClientId: client.ID(),
						UserPoolDomain:   domain.Domain,
					},
				},
				&lb.ListenerDefaultActionArgs{
					Type:           pulumi.String("forward"),
					TargetGroupArn: frontEndTargetGroup.Arn,
				},
			},
		})
		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 frontEnd = new Aws.LB.LoadBalancer("front_end");

    var frontEndTargetGroup = new Aws.LB.TargetGroup("front_end");

    var pool = new Aws.Cognito.UserPool("pool");

    var client = new Aws.Cognito.UserPoolClient("client");

    var domain = new Aws.Cognito.UserPoolDomain("domain");

    var frontEndListener = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEnd.Arn,
        Port = 80,
        Protocol = "HTTP",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "authenticate-cognito",
                AuthenticateCognito = new Aws.LB.Inputs.ListenerDefaultActionAuthenticateCognitoArgs
                {
                    UserPoolArn = pool.Arn,
                    UserPoolClientId = client.Id,
                    UserPoolDomain = domain.Domain,
                },
            },
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                TargetGroupArn = frontEndTargetGroup.Arn,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.cognito.UserPool;
import com.pulumi.aws.cognito.UserPoolClient;
import com.pulumi.aws.cognito.UserPoolDomain;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionAuthenticateCognitoArgs;
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 frontEnd = new LoadBalancer("frontEnd");

        var frontEndTargetGroup = new TargetGroup("frontEndTargetGroup");

        var pool = new UserPool("pool");

        var client = new UserPoolClient("client");

        var domain = new UserPoolDomain("domain");

        var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
            .loadBalancerArn(frontEnd.arn())
            .port(80)
            .protocol("HTTP")
            .defaultActions(            
                ListenerDefaultActionArgs.builder()
                    .type("authenticate-cognito")
                    .authenticateCognito(ListenerDefaultActionAuthenticateCognitoArgs.builder()
                        .userPoolArn(pool.arn())
                        .userPoolClientId(client.id())
                        .userPoolDomain(domain.domain())
                        .build())
                    .build(),
                ListenerDefaultActionArgs.builder()
                    .type("forward")
                    .targetGroupArn(frontEndTargetGroup.arn())
                    .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:LoadBalancer
    name: front_end
  frontEndTargetGroup:
    type: aws:lb:TargetGroup
    name: front_end
  pool:
    type: aws:cognito:UserPool
  client:
    type: aws:cognito:UserPoolClient
  domain:
    type: aws:cognito:UserPoolDomain
  frontEndListener:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEnd.arn}
      port: '80'
      protocol: HTTP
      defaultActions:
        - type: authenticate-cognito
          authenticateCognito:
            userPoolArn: ${pool.arn}
            userPoolClientId: ${client.id}
            userPoolDomain: ${domain.domain}
        - type: forward
          targetGroupArn: ${frontEndTargetGroup.arn}

The authenticateCognito action intercepts requests, redirects unauthenticated users to Cognito’s login page, and validates tokens before forwarding to the target group. The userPoolArn, userPoolClientId, and userPoolDomain connect the listener to your Cognito configuration. Multiple actions execute in order: authenticate first, then forward.

Authenticate with external OIDC providers

Teams using identity providers like Okta or Auth0 configure OIDC authentication at the load balancer layer.

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

const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndTargetGroup = new aws.lb.TargetGroup("front_end", {});
const frontEndListener = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEnd.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [
        {
            type: "authenticate-oidc",
            authenticateOidc: {
                authorizationEndpoint: "https://example.com/authorization_endpoint",
                clientId: "client_id",
                clientSecret: "client_secret",
                issuer: "https://example.com",
                tokenEndpoint: "https://example.com/token_endpoint",
                userInfoEndpoint: "https://example.com/user_info_endpoint",
            },
        },
        {
            type: "forward",
            targetGroupArn: frontEndTargetGroup.arn,
        },
    ],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.LoadBalancer("front_end")
front_end_target_group = aws.lb.TargetGroup("front_end")
front_end_listener = aws.lb.Listener("front_end",
    load_balancer_arn=front_end.arn,
    port=80,
    protocol="HTTP",
    default_actions=[
        {
            "type": "authenticate-oidc",
            "authenticate_oidc": {
                "authorization_endpoint": "https://example.com/authorization_endpoint",
                "client_id": "client_id",
                "client_secret": "client_secret",
                "issuer": "https://example.com",
                "token_endpoint": "https://example.com/token_endpoint",
                "user_info_endpoint": "https://example.com/user_info_endpoint",
            },
        },
        {
            "type": "forward",
            "target_group_arn": front_end_target_group.arn,
        },
    ])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		frontEndTargetGroup, err := lb.NewTargetGroup(ctx, "front_end", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: frontEnd.Arn,
			Port:            pulumi.Int(80),
			Protocol:        pulumi.String("HTTP"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type: pulumi.String("authenticate-oidc"),
					AuthenticateOidc: &lb.ListenerDefaultActionAuthenticateOidcArgs{
						AuthorizationEndpoint: pulumi.String("https://example.com/authorization_endpoint"),
						ClientId:              pulumi.String("client_id"),
						ClientSecret:          pulumi.String("client_secret"),
						Issuer:                pulumi.String("https://example.com"),
						TokenEndpoint:         pulumi.String("https://example.com/token_endpoint"),
						UserInfoEndpoint:      pulumi.String("https://example.com/user_info_endpoint"),
					},
				},
				&lb.ListenerDefaultActionArgs{
					Type:           pulumi.String("forward"),
					TargetGroupArn: frontEndTargetGroup.Arn,
				},
			},
		})
		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 frontEnd = new Aws.LB.LoadBalancer("front_end");

    var frontEndTargetGroup = new Aws.LB.TargetGroup("front_end");

    var frontEndListener = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEnd.Arn,
        Port = 80,
        Protocol = "HTTP",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "authenticate-oidc",
                AuthenticateOidc = new Aws.LB.Inputs.ListenerDefaultActionAuthenticateOidcArgs
                {
                    AuthorizationEndpoint = "https://example.com/authorization_endpoint",
                    ClientId = "client_id",
                    ClientSecret = "client_secret",
                    Issuer = "https://example.com",
                    TokenEndpoint = "https://example.com/token_endpoint",
                    UserInfoEndpoint = "https://example.com/user_info_endpoint",
                },
            },
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                TargetGroupArn = frontEndTargetGroup.Arn,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionAuthenticateOidcArgs;
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 frontEnd = new LoadBalancer("frontEnd");

        var frontEndTargetGroup = new TargetGroup("frontEndTargetGroup");

        var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
            .loadBalancerArn(frontEnd.arn())
            .port(80)
            .protocol("HTTP")
            .defaultActions(            
                ListenerDefaultActionArgs.builder()
                    .type("authenticate-oidc")
                    .authenticateOidc(ListenerDefaultActionAuthenticateOidcArgs.builder()
                        .authorizationEndpoint("https://example.com/authorization_endpoint")
                        .clientId("client_id")
                        .clientSecret("client_secret")
                        .issuer("https://example.com")
                        .tokenEndpoint("https://example.com/token_endpoint")
                        .userInfoEndpoint("https://example.com/user_info_endpoint")
                        .build())
                    .build(),
                ListenerDefaultActionArgs.builder()
                    .type("forward")
                    .targetGroupArn(frontEndTargetGroup.arn())
                    .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:LoadBalancer
    name: front_end
  frontEndTargetGroup:
    type: aws:lb:TargetGroup
    name: front_end
  frontEndListener:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEnd.arn}
      port: '80'
      protocol: HTTP
      defaultActions:
        - type: authenticate-oidc
          authenticateOidc:
            authorizationEndpoint: https://example.com/authorization_endpoint
            clientId: client_id
            clientSecret: client_secret
            issuer: https://example.com
            tokenEndpoint: https://example.com/token_endpoint
            userInfoEndpoint: https://example.com/user_info_endpoint
        - type: forward
          targetGroupArn: ${frontEndTargetGroup.arn}

The authenticateOidc action redirects users to your identity provider’s authorizationEndpoint, exchanges authorization codes at the tokenEndpoint, and validates user information from the userInfoEndpoint. The clientId and clientSecret authenticate the load balancer to your identity provider.

Configure TLS termination for Network Load Balancers

Network Load Balancers handling TLS traffic use ALPN policies to negotiate application protocols with clients.

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

const frontEnd = new aws.lb.Listener("front_end", {
    loadBalancerArn: frontEndAwsLb.arn,
    port: 443,
    protocol: "TLS",
    sslPolicy: "ELBSecurityPolicy-2016-08",
    certificateArn: "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    alpnPolicy: "HTTP2Preferred",
    defaultActions: [{
        type: "forward",
        targetGroupArn: frontEndAwsLbTargetGroup.arn,
    }],
});
import pulumi
import pulumi_aws as aws

front_end = aws.lb.Listener("front_end",
    load_balancer_arn=front_end_aws_lb["arn"],
    port=443,
    protocol="TLS",
    ssl_policy="ELBSecurityPolicy-2016-08",
    certificate_arn="arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
    alpn_policy="HTTP2Preferred",
    default_actions=[{
        "type": "forward",
        "target_group_arn": front_end_aws_lb_target_group["arn"],
    }])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
			LoadBalancerArn: pulumi.Any(frontEndAwsLb.Arn),
			Port:            pulumi.Int(443),
			Protocol:        pulumi.String("TLS"),
			SslPolicy:       pulumi.String("ELBSecurityPolicy-2016-08"),
			CertificateArn:  pulumi.String("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"),
			AlpnPolicy:      pulumi.String("HTTP2Preferred"),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					Type:           pulumi.String("forward"),
					TargetGroupArn: pulumi.Any(frontEndAwsLbTargetGroup.Arn),
				},
			},
		})
		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 frontEnd = new Aws.LB.Listener("front_end", new()
    {
        LoadBalancerArn = frontEndAwsLb.Arn,
        Port = 443,
        Protocol = "TLS",
        SslPolicy = "ELBSecurityPolicy-2016-08",
        CertificateArn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
        AlpnPolicy = "HTTP2Preferred",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                TargetGroupArn = frontEndAwsLbTargetGroup.Arn,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
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 frontEnd = new Listener("frontEnd", ListenerArgs.builder()
            .loadBalancerArn(frontEndAwsLb.arn())
            .port(443)
            .protocol("TLS")
            .sslPolicy("ELBSecurityPolicy-2016-08")
            .certificateArn("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4")
            .alpnPolicy("HTTP2Preferred")
            .defaultActions(ListenerDefaultActionArgs.builder()
                .type("forward")
                .targetGroupArn(frontEndAwsLbTargetGroup.arn())
                .build())
            .build());

    }
}
resources:
  frontEnd:
    type: aws:lb:Listener
    name: front_end
    properties:
      loadBalancerArn: ${frontEndAwsLb.arn}
      port: '443'
      protocol: TLS
      sslPolicy: ELBSecurityPolicy-2016-08
      certificateArn: arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4
      alpnPolicy: HTTP2Preferred
      defaultActions:
        - type: forward
          targetGroupArn: ${frontEndAwsLbTargetGroup.arn}

The alpnPolicy property controls Application-Layer Protocol Negotiation, allowing clients and servers to agree on HTTP/2, HTTP/1.1, or other protocols during the TLS handshake. HTTP2Preferred attempts HTTP/2 but falls back to HTTP/1.1 if the client doesn’t support it.

Require client certificates with mutual TLS

Applications requiring strong client authentication use mutual TLS to verify client certificates against a trust store.

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

const example = new aws.lb.LoadBalancer("example", {loadBalancerType: "application"});
const exampleTargetGroup = new aws.lb.TargetGroup("example", {});
const exampleListener = new aws.lb.Listener("example", {
    loadBalancerArn: example.id,
    defaultActions: [{
        targetGroupArn: exampleTargetGroup.id,
        type: "forward",
    }],
    mutualAuthentication: {
        mode: "verify",
        trustStoreArn: "...",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.lb.LoadBalancer("example", load_balancer_type="application")
example_target_group = aws.lb.TargetGroup("example")
example_listener = aws.lb.Listener("example",
    load_balancer_arn=example.id,
    default_actions=[{
        "target_group_arn": example_target_group.id,
        "type": "forward",
    }],
    mutual_authentication={
        "mode": "verify",
        "trust_store_arn": "...",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := lb.NewLoadBalancer(ctx, "example", &lb.LoadBalancerArgs{
			LoadBalancerType: pulumi.String("application"),
		})
		if err != nil {
			return err
		}
		exampleTargetGroup, err := lb.NewTargetGroup(ctx, "example", nil)
		if err != nil {
			return err
		}
		_, err = lb.NewListener(ctx, "example", &lb.ListenerArgs{
			LoadBalancerArn: example.ID(),
			DefaultActions: lb.ListenerDefaultActionArray{
				&lb.ListenerDefaultActionArgs{
					TargetGroupArn: exampleTargetGroup.ID(),
					Type:           pulumi.String("forward"),
				},
			},
			MutualAuthentication: &lb.ListenerMutualAuthenticationArgs{
				Mode:          pulumi.String("verify"),
				TrustStoreArn: pulumi.String("..."),
			},
		})
		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.LB.LoadBalancer("example", new()
    {
        LoadBalancerType = "application",
    });

    var exampleTargetGroup = new Aws.LB.TargetGroup("example");

    var exampleListener = new Aws.LB.Listener("example", new()
    {
        LoadBalancerArn = example.Id,
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                TargetGroupArn = exampleTargetGroup.Id,
                Type = "forward",
            },
        },
        MutualAuthentication = new Aws.LB.Inputs.ListenerMutualAuthenticationArgs
        {
            Mode = "verify",
            TrustStoreArn = "...",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerMutualAuthenticationArgs;
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 LoadBalancer("example", LoadBalancerArgs.builder()
            .loadBalancerType("application")
            .build());

        var exampleTargetGroup = new TargetGroup("exampleTargetGroup");

        var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
            .loadBalancerArn(example.id())
            .defaultActions(ListenerDefaultActionArgs.builder()
                .targetGroupArn(exampleTargetGroup.id())
                .type("forward")
                .build())
            .mutualAuthentication(ListenerMutualAuthenticationArgs.builder()
                .mode("verify")
                .trustStoreArn("...")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:lb:LoadBalancer
    properties:
      loadBalancerType: application
  exampleTargetGroup:
    type: aws:lb:TargetGroup
    name: example
  exampleListener:
    type: aws:lb:Listener
    name: example
    properties:
      loadBalancerArn: ${example.id}
      defaultActions:
        - targetGroupArn: ${exampleTargetGroup.id}
          type: forward
      mutualAuthentication:
        mode: verify
        trustStoreArn: '...'

The mutualAuthentication block enables certificate-based client verification. The mode property set to “verify” requires valid client certificates; the trustStoreArn references a collection of trusted CA certificates. Clients without valid certificates matching the trust store are rejected.

Beyond these examples

These snippets focus on specific listener-level features: traffic routing and TLS termination, authentication (Cognito, OIDC, mutual TLS), and traffic splitting and redirects. They’re intentionally minimal rather than full load balancing solutions.

The examples reference pre-existing infrastructure such as load balancers and target groups, TLS certificates (IAM or ACM), Cognito User Pools or OIDC providers, and trust stores for mutual TLS. They focus on configuring the listener rather than provisioning everything around it.

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

  • Fixed-response and JWT validation actions
  • Gateway Load Balancer listeners (GENEVE protocol)
  • HTTP response header customization (CORS, security headers)
  • Custom routing header names (X-Amzn-Mtls-, X-Amzn-Tls-)
  • TCP idle timeout tuning for Network Load Balancers

These omissions are intentional: the goal is to illustrate how each listener feature is wired, not provide drop-in load balancing modules. See the Load Balancer Listener resource reference for all available configuration options.

Let's configure AWS Load Balancer Listeners

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Protocols & Load Balancer Types
What protocols can I use for my listener?
Protocol options depend on your load balancer type. Application Load Balancers support HTTP and HTTPS (default HTTP). Network Load Balancers support TCP, TLS, UDP, and TCP_UDP. Gateway Load Balancers don’t use the protocol property. Note that UDP and TCP_UDP cannot be used if dual-stack mode is enabled.
What's the difference between aws.alb.Listener and aws.lb.Listener?
They’re identical in functionality. aws.alb.Listener is an alias for aws.lb.Listener.
Why can't I set CORS or security headers on my listener?
Routing properties like CORS headers (routingHttpResponseAccessControlAllowOrigin, etc.) and security headers can only be set if protocol is HTTP or HTTPS on Application Load Balancers. They’re not supported for Network Load Balancers or Gateway Load Balancers.
Can I use a port with Gateway Load Balancers?
No, the port property is not valid for Gateway Load Balancer listeners.
HTTPS & TLS Configuration
How do I set up HTTPS on my listener?
Set protocol to HTTPS, provide a certificateArn (exactly one certificate is required), and specify an sslPolicy (defaults to ELBSecurityPolicy-2016-08 if not specified). For additional certificates, use the aws.lb.ListenerCertificate resource.
How do I configure mutual TLS authentication?
Use the mutualAuthentication property with mode set to verify and provide a trustStoreArn.
What's the ALPN policy for?
The alpnPolicy configures Application-Layer Protocol Negotiation for TLS listeners on Network Load Balancers. Valid values are HTTP1Only, HTTP2Only, HTTP2Optional, HTTP2Preferred, and None. It can only be set if protocol is TLS.
Actions & Routing
What action types can I use in defaultActions?
You can use forward (to target groups), redirect (e.g., HTTP to HTTPS), fixed-response (return static content), authenticate-cognito, authenticate-oidc, and jwt-validation. Multiple actions can be chained, such as authentication followed by forwarding.
How do I redirect HTTP traffic to HTTPS?
Use a redirect action with redirect.protocol set to HTTPS, redirect.port to 443, and redirect.statusCode to HTTP_301.
How do I implement blue/green deployments with weighted target groups?
Use a forward action with the forward.targetGroups array, specifying a weight for each target group. For example, set blue to weight 100 and green to weight 0, then gradually shift traffic by adjusting weights.
How do I add authentication to my listener?
Use multiple defaultActions with authentication first, then forwarding. For Cognito, use authenticate-cognito with userPoolArn, userPoolClientId, and userPoolDomain. For OIDC, use authenticate-oidc with authorizationEndpoint, clientId, clientSecret, issuer, tokenEndpoint, and userInfoEndpoint. For JWT, use jwt-validation with issuer and jwksEndpoint.
Timeouts & Performance
What are the TCP idle timeout limits?
The tcpIdleTimeoutSeconds property accepts values between 60 and 6000 seconds, with a default of 350. This can only be set if protocol is TCP on Network Load Balancers or with Gateway Load Balancers; it’s not supported for Application Load Balancers.
Common Issues & Gotchas
Why does my listener name show as 'Default' in the AWS Console?
When you specify a Name key in the tags map, AWS Console maps it to the “Name Tag” column in the Listener Rules table. Without a Name key, the value displays as “Default”.
Can I change the load balancer after creating a listener?
No, the loadBalancerArn property is immutable and cannot be changed after creation.

Using a different cloud?

Explore networking guides for other cloud providers: