Skip to content

Feat/helm charts#182

Draft
dsbibby wants to merge 14 commits into
adyanth:mainfrom
dsbibby:feat/helm-charts
Draft

Feat/helm charts#182
dsbibby wants to merge 14 commits into
adyanth:mainfrom
dsbibby:feat/helm-charts

Conversation

@dsbibby
Copy link
Copy Markdown

@dsbibby dsbibby commented May 12, 2026

Summary

Adds two Helm charts to charts/, published to oci://ghcr.io/adyanth/charts via an updated release workflow.

charts/cloudflare-operator — installs the operator: Deployment, CRDs, RBAC, ServiceAccount, webhook Service, and a self-signed cert-manager Certificate for the conversion webhook.

charts/cloudflare-tunnels — renders ClusterTunnel CRs from a values list. Shared settings (protocol, edgeIpVersion, rolling strategy, anti-affinity) are defined once in defaults and can be overridden per tunnel. Individual entries only need name and domain.


Design decisions

CRDs in /crds — copied verbatim from config/crd/bases/, not symlinked. make helm-sync-crds (hooked into make manifests) keeps them in sync automatically.

appVersion from Makefilemake helm-sync-versions (also hooked into make manifests) writes VERSION into Chart.yaml, keeping a single source of truth.

Structured values over raw argsprotocol and edgeIpVersion are first-class values; the template builds the correct cloudflared argument sequence and validates both fields at render time.

QUIC as default protocol — QUIC reconnects in under a second via 0-RTT; HTTP/2 TCP can take 10–20s due to SYN-retry backoff during Cloudflare edge rotation. Operators who need HTTP/2 can set defaults.protocol: http2.

Webhook TLS — the operator crashes without TLS certs at startup. The chart provisions a self-signed cert-manager Issuer + Certificate by default (webhook.certManager.enabled: true), which can be disabled to supply the Secret manually.

OCI publishingrelease.yml gains a publish-charts job using helm push. Chart version comes from Chart.yaml on branch pushes and from the git tag on releases.


On RBAC maintenance

The previous Helm PR (#143) stalled partly on this. The RBAC in templates/rbac.yaml is derived directly from the existing config/rbac/ manifests that controller-gen already maintains — it isn't hand-authored from scratch. Re-syncing is needed when roles change, but that's the same review that config/rbac/ already gets on any controller change.

The kubebuilder helm-v1-alpha plugin (noted by @adyanth) could replace this long-term via full autogeneration, but it's currently alpha and requires a more significant build toolchain change. This chart gets something working now with an explicit, reviewable sync point.


Testing

Both charts have been deployed to a live 3-node k3s cluster via Flux HelmReleases backed by the OCI registry, running stably across multiple domains with pod anti-affinity and QUIC connections verified in cloudflared logs.


Notes

  • make manifests currently fails to build controller-gen under Go 1.24 due to a bug in golang.org/x/tools@v0.24.0 — fixed by bumping CONTROLLER_TOOLS_VERSION to v0.21.0.
  • charts/cloudflare-operator/crds/ have been updated as a result of the above but contain only cosmetic changes.

dsbibby added 11 commits May 7, 2026 10:10
Adds two Helm charts to complement the existing kustomize-based installation:

- charts/cloudflare-operator: installs the controller Deployment, CRDs,
  RBAC (manager, leader-election, metrics-auth, metrics-reader roles), and
  ServiceAccount. CRDs are copied verbatim from config/crd/bases/ to avoid
  the symlink packaging failure that blocked the earlier WIP PR (adyanth#143).

- charts/cloudflare-tunnels: renders ClusterTunnel CRs from a values list,
  centralising shared settings (protocol, rolling strategy, cloudflared args
  including --edge-ip-version auto, hard pod anti-affinity) so individual
  tunnel definitions only supply name and domain.

Also adds:
- make helm-sync-crds target (hooked into the existing manifests target) to
  keep chart CRDs in sync with controller-gen output, preventing drift.
- helm/chart-releaser-action job in release.yml to publish both charts to
  GitHub Pages on version tags.

Closes adyanth#108
Add publish-charts job to the CI workflow that packages both Helm charts
and pushes them to oci://ghcr.io/<owner>/charts using helm push.

Uses github.repository_owner so the registry path is correct regardless
of which fork the workflow runs in — no hardcoded paths.

Triggers on pushes to main and feat/helm-charts (for branch testing),
and on version tags alongside the existing chart-releaser job.
Replace the freeform args list in cloudflare-tunnels/values.yaml with
explicit protocol and edgeIpVersion fields. The template now constructs
the cloudflared args internally from these values, ensuring correctness
and preventing invalid combinations.

Adds fail validations for both fields:
- protocol: must be one of http2, h2mux, auto
- edgeIpVersion: must be one of auto, 4, 6
- replicas: must be >= 1

Updates getting-started.md with a full Helm installation section covering
both the cloudflare-operator and cloudflare-tunnels charts, including a
values reference table.
…om tag

Update all actions to their current latest releases:
- actions/checkout: v4 -> v6.0.2
- azure/setup-helm: v4 -> v5.0.0
- docker/login-action: v1/v3 -> v4.1.0
- docker/metadata-action: v3 -> v6.0.0
- docker/setup-qemu-action: v1 -> v4.0.0
- docker/setup-buildx-action: v1 -> v4.0.0
- docker/build-push-action: v2 -> v7.1.0
- peter-evans/dockerhub-description: v3 -> v5.0.0
- helm/chart-releaser-action: v1.6.0 -> v1.7.0
- actions/setup-go: already on v5 (current latest major)

Add 'Derive chart version' step to publish-charts job: when triggered
by a version tag (e.g. v0.14.0) the tag is used as both --version and
--app-version in helm package, ensuring the OCI chart version matches
the operator release. On branch pushes the Chart.yaml version is used
as-is.
@dsbibby dsbibby mentioned this pull request May 12, 2026
labels: ${{ steps.meta.outputs.labels }}
- name: Docker Hub Description
if: github.event.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
uses: peter-evans/dockerhub-description@v3
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appreciate you didn't set this up but it would produce meaningful security guarantees if we switch to a hash for actions

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done ✔️ I'll disclaim though that there's a lot of them so I let Claude do these updates for me. All seems to be working though.

Comment thread .github/workflows/release.yml Outdated
Comment thread Makefile
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

.PHONY: helm-sync-crds
helm-sync-crds: ## Sync CRD YAMLs from config/crd/bases into charts/cloudflare-operator/crds/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possibly I missed it, but we'll want some kind of CI time check to ensure that this has been run. something that runs the makefile command, and asserts that doing so doesn't produce a diff

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a step to the lint workflow that should do this and give a helpful message if it fails

@@ -0,0 +1,111 @@
---
apiVersion: apiextensions.k8s.io/v1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something just occurred to me, could these be symlinks?

@cyclingwithelephants
Copy link
Copy Markdown
Contributor

one comment occurred to me and no idea if it works. LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants