Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/concepts/gateways.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ If you disable [public IP](#public-ip) (e.g. to make the gateway private) or if
`dstack` supports the following certificate types:

* `lets-encrypt` (default) — Automatic certificates via [Let's Encrypt](https://letsencrypt.org/). Requires a [public IP](#public-ip).
* `acm` — Certificates managed by [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/). AWS-only. TLS is terminated at the load balancer, not at the gateway.
* `acm` — Certificates managed by [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/). AWS-only. TLS is terminated at the load balancer, not at the gateway, and HTTP requests are redirected to HTTPS by the ALB.
Requires a VPC with at least two subnets in different availability zones to provision a load balancer. If `public_ip: False`, subnets must be private and have a route to NAT gateway.
* `null` — No certificate. Services will use HTTP.

Expand Down
27 changes: 25 additions & 2 deletions src/dstack/_internal/core/backends/aws/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class AWSGatewayBackendData(CoreModel):
lb_arn: str
tg_arn: str
listener_arn: str
http_listener_arn: Optional[str] = None # None for old gateways


class AWSVolumeBackendData(CoreModel):
Expand Down Expand Up @@ -594,7 +595,7 @@ def create_gateway(
)
logger.debug("Registered ALB target for gateway %s", configuration.instance_name)

logger.debug("Creating ALB Listener for gateway %s...", configuration.instance_name)
logger.debug("Creating HTTPS ALB listener for gateway %s...", configuration.instance_name)
response = elb_client.create_listener(
LoadBalancerArn=lb_arn,
Protocol="HTTPS",
Expand All @@ -611,7 +612,26 @@ def create_gateway(
],
)
listener_arn = response["Listeners"][0]["ListenerArn"]
logger.debug("Created ALB Listener for gateway %s", configuration.instance_name)
logger.debug("Created HTTPS ALB listener for gateway %s", configuration.instance_name)

logger.debug("Creating HTTP ALB listener for gateway %s...", configuration.instance_name)
response = elb_client.create_listener(
LoadBalancerArn=lb_arn,
Protocol="HTTP",
Port=80,
DefaultActions=[
{
"Type": "redirect",
"RedirectConfig": {
"Protocol": "HTTPS",
"Port": "443",
"StatusCode": "HTTP_301",
},
}
],
)
http_listener_arn = response["Listeners"][0]["ListenerArn"]
logger.debug("Created HTTP ALB listener for gateway %s", configuration.instance_name)

ip_address = _get_instance_ip(instance, configuration.public_ip)
return GatewayProvisioningData(
Expand All @@ -623,6 +643,7 @@ def create_gateway(
lb_arn=lb_arn,
tg_arn=tg_arn,
listener_arn=listener_arn,
http_listener_arn=http_listener_arn,
).json(),
)

Expand Down Expand Up @@ -659,6 +680,8 @@ def terminate_gateway(
elb_client = self.session.client("elbv2", region_name=configuration.region)

logger.debug("Deleting ALB resources for gateway %s...", configuration.instance_name)
if backend_data_parsed.http_listener_arn is not None:
elb_client.delete_listener(ListenerArn=backend_data_parsed.http_listener_arn)
elb_client.delete_listener(ListenerArn=backend_data_parsed.listener_arn)
elb_client.delete_target_group(TargetGroupArn=backend_data_parsed.tg_arn)
elb_client.delete_load_balancer(LoadBalancerArn=backend_data_parsed.lb_arn)
Expand Down
Loading