Controller Options¶
This document describes all configuration options for the controller binary. For Helm chart values, see Helm Values.
Command Line Flags¶
| Flag | Environment Variable | Default | Description |
|---|---|---|---|
--controller-name | CF_CONTROLLER_NAME | cf.k8s.lex.la/tunnel-controller | Controller name matching GatewayClass spec.controllerName |
--cluster-domain | CF_CLUSTER_DOMAIN | (auto-detect) | Kubernetes cluster domain |
--metrics-addr | CF_METRICS_ADDR | :8080 | Metrics endpoint address |
--health-addr | CF_HEALTH_ADDR | :8081 | Health probe endpoint address |
--log-level | CF_LOG_LEVEL | info | Log level (debug, info, warn, error) |
--log-format | CF_LOG_FORMAT | json | Log format (json, text) |
--leader-elect | CF_LEADER_ELECT | false | Enable leader election for HA |
--leader-election-namespace | CF_LEADER_ELECTION_NAMESPACE | Namespace for leader election lease | |
--leader-election-name | CF_LEADER_ELECTION_NAME | cloudflare-tunnel-gateway-controller-leader | Leader election lease name |
--proxy-endpoints | CF_PROXY_ENDPOINTS | Proxy config API endpoints for L7 proxy sync (required in v3) | |
--proxy-auth-token | CF_PROXY_AUTH_TOKEN | Bearer token for proxy config push authentication, as a direct value. For callers outside the chart only -- the chart always sets --proxy-auth-secret-ref instead, for both the bring-your-own and generated cases. Overridden by --proxy-auth-secret-ref when both are set | |
--proxy-auth-secret-ref | CF_PROXY_AUTH_SECRET_REF | Shared-proxy config-API auth-token Secret to resolve, in <namespace>/<name> form, and use for the controller's own push auth. Resolved directly via the API, not a pod-level secretKeyRef (which the controller creating its own dependency would deadlock on). The single mechanism the chart uses for both the bring-your-own and generated cases; combine with --proxy-auth-secret-generate | |
--proxy-auth-secret-key | CF_PROXY_AUTH_SECRET_KEY | auth-token | Data key to read within the --proxy-auth-secret-ref Secret |
--proxy-auth-secret-generate | CF_PROXY_AUTH_SECRET_GENERATE | false | Allow creating the --proxy-auth-secret-ref Secret (with a random token) when it does not exist. false is the bring-your-own contract: the Secret must already exist. The chart sets this true only when proxy.authTokenSecretRef.name is empty |
--proxy-token-secret | CF_PROXY_TOKEN_SECRET | Tunnel-token Secret to watch in <namespace>/<name> form; the controller rolls the proxy Deployment when the Secret data changes. Empty disables the watcher | |
--proxy-deployment-label | CF_PROXY_DEPLOYMENT_LABEL | app.kubernetes.io/component=proxy | Label selector (key=value) identifying the proxy Deployment(s) to roll on tunnel-token change |
--tunnel-protocol | CF_TUNNEL_PROTOCOL | auto | Edge transport protocol (auto, http2, quic); used to warn when GRPCRoutes are present on an explicit quic tunnel |
--tracing-enabled | CF_TRACING_ENABLED | false | Enable OpenTelemetry distributed tracing |
--tracing-endpoint | CF_TRACING_ENDPOINT | OTLP/gRPC collector endpoint (defers to OTEL_EXPORTER_OTLP_ENDPOINT when empty) | |
--tracing-sample-rate | CF_TRACING_SAMPLE_RATE | 1.0 | Head-sampling probability in [0,1] |
--proxy-image | CF_PROXY_IMAGE | Container image for per-Gateway rendered proxy Deployments (per-Gateway isolation). When BOTH this flag and the GatewayConfig.spec.image override are empty, rendering is skipped and the Gateway surfaces a Warning Event instead of a data plane. The Helm chart always sets it; manual installs should pass it (or set spec.image per GatewayConfig) | |
--hostname-ownership-enforce | CF_HOSTNAME_OWNERSHIP_ENFORCE | false | Controller-side hostname-ownership layer: routes whose hostnames fall outside their namespace's allowed-suffix label are rejected (HostnameNotPermitted) and never programmed. Independent of the chart's ValidatingAdmissionPolicy — see Multi-Tenancy |
--hostname-ownership-label-key | CF_HOSTNAME_OWNERSHIP_LABEL_KEY | cf.k8s.lex.la/hostname-suffix | Namespace label carrying the tenant's allowed hostname suffix |
--hostname-ownership-namespace-selector | CF_HOSTNAME_OWNERSHIP_NAMESPACE_SELECTOR | Label selector (kubectl syntax) scoping which namespaces are policed; empty polices every namespace (fail-closed) | |
--monitoring-namespace-selector | CF_MONITORING_NAMESPACE_SELECTOR | Label selector (kubectl syntax) for namespaces additionally allowed to reach a per-Gateway proxy's config-API/metrics port in the rendered NetworkPolicy; empty admits the controller namespace only — see Per-Gateway Isolation | |
--render-network-policy | CF_RENDER_NETWORK_POLICY | true | Render the per-Gateway config-API NetworkPolicy. Wired from the chart's proxy.networkPolicy.enabled. Set false on strict CNIs where node-sourced kubelet probes are blocked by the policy's namespaceSelector ingress rule; a previously-rendered policy is then deleted |
For full distributed-tracing setup, see Distributed Tracing.
Environment Variables¶
All flags can be set via environment variables with the CF_ prefix. Dashes in flag names are replaced with underscores.
Examples:
--controller-name→CF_CONTROLLER_NAME--log-level→CF_LOG_LEVEL--leader-elect→CF_LEADER_ELECT
Cluster Domain Auto-Detection¶
The controller automatically detects the Kubernetes cluster domain from /etc/resolv.conf search domains. If detection fails, it falls back to cluster.local.
To override auto-detection:
Or via environment variable:
Leader Election¶
For high availability deployments with multiple controller replicas, enable leader election:
Only the leader processes events; other replicas remain on standby for automatic failover.
flowchart LR
subgraph Replicas
R1[Replica 1<br/>Leader]
R2[Replica 2<br/>Standby]
R3[Replica 3<br/>Standby]
end
LEASE[(Lease)]
R1 -->|holds| LEASE
R2 -.->|watches| LEASE
R3 -.->|watches| LEASE Logging¶
Log Levels¶
| Level | Description |
|---|---|
debug | Detailed debugging information |
info | Normal operational messages |
warn | Warning conditions |
error | Error conditions |
Log Formats¶
| Format | Description |
|---|---|
json | Structured JSON logs (recommended for production) |
text | Human-readable text logs (useful for development) |
Example JSON log:
{
"level": "info",
"ts": "2024-01-15T10:30:00Z",
"msg": "HTTPRoute reconciled",
"route": "default/my-app",
"hostnames": ["app.example.com"]
}
Health Endpoints¶
The controller exposes health endpoints for Kubernetes probes:
| Endpoint | Port | Description |
|---|---|---|
/healthz | 8081 | Liveness probe |
/readyz | 8081 | Readiness probe |
These are used by Kubernetes to determine pod health:
Metrics Endpoint¶
The controller exposes Prometheus metrics on the metrics port:
| Endpoint | Port | Description |
|---|---|---|
/metrics | 8080 | Prometheus metrics |
See Metrics & Alerting for available metrics.