Running Cloudflare DDNS as a Kubernetes CronJob
This is how I run Cloudflare DDNS as a Kubernetes CronJob on my home cluster, with deployment managed by ArgoCD. This way, I can control how often it runs and trust ArgoCD to keep it healthy.
Create the Helm Chart
First, create a folder for cloudflare-ddns and scaffold a Helm chart:
# Create a directory
mkdir cloudflare-ddns
cd cloudflare-ddns
# Create a Helm chart
helm create cloudflare-ddns
cd cloudflare-ddns
Helm will generate a lot of boilerplate. You can clean it up by removing unnecessary files. Keep only:
Chart.yamlvalues.yaml- the
templatesfolder (but clear out its sample manifests — we’ll add our own).
Edit values.yaml
Open values.yaml and add your configuration:
cloudflare:
zoneID: "<your Cloudflare zone ID>"
recordName: "<your DNS A record name, e.g. katam.cc>"
ttl: <Integer: TTL in seconds (1 means 'auto'). Must be 60–86400 (or 30 for Enterprise).>
proxied: <Boolean: true or false — whether Cloudflare proxying is enabled.>
Note: Use quotation marks for strings.
Example:
cloudflare:
zoneID: "abc1234567890"
recordName: "katam.cc"
ttl: 300
proxied: true
Create the CronJob manifest
In templates/, create a file named cronjob.yaml and paste this:
apiVersion: batch/v1
kind: CronJob
metadata:
name: cloudflare-ddns-updater
spec:
schedule: "*/5 * * * *" # Runs every 5 minutes
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: cloudflare-ddns-updater
image: ghcr.io/prateekatam/cloudflare-ddns:1.0.4
env:
- name: CLOUDFLARE_ZONE_ID
value: "{{ .Values.cloudflare.zoneID }}"
- name: CLOUDFLARE_RECORD_NAME
value: "{{ .Values.cloudflare.recordName }}"
- name: CLOUDFLARE_API_TOKEN
valueFrom:
secretKeyRef:
name: cloudflare-api-key
key: CLOUDFLARE_API_TOKEN # Must match your secret key name
- name: CLOUDFLARE_TTL
value: "{{ .Values.cloudflare.ttl }}"
- name: CLOUDFLARE_PROXIED
value: "{{ .Values.cloudflare.proxied }}"
restartPolicy: OnFailure
You must create a Kubernetes Secret in the same namespace, named cloudflare-api-key.
It should contain your Cloudflare API token with the key CLOUDFLARE_API_TOKEN.
Example:
kubectl create secret generic cloudflare-api-key \
--from-literal=CLOUDFLARE_API_TOKEN="your_cloudflare_api_token" \
-n cloudflare
Deploy with ArgoCD
Create an app.yaml for ArgoCD:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cloudflare-ddns-updater
namespace: argocd
spec:
project: default
sources:
- repoURL: "<your Git repository URL>"
path: cloudflare-ddns
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: cloudflare
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Replace <your Git repository URL> with your repo.
Apply & Verify
Apply the ArgoCD application and watch it sync and create your CronJob:
kubectl apply -f app.yamlArgoCD will handle the deployment and ensure the CronJob runs every 5 minutes.
That’s it! Now your external IP updates automatically — no manual changes, no downtime when you’re away.