Skip to main content
Choose the network, DNS, and access settings before following the ECS deployment guide. Add these inputs inside module "runlayer_infrastructure" in your root configuration. Merge examples with your existing values; do not declare the same input twice.

DNS and TLS

domain_name is the application hostname, such as ai.example.com. hosted_zone_name is the existing authoritative Route 53 zone, such as example.com; they are usually different. The deployment guide creates and validates *.example.com in ACM and creates the application DNS record in that zone. For DNS in another account, configure aws.route53 with the DNS account role and set cross_account_hosted_zone_id to that zone’s ID. Always pass both provider aliases to the module. The certificate must be in the workload account and ALB region. For DNS outside Route 53, supply an issued ssl_certificate_arn, leave enable_acm_dns_validation = false and create_dns_records = false, then create the application DNS record yourself using the module’s alb_dns_name output. Complete ACM validation with your DNS provider before deploying. Choose one certificate strategy:

Access choices

Private ALBs and PrivateLink do not remove outbound requirements. AWS VPC endpoints cover specific AWS APIs; WorkOS, AuthKit, catalog, and other external services still need outbound HTTPS. Review egress requirements.

Network Configuration

Use an existing VPC — all three variables must be provided together:
Private subnets need ECR/S3 endpoints or NAT for image pulls, plus NAT or another outbound HTTPS path for the external hosts in Self-Hosted Egress Requirements. Public subnets need an internet gateway for the ALB. Pass one public subnet per Availability Zone. Multiple subnets in the same AZ cause CreateLoadBalancer to fail with A load balancer cannot be attached to multiple subnets in the same Availability Zone. Subnet size can be small (for example /26) as long as the ALB has free IPs (~8+). Multiple ALBs may share the same public subnets. For topology options, see Networking.

Security Configuration

waf_webhook_allowlist_ipv4_cidrs and waf_webhook_allowlist_ipv6_cidrs default to []. They admit the specified request-origin IPs only for POST agent webhook invocation: /api/v1/agents/{uuid}/webhooks/{token} and the legacy /api/v1/assistants/{uuid}/webhooks/{token}, with an optional trailing slash. Paths are URL-decoded and normalized before matching. Webhook management routes and other methods receive no additional access; existing general allowlists and public-path exemptions still apply. Nonempty lists require waf_enable_ip_allowlisting = true; nonempty IPv6 lists also require enable_ipv6 = true. Invalid configurations fail planning; empty lists remain valid when either feature is disabled. General allowlist CIDRs remain required when allowlisting is enabled. Entries must be valid IPv4 CIDRs with prefix lengths 1–32 or IPv6 CIDRs with prefix lengths 1–128. The caller maintains these ranges; the module does not fetch vendor IP lists. Managed WAF rules and webhook authentication still apply. These lists cover invocation routes across agents, so review the admitted ranges, webhook credentials/signing, and execution identity with your security team before activation. ALB security groups must also permit the integration’s source IPs. When AgentCore is enabled, WAF IP allowlisting requires AgentCore VPC mode with PrivateLink. PUBLIC mode has no stable source IP to allowlist. Configure this before deployment:
The consumer subnets need the AgentCore egress paths. See AgentCore with WAF.

Slack and Microsoft Teams with an IP allowlist

Agents and the Runlayer Assistant answer in Slack and Teams only if those services can reach your deployment. Messages to Slack and Teams go out from Runlayer, but every mention, DM, reply and button click comes back in as an HTTPS POST from Slack or Microsoft to your public hostname. If the WAF IP allowlist, the ALB security group or a VPN-only ingress drops those requests, posting from Runlayer to Slack still works, but agents never reply and nothing shows up in Runlayer’s logs. Slack and Microsoft don’t publish a fixed list of source IPs for these requests, so allowlisting their IPs isn’t reliable. Exempt the paths instead:
  • Requests are still authenticated. Slack events and button clicks must carry a valid signature from the app’s signing secret, Teams messages a valid Bot Framework JWT, and the install and consent callbacks a signed link or one-time state. AWS managed WAF rules still apply.
  • Keep alb_allowed_cidrs (and alb_allowed_ipv6_cidrs) open to the internet, 0.0.0.0/0. The WAF exemption doesn’t open the security group.
  • With a private-only ALB, Slack and Teams can’t reach you at all. Use the dual ALB setup: the public ALB takes Slack and Teams traffic and the internal ALB serves your users.
  • If SLACK_APP_URL or MS_TEAMS_APP_URL points at a different host than APP_URL, that host must be publicly reachable instead.
Add only the integrations you use. To confirm the allowlist is the cause, mention an agent in Slack and open the web ACL’s sampled requests in the AWS WAF console: a blocked POST /api/v1/integrations/slack/... means the request never reached Runlayer.

Dual ALB Setup (Split-Horizon DNS)

Use case: public access (for example ChatGPT / external integrations) plus private network access on the same hostname via split-horizon DNS.
  • Public DNS → public ALB
  • Private DNS → internal ALB
  • ECS services register with both ALBs
  • WAF applies only to the public ALB

VPC Peering for Cross-VPC Connectivity

Security note: every peering connection must set peer_owner_id. The module validates ownership before accepting the connection.
VPC peering only applies when the module creates the VPC (not with existing_vpc_id). Expose Runlayer to consumer VPCs with an endpoint service:
Expose the child module output in your root configuration:
After apply, use terraform output -raw privatelink_service_name to create consumer interface endpoints. Accept endpoint requests when acceptance is required and configure consumer DNS, routing, and security groups.

Outbound private connections for Runlayer Deploy

Private connections let MCP servers you run on Runlayer Deploy reach systems on your private network, through AWS PrivateLink or a tunnel. Turn on the connection types you need:
Admins then create connections in Settings → Network Access, and each deployed server lists the ones it uses in runlayer.yaml. See private connections. Upgrade the module with the application: each module release selects the matching router, endpoint, and connector bundle. Enable tunnels only with a compatible application release. Upgrade the application before the module; on rollback, restore the previous module configuration before the application. See Updates. When runlayer_obs_otel_enabled = true, the module runs a private OTEL Collector for tunnel metrics and traces once the configured bearer secret or plaintext fallback resolves. An unseeded secret leaves the collector disabled; seeding it later enables the collector on the next apply without an input change. Schedule that apply as a tunnel interruption: it restarts tunnel routers and drops live sessions while clients reconnect. Routers and endpoints send OTLP/HTTP to its Cloud Map name on port 4318. The collector alone receives the observability bearer secret. Of the module-managed tunnel tasks, it is also the only one with public HTTPS egress; for telemetry, routers and endpoints can reach only the collector. Tunnel logs continue to use CloudWatch Logs. One 256 CPU / 512 MiB replica is the default capacity for up to 100 endpoint tasks, about 1,700 metric points/second, and 1,000 sampled spans/second. Set tunnel_otel_collector_desired_count = 2 for redundant capacity; changing only this value scales the collector without redeploying tunnel routers or endpoints. For an existing-VPC deployment, confirm the selected private subnets can reach otlp.obs.runlayer.com on HTTPS before upgrading. Schedule the upgrade for a tunnel interruption: adding the collector endpoints restarts the tunnel routers and drops live tunnel sessions while clients reconnect. Apply the new module, wait for the collector service to reach steady state, then wait for existing tunnel connections to reconcile to the current configuration. The deprecated tunnel_otel_proxy_security_group_id output remains valid during migration, so an existing Tailscale telemetry proxy can keep the same SG attached through the soak. Do not remove that proxy until collector metrics and traces are healthy. To roll back during soak, set runlayer_obs_otel_enabled = false, apply, and wait for tunnel connections to reconcile away their collector endpoints before restoring the previous module and application versions. This stops tunnel metrics and traces during rollback. Application observability logs keep exporting when runlayer_obs_otel_logs_enabled = true; tunnel logs remain in CloudWatch.

Optional tunnel connector metadata

Tunnel connectors send no optional metadata by default. To share their release version, add this environment setting to each connector container:
The setting accepts a comma-separated allowlist; version is currently the only supported value. Empty or unset disables reporting. Unknown values prevent startup. Version metadata travels inside the encrypted tunnel session and never changes access permissions or routing. Settings → Network access shows distinct reported connector versions. Multiple versions can appear during an upgrade. Disconnected sessions disappear after the next endpoint heartbeat; stale endpoint reports expire. Connector versions is hidden when no current versions are reported. This does not change connection status. The backend and UI can be upgraded before the tunnel bundle. Keep router and endpoint images on the current released bundle during that rollout; deploy the metadata-capable bundle separately after the backend is stable. Building or publishing a bundle does not deploy it. Finish upgrading the backend and workers before upgrading tunnel endpoints. Before rolling back to a backend release without metadata support, disable reporting and reconnect opted-in connectors. Wait for endpoint heartbeats to clear the stored version reports, then restore the previous endpoint bundle before rolling back the backend.

Private connection provisioning

ECS private connections reconcile asynchronously. Revision 2 is an internal private-connection configuration marker, separate from the ECS module release (for example, v33.1.0). This migration guidance applies to existing connections, not initial platform installation. Existing Deploy PrivateLink connections upgrade to connection configuration revision 2, adding connection-owned access security groups while retaining the existing endpoint and legacy security group. Wait for reconciliation before creating or redeploying an MCP deployment that uses the connection. Each deployment reserves one of its five security-group slots for its service. Tunnels use the remaining four slots first; PrivateLink connections fill any free slots in connection-name order. These connections use shared access groups, adding no endpoint rules per deployment. Reordering the connections in YAML does not change the allocation. PrivateLink connections beyond those four attachment slots use rules referencing the deployment’s service security group. Each overflow connection consumes one inbound rule per configured port on its endpoint security group, shared across all deployments using that connection through direct grants. With the default 60-rule quota and no other rules, a five-port overflow connection supports 12 deployments; existing rules, including legacy grants, reduce that capacity. Tunnels remain limited to four per deployment, including deployments that also use PrivateLink. The ECS module upgrade grants workers permission to inspect the applied VPC rule quota and prefix lists and describe ECS service deployments before rolling out updated workers. During the upgrade, a deployment selecting more than four connections can fail on an older worker. Retry it after the rollout finishes. Existing deployments with four or fewer private connections retain their shared access and do not need a redeploy. Redeploy when adding connections. Private-connection redeploys wait for ECS to finish rolling out replacement tasks before removing obsolete direct ingress grants. Endpoints and DNS names stay the same. The worker checks rule capacity before applying overflow grants, but concurrent AWS changes can still exhaust it. A capacity error identifies the affected group and required headroom. Reducing selected ports or overflow usage, removing unused grants, or increasing the AWS quota can free capacity. Before rolling back the application, reduce each affected deployment to four or fewer total private connections and redeploy it to restore shared security-group attachments. Then roll back the backend and worker images. An image rollback alone does not restore network rules. Removing access blocks new connections after rollout; existing tracked TCP connections may remain open. RUNLAYER_PRIVATE_CONNECTION_TERRAFORM_TIMEOUT_SECONDS defaults to 1800 and must be a positive finite number. Set it through additional_backend_env_vars to override the shared deadline for Terraform init, apply/destroy, and output commands. It does not change ordinary MCP deployment timeouts. Failed reconciliation preserves the connection’s prior usable state and is retried automatically up to 3 times, at least 15 minutes apart; if it still fails, contact Runlayer support to inspect and recover the upgrade before retrying the deployment.

Private CA certificates

To trust MCP servers or HTTPS proxies whose certificates use your private CA, pass the CA certificate bundle to the ECS module:
The file may concatenate multiple PEM certificate blocks. Include CA certificates only—never private keys. The module combines them with the public roots already in the Runlayer image and configures the backend, shared worker, and MCP execution worker to use the combined bundle. Frontend and migration tasks are intentionally unchanged because neither connects to customer MCP servers or customer-managed private-CA HTTPS endpoints. Changing the file and applying Terraform rolls the affected ECS tasks. The tasks start only after an init container validates and writes the bundle.