Architecture
The tunnel is a Layer 4 proxy over Cloudflare’s network. cloudflared runs on EC2 inside each environment’s VPC and opens an outbound session to the Cloudflare edge. Cloudflare terminates Worker traffic at the edge, and Hyperdrive’s pooled connections travel through the tunnel to the private Aurora endpoint. Nothing about this path requires an inbound port on AWS, a public database endpoint, or a VPN.
The whole stack is Terraform in adventive-platform-infra, split across three root modules: imagebuilder builds the AMI, cflared-asg runs the EC2 fleet per environment, and cloudflare-tunnels creates the Cloudflare tunnels and writes their credentials to Secrets Manager.
Connection path
Section titled “Connection path”Each environment’s tunnel is a named Cloudflare tunnel with config_src = local, meaning the host reads its ingress rules from /etc/cloudflared/config.yml. That config, plus the tunnel credentials, is rendered by the cloudflare-tunnels Terraform module and stored in AWS Secrets Manager at /adventive/cloudflared/<env>. The public tunnel hostnames are proxied CNAMEs to <tunnel-uuid>.cfargotunnel.com; cloudflared routes each to the service its ingress rule names (for the databases, tcp://<aurora-endpoint>:3306), with an implicit catch-all returning http_status:404.
As-built topology
Section titled “As-built topology”Dev and staging run a single cloudflared host in one Availability Zone; production runs two hosts across two Availability Zones. Each is kept alive by an Auto Scaling Group sized min = desired, max = desired + 1, so an instance refresh launches a replacement before terminating the old instance. Because cloudflared supports multiple connectors on one tunnel, that overlap keeps the tunnel up through a roll rather than dropping it, and in production the second host keeps serving even while the first is replaced.
Hosts sit in a public subnet today with security-group-only isolation (no inbound rule, no SSH; access is AWS Systems Manager Session Manager). Moving to private subnets with NAT egress is the documented pre-production hardening step, tracked separately, and does not change the tunnel design.
Self-heal
Section titled “Self-heal”The tunnel heals at two layers, and neither is a CloudWatch alarm loop. First, the cloudflared systemd unit is Restart=on-failure with a 5 second backoff, so a crashed daemon restarts in place. Second, the ASG’s EC2 health check replaces the whole instance if EC2 status checks fail; the replacement boots from the golden AMI, its bootstrap re-fetches credentials from Secrets Manager, and cloudflared reconnects. cloudflared’s own edge reconnect handles transient drops. There is no custom tunnel-aware health check or self-heal Lambda today; adding one is a future enhancement that the New Relic signal would feed.
Redundancy and the HA pathway
Section titled “Redundancy and the HA pathway”cloudflared natively supports multiple replicas sharing one tunnel, with Cloudflare load-balancing across the healthy connectors. Production runs two replicas across two AZs; dev and staging run a single host. Raising an environment’s replica count is a change to that environment’s entry in the cflared-asg environments map (its subnet_ids and desired_capacity, with min_healthy_percentage at 50 so a rolling refresh keeps one host serving), not a redesign: the AMI, the Secrets Manager credentials, and the ingress rules are unchanged. The trigger criteria for raising staging to two replicas are in the runbook.
Naming
Section titled “Naming”Every resource derives its name from the environment. The full table is in Reference.
| Resource | Pattern | Example |
|---|---|---|
| Cloudflare Tunnel | adv-cflared-{env} | adv-cflared-prd |
| EC2 launch template / ASG | adv-cflared-{env} | adv-cflared-prd |
| Runtime IAM role / instance profile | adv-cflared-runtime-{env} | adv-cflared-runtime-prd |
| AMI recipe / pipeline | adv-cflared-recipe / adv-cflared-pipeline | shared, env-agnostic |
| SSM AMI pointer | /adventive/cloudflared/ami-id-latest | shared |
| Secrets Manager tunnel secret | /adventive/cloudflared/{env} | one per environment |
| Secrets Manager New Relic key | /adventive/newrelic/license-key | shared |
| Instance tags | adv:env, adv:project=cloudflare-tunnel, adv:role=tunnel-runtime | on every instance |
Tunnel to Hyperdrive mapping
Section titled “Tunnel to Hyperdrive mapping”The tunnel is a generic TCP proxy: the same tunnel serves the Public API, the auth helper, and any future Worker needing Aurora reachback. Each environment’s ingress rules map its tunnel hostnames to the private Aurora endpoints; Hyperdrive resolves those hostnames. See the Hyperdrive standard for the Worker-side config and credential naming.