Skip to main content
  1. Projects/

Hardening Public Services with Cloudflare Zero Trust

Author
Richard Lintern
Building Kubernetes, GitOps and local-first AI systems.

Project date: 2026-08-28 Role: Architecture, implementation, validation and operation

A tunnel-based public access design with two cloudflared replicas, selective edge controls and CrowdSec-informed enforcement.

Environment and operating context
#

The Kubernetes cluster hosts both internal and externally reachable applications. Publishing every ingress directly would unnecessarily expose the origin and mix public routing with internal service discovery. The edge project created a selective path through Cloudflare while retaining Traefik and application authentication inside the cluster.

Objective
#

The design needed to avoid broad inbound application exposure, support public and protected services, preserve clear rollback, and integrate behavioural decisions without embedding Cloudflare credentials in source.

Operational value and risk reduction
#

Before: Kubernetes ingress and external publication risked being treated as the same thing, making exposure boundaries harder to reason about.

After: Two controlled tunnel replicas provide an outbound publication path, while CrowdSec decisions feed a dedicated Cloudflare bouncer.

Risk reduced: Selected public services do not require broad direct inbound origin exposure, and connector credentials are encrypted rather than embedded in manifests.

Architectural decisions and alternatives
#

Direct port forwarding
Simple, but exposes the origin path and increases dependence on perimeter firewall rules.
Single tunnel connector
Lower resource use, but introduces a connector-level single point of failure.
Separate tunnel routes directly to every service
Possible, but duplicates the routing responsibility already owned by Traefik.
Selected design
Two cloudflared replicas feed the existing Traefik ingress layer, with central CrowdSec decisions and encrypted credentials.

Technical challenges
#

A tunnel being connected does not prove that an application is healthy. DNS, edge policy, the tunnel, Traefik and the application can fail independently. The cluster also contains 23 ingress hostnames, but many are internal, so the exposure model had to distinguish ingress from Internet publication.

Proposed solution
#

Two cloudflared replicas run on separate k3s nodes and establish outbound tunnel connections. Automatic connector updates are disabled so image changes remain controlled; Prometheus-compatible metrics are exposed on port 2000. Public traffic passes through Cloudflare to Traefik, which then routes to the selected Kubernetes service.

Internet -> Cloudflare DNS and controls
         -> two cloudflared replicas
         -> Traefik ingress
         -> selected Kubernetes service

CrowdSec integration
#

CrowdSec was selected for its central LAPI model: multiple telemetry sources can contribute to one decision core, and enforcement components can consume those decisions. The Cloudflare Worker bouncer runs as a dedicated ready Deployment and receives Cloudflare and LAPI values through environment references backed by a SOPS-encrypted Secret.

The available evidence proves the central decision and enforcement architecture. It does not prove a deliberately validated fail-open scenario, so the case study does not make that stronger claim.

Implementation and controls
#

  • Two cloudflared replicas, both ready
  • Replicas distributed across nodes 1 and 4
  • Immutable cloudflared image digest
  • --no-autoupdate for controlled releases
  • Tunnel metrics available on port 2000
  • SOPS-encrypted tunnel token
  • SOPS-encrypted bouncer credentials
  • Traefik retained as internal ingress authority

Validation and measurable outcomes
#

Cloudflared replicas2 desired, 2 ready, 2 available
Replica restarts0 in evidence snapshot
Total Kubernetes ingress hosts23 internal and external
CrowdSec Cloudflare bouncer1 of 1 ready
Encrypted Cloudflare Secret manifests2

The 23-host count is deliberately not described as 23 public services. It records the size of the Kubernetes ingress estate and demonstrates why selective edge classification is necessary.

Outcome
#

Selected applications can use an encrypted outbound tunnel rather than general direct inbound exposure. The connector is redundant across nodes, its release is controlled through an immutable image, and behavioural decisions can be distributed through the CrowdSec core.

Skills demonstrated
#

  • Cloudflare Tunnel
  • Zero Trust edge design
  • Traefik integration
  • DNS and ingress classification
  • CrowdSec LAPI and bouncer architecture
  • Secret management
  • Availability and failure-boundary analysis

Lessons learned
#

A connected tunnel is only one link in the service path. Useful validation must separate connector health, edge policy, ingress routing and application health. Internal ingress records must also never be assumed to be publicly exposed.

Current status and next steps
#

Operational. Exact public-route and Cloudflare Access counts are intentionally omitted because the collected Kubernetes evidence cannot establish dashboard-side policy state.

Explore the implementation
#

Browse the networking runbooks or review the CrowdSec and Wazuh design.

How it was done
#

  1. Classified ingress routes. Kubernetes ingress names were reviewed as internal or candidates for external publication. The presence of an ingress was not treated as evidence that a service was Internet-accessible.
  2. Selected an outbound tunnel model. Cloudflare Tunnel was used so published services could be reached without creating a general inbound application path to the Kubernetes origin.
  3. Deployed redundant connectors. Cloudflared was deployed with two replicas scheduled on separate k3s nodes. Automatic updates were disabled, and the container image was controlled through an immutable digest.
  4. Connected the tunnel to Traefik. Cloudflare traffic reaches the existing Traefik ingress layer, preserving one internal routing authority rather than creating separate application routes inside the tunnel connector.
  5. Protected tunnel credentials. The connector token was stored in a SOPS-encrypted Kubernetes Secret and supplied at runtime rather than embedded in source.
  6. Enabled operational metrics. Cloudflared exposes metrics on port 2000 so tunnel connector state can be monitored independently from application state.
  7. Centralised behavioural decisions. CrowdSec LAPI provides one decision core that can accept connected telemetry sources and distribute decisions to enforcement components.
  8. Added the Cloudflare Worker bouncer. A dedicated bouncer Deployment consumes Cloudflare account, zone, API and CrowdSec values through protected environment references.
  9. Validated each path separately. Connector readiness, Kubernetes ingress, Traefik routing and application reachability were checked as separate layers so a healthy tunnel could not mask an unhealthy application.
  10. Recorded the evidence boundary. The cluster showed 23 internal and external ingress hostnames, two ready tunnel replicas and one ready bouncer. The article does not incorrectly present all 23 ingresses as public routes.

Evidence methodology
#

The figures in this case study were derived from reproducible source and runtime checks rather than estimates.

  1. Deployment replica, readiness, restart, image and placement evidence came from the Kubernetes API.
  2. Ingress hosts were counted from Kubernetes resources and deliberately classified only as internal-or-external ingress, not as public Cloudflare routes.
  3. Secret manifests were checked for SOPS markers, and bouncer configuration was inspected by variable name without exposing values.

Limitations and residual risks
#

  • Kubernetes evidence cannot prove the exact number of Cloudflare dashboard routes or Access policies.
  • A ready tunnel does not prove that the application behind it is healthy.
  • A tested CrowdSec fail-open scenario is not claimed.
  • Cloudflare remains an external dependency for published-service reachability.

Plain-English glossary
#

Cloudflare Tunnel
An outbound connector that carries selected traffic between Cloudflare and an internal service without a general inbound listener.
Traefik
The Kubernetes ingress controller that maps host and path rules to services.
Bouncer
A CrowdSec enforcement component that consumes central decisions and applies them to another platform.

Independent validation
#

This was a self-directed engineering project rather than a client engagement. Credibility is established through deployed configuration, source history, successful builds, operational measurements, restoration tests and repeatable validation rather than a client testimonial.