· Jakub · Platform Engineering · 7 min read
Secure Private EKS Access and SSO-Protected Frontends with Cloudflare Tunnel on EC2
How I replaced VPN infrastructure with a Cloudflare Tunnel to provide both zero-trust VPC access via WARP and SSO-gated frontend application delivery through a private ALB — all on real public domains.

Introduction
The client ran a private EKS cluster with no public API endpoint and multiple frontend applications served behind a private ALB. Their engineering team needed daily access to the cluster and internal services, while stakeholders needed access to staging frontends on real public subdomains — without exposing the underlying infrastructure to the internet.
I proposed a Cloudflare Tunnel running on a single EC2 instance that serves two distinct purposes: WARP routing for engineers to access private VPC resources (EKS API, databases, internal services), and application-level ingress that exposes frontend apps on public subdomains like staging.jakops.cloud or admin.jakops.cloud with SSO enforcement at Cloudflare’s edge. The result: zero-trust access for both infrastructure operations and web application delivery, with no inbound ports exposed anywhere.
System Architecture
The architecture serves two access patterns through a single tunnel instance:
Pattern 1 — WARP Routing (Engineer Access): Engineers enrolled in the Cloudflare Zero Trust organization connect via the WARP client. Traffic for the VPC CIDR is routed through the tunnel, giving direct access to the EKS API server, RDS instances, and any private service.
Pattern 2 — Application Access (Frontend Delivery): Frontend applications running in EKS are mapped to public subdomains (e.g., app.jakops.cloud, dashboard.jakops.cloud) via Cloudflare Access applications. When a user hits one of these subdomains, Cloudflare enforces SSO authentication before forwarding the request through the tunnel to the private ALB, which routes to the appropriate frontend pods. The domains are real, publicly resolvable — but the traffic never touches a public load balancer.
Core components:
- EC2 instance (t4g.micro, ARM64, RHEL 9) in a private subnet
- Cloudflare Tunnel with WARP routing for full VPC access
- Cloudflare Access Applications mapping public subdomains to the private ALB
- Private ALB fronting frontend services in EKS
- AWS Secrets Manager storing the tunnel token
- Security group with restrictive egress-only rules
- IAM role scoped to Secrets Manager and SSM
- EKS cluster security group rule allowing ingress from the tunnel
The instance has no public IP, no SSH access, and no inbound ports. Management happens exclusively through SSM Session Manager.
Runtime & Scaling Behavior
Engineer Access (WARP)
On boot, the instance retrieves the tunnel token from Secrets Manager and starts the cloudflared daemon as a systemd service. The daemon establishes outbound QUIC connections (ports 7844–7845) to Cloudflare’s edge.
Once connected, any team member with the WARP client enrolled in the Zero Trust organization can route traffic to private VPC addresses. kubectl commands hit the EKS API server directly. Database connections reach RDS instances. Internal services respond as if the engineer were on the network.
Frontend Access (SSO-Gated Public Subdomains)
For frontend applications, Cloudflare Access acts as an identity-aware reverse proxy on real public domains. A user navigates to app.jakops.cloud in their browser. Cloudflare intercepts the request, presents an SSO login page (backed by the configured identity provider), and only after successful authentication forwards the request through the tunnel to the private ALB. The ALB routes to the appropriate target group — frontend pods running in EKS.
From the user’s perspective, they’re visiting a normal website on a normal domain. From an infrastructure perspective, there’s no public ALB, no public ingress controller, no WAF to manage, and no certificates to rotate on the AWS side. Cloudflare handles TLS termination, DNS, and identity verification at the edge.
This pattern works well for staging environments, admin panels, internal dashboards, and any frontend that should be accessible by URL but restricted to authorized users.
Request Flow (Frontend)
User → app.jakops.cloud (Cloudflare Edge, TLS + SSO)
→ Cloudflare Tunnel (encrypted QUIC)
→ EC2 cloudflared instance (private subnet)
→ Private ALB (VPC)
→ EKS frontend podsThe security group enforces the network topology:
egress {
from_port = 7844
to_port = 7845
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow outbound QUIC for Cloudflare Tunnel"
}All VPC-internal traffic flows between the tunnel instance and the ALB/EKS resources:
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.vpc_cidr_block]
description = "Allow all traffic from VPC for WARP routing"
}Key Engineering Decisions
Dual-purpose tunnel. Rather than deploying separate infrastructure for engineer access and application delivery, a single tunnel instance handles both. WARP routing covers L3/L4 access; Cloudflare Access applications cover L7 ingress with identity enforcement on public subdomains. One instance, two access patterns.
Public domains, private infrastructure. The subdomains are real, publicly resolvable DNS records pointing to Cloudflare’s edge — but there’s nothing public on the AWS side. No public ALB, no internet-facing security groups, no exposed endpoints. The entire AWS footprint remains invisible.
SSO at the edge, not the application. Authentication happens before traffic ever reaches the VPC. Frontend applications don’t need to implement their own auth gates — Cloudflare Access enforces identity policies before a single byte reaches the private ALB. This is particularly valuable for staging environments and admin panels where applications may not have production-grade auth flows.
Private ALB, not public. The ALB has no internet-facing listener. All external traffic arrives exclusively through the tunnel. This eliminates DDoS surface, certificate management burden, and public security group rules entirely.
ARM over x86. The t4g.micro is ~20% cheaper than equivalent t3 instances. cloudflared is a lightweight Go binary — it doesn’t need compute headroom even when proxying frontend traffic.
Hardcoded AMI over dynamic lookup. I kept a data source for latest RHEL 9 ARM available but pinned the AMI explicitly. This prevents unexpected instance replacements during terraform apply when Red Hat publishes a new image.
Single instance, no ASG. The tunnel reconnects automatically on the Cloudflare side. If the instance dies, a simple terraform apply recreates it. For staging frontends and developer access, sub-minute recovery wasn’t required.
IMDSv2 required. Blocks SSRF-based credential theft from the instance metadata endpoint.
Dedicated system user. The cloudflared process runs as a non-login user with no shell, minimizing blast radius.
KMS-encrypted EBS. The root volume is encrypted with a customer-managed KMS key, ensuring data at rest is protected even if the volume is somehow detached or snapshotted.
Trade-offs
Optimized for: cost, simplicity, zero-trust posture, unified access control, operational minimalism, elimination of public attack surface.
Sacrificed: high availability (single instance), self-healing (no ASG), automated AMI rotation, independent scaling of frontend proxy vs. WARP routing, centralized logging (logs stay on-instance via journald).
For a team accessing staging and internal environments with frontend apps that don’t require five-nines availability, this trade-off is correct. Production-facing frontend delivery with strict SLA requirements would warrant an ASG with health checks and potentially dedicated tunnel instances per access pattern.
Cost & Operational Impact
Monthly cost breakdown:
| Component | Cost |
|---|---|
| t4g.micro (on-demand) | ~$6.13 |
| 8GB GP3 EBS | ~$0.80 |
| Secrets Manager secret | ~$0.40 |
| Total | ~$7.33/month |
This replaced both a managed VPN solution and the need for a public ALB with associated WAF, certificate management, public DNS configuration, and ACM certificate validation. The previous setup cost the client over $75/month with significantly more operational overhead.
The tunnel requires zero maintenance for frontend delivery — no certificate rotation (Cloudflare handles TLS for the public subdomains), no DNS propagation delays, no WAF rule management, no public security group auditing. Adding a new frontend subdomain is a Cloudflare dashboard configuration change, not an infrastructure deployment.
Conclusion
A Cloudflare Tunnel on a minimal EC2 instance solves two problems simultaneously: zero-trust network access for engineers via WARP, and SSO-protected frontend delivery on real public subdomains for stakeholders. By keeping the ALB private and routing all external traffic through Cloudflare’s edge, the entire AWS infrastructure remains invisible to the internet while applications are served on proper public domains with identity enforcement.
The key insight: combining WARP routing with Cloudflare Access applications on a single tunnel gives you both L3 infrastructure access and L7 application delivery with SSO — on real domains, with zero public infrastructure, for under $8/month.
Need Help With Cloudflare Tunnel or Zero-Trust Infrastructure?
If you’d rather skip the trial-and-error and get a production-ready zero-trust setup from day one — that’s exactly what I do at jakops.cloud.
I can help you with:
- Deploying Cloudflare Tunnel on EC2 with WARP routing for private VPC access
- Configuring Cloudflare Access applications with SSO enforcement on real public subdomains
- Setting up private ALB ingress for EKS frontends with no public attack surface
- Writing Terraform modules for tunnel EC2 instances with IMDSv2, KMS encryption, and SSM access
- Replacing VPN infrastructure with zero-trust alternatives at a fraction of the cost




