Prod Cloudflare tunnel routing
This runbook uses the cloudflare and games/blaster repos together. It configures the Cloudflare tunnel for blaster.muppit.au, defines Origin CA resources in Kubernetes, and shows how to restart cloudflared without surprises.
Blaster GitOps series
- Blaster GitOps summary
- Blaster repo and branches
- Dockerfile & GitLab CI
- Clerk authentication & user setup
- Google OAuth for Clerk
- Blaster prep for automation
- Dev app k8s manifests
- Dev flux sources & Kustomizations
- Dev image automation
- Dev SOPS & age
- Dev verification & troubleshooting
- Dev full runbook
- Prod overview
- Prod app k8s manifests and deployment
- Prod Flux GitOps and image automation
- Prod Cloudflare, Origin CA and tunnel routing - you are here
- Prod full runbook
- Post development branches
1. Cloudflare repo changes
1.1 Pull latest
cd ~/Projects/cloudflare
git pull
Already up to date.
1.2 Update cloudflared ConfigMap
---
# k8s/prod/40-configmap-cloudflared.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cloudflared
namespace: cloudflare
data:
config.yaml: |
tunnel: 3183eb59-d124-483f-90a1-3409e41b1d69
credentials-file: /etc/cloudflared/creds/credentials.json
metrics: 0.0.0.0:2000
ingress:
# (optional) Block WP admin to public
- hostname: muppit.au
path: ^/(wp-login\.php|wp-admin(?:/.*)?$)
service: http_status:403
# Send to ingress-nginx over TLS and verify with Origin CA
- hostname: muppit.au
service: https://ingress-nginx-controller.ingress-nginx.svc.cluster.local:443
originRequest:
originServerName: muppit.au
caPool: /etc/cloudflared/certs/origin_ca.pem
- hostname: blaster.muppit.au
service: https://ingress-nginx-controller.ingress-nginx.svc.cluster.local:443
originRequest:
originServerName: blaster.muppit.au
caPool: /etc/cloudflared/certs/origin_ca.pem
# Catch-all
- service: http_status:404
1.3 Commit and push
git add .
git commit -m "Added blaster to configmap"
[main 4d03596] Added blaster to configmap
1 file changed, 6 insertions(+)
git push
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 24 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 459 bytes | 459.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
To https://gitlab.reids.net.au/muppit-apps/cloudflare.git
ff25bd4..4d03596 main -> main
1.4 Reconcile Origin CA issuer components
flux reconcile source git origin-ca-issuer-upstream -n flux-system && flux reconcile kustomization origin-ca-issuer-crds -n flux-system && flux reconcile kustomization origin-ca-issuer-rbac -n flux-system && flux reconcile kustomization origin-ca-issuer-controller -n flux-system
► annotating GitRepository origin-ca-issuer-upstream in flux-system namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ fetched revision v0.12.1@sha1:86d908eda6c91815557c04b7f3e871ca4f0a0cce
► annotating Kustomization origin-ca-issuer-crds in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ applied revision v0.12.1@sha1:86d908eda6c91815557c04b7f3e871ca4f0a0cce
► annotating Kustomization origin-ca-issuer-rbac in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ applied revision v0.12.1@sha1:86d908eda6c91815557c04b7f3e871ca4f0a0cce
► annotating Kustomization origin-ca-issuer-controller in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ applied revision v0.12.1@sha1:86d908eda6c91815557c04b7f3e871ca4f0a0cce
2. Cloudflare DNS and tunnel
2.1 Initial reachability test (expected 404)
404 response is expected before blaster.muppit.au is added into the tunnel config.
curl -k https://blaster.muppit.au/ -I
HTTP/2 404
2.2 Obtain tunnel ID
The existing tunnel ID is required for the DNS CNAME target in Cloudflare.
cloudflared tunnel list
You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>`
ID NAME CREATED CONNECTIONS
2.3 Cloudflare dashboard – DNS entry
- Log in to
https://dash.cloudflare.com - Add a new DNS entry:
- Type:
CNAME - Name:
blaster - Target:
TUNNELID.cfargotunnel.com - Proxy status:
Proxied
- Type:
3. Origin CA resources in Kubernetes
These resources live in the games/blaster repo under k8s/prod/ and are applied by Flux. They allow cloudflared to validate the origin using an Origin CA certificate.
3.1 Secret – Cloudflare API token copy
Reuse the same Cloudflare API token value as your cloudflare app repo; this copy must live in
blasterso OriginIssuer can issue a cert in this namespace.
# k8s/prod/70-secret-cfapi-token.enc.yaml
apiVersion: v1
kind: Secret
metadata:
name: cfapi-token
namespace: blaster
type: Opaque
stringData:
key: PASTE_YOUR_API_TOKEN
3.2 OriginIssuer
# k8s/prod/80-originissuer.yaml
apiVersion: cert-manager.k8s.cloudflare.com/v1
kind: OriginIssuer
metadata:
name: cf-origin
namespace: blaster
spec:
requestType: OriginECC
auth:
tokenRef:
name: cfapi-token
key: key
3.3 Certificate for blaster.muppit.au
Issue an Origin CA certificate in the same namespace as your Ingress (
blaster).
# k8s/prod/90-certificate-blaster.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: blaster-muppit-au-origin
namespace: blaster
spec:
secretName: blaster-muppit-au-tls
dnsNames:
- blaster.muppit.au
issuerRef:
group: cert-manager.k8s.cloudflare.com
kind: OriginIssuer
name: cf-origin
4. Restarting cloudflared after config change
4.1 Why a restart is required
- The ConfigMap was changed in Git.
- Flux reconciled and updated the ConfigMap object in the cluster.
- The
cloudflaredPod keeps running with the old config in memory. - Kubernetes does not automatically restart Pods when only a ConfigMap changes.
cloudflareddoes not re-read its config unless restarted (or run with a special watch mode).
Result:
- Flux has synced Git → cluster.
- The Deployment spec did not change.
- No new ReplicaSet is created – the old Pod keeps the old config until you roll it.
4.2 Rollout restart
Manual restart:
kubectl -n cloudflare rollout restart deploy/cloudflared
kubectl -n cloudflare rollout status deploy/cloudflared
deployment.apps/cloudflared restarted
Waiting for deployment "cloudflared" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "cloudflared" rollout to finish: 1 old replicas are pending termination...
deployment "cloudflared" successfully rolled out
5. Reachability test – success
curl -k https://blaster.muppit.au/ -I
HTTP/2 200
6. Verification checklist
-
cloudflaredConfigMap in cluster matches Git. - DNS
CNAMEblaster→<TUNNELID>.cfargotunnel.comis present and proxied. -
Secret/cfapi-tokenpresent inblasternamespace and encrypted in Git. -
OriginIssuer/cf-originandCertificate/blaster-muppit-au-originareReady=True. -
blaster-muppit-au-tlsSecret present and referenced byblaster-ingress. -
curl -k https://blaster.muppit.au/ -IreturnsHTTP/2 200.