diff --git a/infrastructure/ddns/cloudflare-keys.sealedsecret.yaml b/infrastructure/ddns/cloudflare-keys.sealedsecret.yaml
new file mode 100644
index 0000000..9cfa4bf
--- /dev/null
+++ b/infrastructure/ddns/cloudflare-keys.sealedsecret.yaml
@@ -0,0 +1,19 @@
+---
+apiVersion: bitnami.com/v1alpha1
+kind: SealedSecret
+metadata:
+  creationTimestamp: null
+  name: cloudflare-keys
+  namespace: ddns
+spec:
+  encryptedData:
+    CLOUDFLARE_API_KEY: AgCSEPeO4QRhQLLi/PPBxKOu7boxEbk1wb23WT3ZMw8nMgw3kCST2lvyKSacVWX7czv+JYXU6z2eNvZ001xr/0EXsHtsM/AbAf6KmPzzZUzLwWkDJ0iIyw4yDVKqPqP4N2T+KOJpIh6o9kmit/kFyZ8cRlPsuBsFYOKljI6IxLBvoaiMQiYeymL50b0bmWhxK7VNkISxDyVGLkCWl9cMCvietoawSq64LDuAvwYnOFoXOmnxa523vYsLp/L9lNK5Yfk3ywlyjHeJgr8Bz80QRmBs8Fbo3dv2yZVZxHFDUY8+BNHk1N8qgjeaW1g02+puTntxlQu82Ea1gyhQ+Ft/DKQ9EPk7asDHaMtNybckHh7Hb/8QJDsk9cIAK3btE99IANzVUIddO7g8nPv/NybSpWq3kw40ErUjZVraOkAMEX7YIwJKD2n8RKps0Z3xDSYWkWygKQePoonh9xaQhV2R4Enc8nkzf/+eX7yg9SzZeAgR6w+RY+fi+BPC/PW/GgH4cRr8jgMBzEIDrw0OShdjYKlij8Xwe5vq/GdXmI2A9ZJnn2MhG7EKlxBlWD1FF219shqtro6ppVBJZNQAfWlg6jM4SFWP3DwL0RoO5dz+GMXofVBXG0sp6Ay0ILOxnXe/DHlgZN9AS4EcM1lWp6Rs31TkVMI/PUXL7uDwgBOZIwUdGJG+OlHNxXQZ/nuUIDIhZgBfBHuFnOpNN8KmJN33P1e2Wm5daru3bIKyr85LGfHhetRw/1jW6t4b
+    CLOUDFLARE_DNS_RECORD_ID: AgBx3Fu7qkgbrxJw0JtNYQyAop0yY7vCZ271GgTvUSZKQhdTY4mlo/xWL/3+sB4SnKRpyZ4/HcmJUEMrW6yb7aHKrQtzwvZRBeYQ52LMAQKBLzPqzKjce1VomqpMFwtferORR4drBYXFFuBJ7xEkRcJSaQ4dJTAWNQF/TKXJtMLswPGA259S6xfjuXaDcPA8faV63L0MPDqNU22Zzr99fOoEFRrYvyFVe1verXzJ2NnfgY6Em87cDRZHEUn0VZ03BURvZW4ElIODyRmSkUsptjvjjOVhSDixBkRljA/Ybp641Wa3Y2ZjKj3ta5g/CvPU50sHjlhQnV1v8viyqlxt79O2ysH+keeIxwQJOCzQYv44aXCWLvmswMTGsiOaKWCsCG8iSkXQe0VO44V7GOb9tZ+vbpi0o6x6+rh5N/L93dZdQydEG0omOkN5YmyZLN/wlepBSXPQPqFYVljaW6a/oGNNYwULPkmvqa5tUgSFuQDgrIHSJKFR8oBnBLYEKlglkLCOZKxqI+SkoeIK1TLP1eJ1hea3e6ULJopZFK6XLr1DJOl2pefPczeummLuoxtyJwmGWM9uGcVuDwi0V6N4ixWAnWWiimFVIFKjY6Fj7QJLge3B0K1gNtpeIIBlZ6whns/4YYv5DSojgCKS1OkmCohYQXN4/t+AG90OoR79+oJiVdzwrMCHRpLddfSGGfSzm2DkKw4x1kxptyQRJg3y89Kd2acM7kDvbaajMFNCy3yl3A==
+    CLOUDFLARE_ZONE_ID: AgCn20qDEs/2F3RtrSIyiBXD5IwPYB/yTkUhG3aA7puH8UlkVILzTXJfVGTeSp7hkDgBjcoX3o/KtMR44sS6oGl3cYYtvbni2/iplarqqZflRzvW7MSyE3TuSi8cVk+aTab0+mI4BkwiQ/RI1jolCIfcblh10kvJBSrH67R4JygKqb0OyM0DWtCXzMyUFunGKkEIpjnMQN/OfMhk+G9iB57iL9EL2ROl2ZgpYPwsDc+XFb8R1FGKJfpTux0b50NYS95VBb8uOZJ7kgBabfPn3hTlN4bL7uzDWlCEotGOTJ1tYhBfgQN7O5SxU4/Lks11mqv6TRenZPXb7pe39/k6BOoh7dY6odqfT9MWD/OjTJ78RAKcfwA/z2zEXmCxrKdZwC8aQ9I35rLYo6rzktcguWn9nThza5bN3uQF9Gy16R0Dq5JO37I61gFkH8UHmCax+8/a8YlcUkeHSii7AUFv8z8VaFI2qzz4OtyeRO0yatP87D8ID98kFeymzU1AVacCqLsm08qaPHj7yOV1B6mxufHaYsuXckDcGEh1e03Op+hYDqff0pz7oQ2izHFvx+w0X2AbMXx+8j+Grpw14PO8bWal2DQBVu8/+4bfAFWoCVMuE4Tf/jGnbzlUHvU8N9wnpQ9OgV9EOO7m2A5vbGOsjIGV8kZrWNKhzHs6BroJl2GIyiteTJC+/EbNGK8y4hZrmjIhjhlel0X2GgT/3iQ5svH2yrIGvUmONk8ZBE2xjI+V4A==
+    KLUSTER_DOMAIN: AgBVbvgJHtG6jnZK8vU+Hf+6U948uwd5yMBCOoIqvlEIN+uLQqorLNLvUuvStZjsga4B+2biufuYcIbc41yyRJc8Z0MKmGjvZI7l4oCZ3uu09qlFLV1xMjrQC5HtXNJd/x9nbFToj9wEdM/IZY2medJ59MaIolmeck14ZIiwCJiMTXG4UZt1eoS9J6NEIweqPWA/x9uq1IATVTPtL80sH6OtjMDzmmjx6lDgQfw8saoxg8zmHBAAi+MT6GCUhAzjRl/bCA8oUfuW69exXl0FMBlxWyi/+vXNDCOwVJDiVTDfodThr0ocGAaEkZHx7w5jaPdfh1+Wj2dsHTxyp1LIIYSQy7m9elRV8Wz74//5ejsDbETKM69qirsOhQbPNJpEj4Tnjr5re1o49hH8ej0KcFOpHjMcupwJW4sqNJqEyqUnP4C/BE5bySauuYT0pShAc24yQyJHQokdei0oBKzRtUDiM4+2NQVZXxURv2oSIfgB0CKfHPjsYpQxRJ4B83qBUGUmLZYyFnwl3FWwbHhrgmHBE2qik9XgcssvMWMhobkxiWd46KsaXVnjU7KqlTHWuEoI6AaC1s2r0WTJGf0zY1Mn93Na1uLgypwwgkUx/cV2l+ThzMETPXjNKm4INn6WeGmE6HomRXqBcJxgg4+RimXKtaitXxr7ujZZEZhIiVGgDJT36pwAjZBg3kD6NeJ10LjivwB9VuYHWjqgGyicuEZ5TA==
+  template:
+    metadata:
+      creationTimestamp: null
+      name: cloudflare-keys
+      namespace: ddns
+    type: Opaque
diff --git a/infrastructure/ddns/cronjob.yaml b/infrastructure/ddns/cronjob.yaml
new file mode 100644
index 0000000..b2729a5
--- /dev/null
+++ b/infrastructure/ddns/cronjob.yaml
@@ -0,0 +1,54 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+  name: ddns-cronjob
+spec:
+  schedule: "0 6,18 * * *"
+  jobTemplate:
+    spec:
+      template:
+        spec:
+          containers:
+          - name: hello
+            image: curl
+            command:
+              - /bin/sh
+              - -c
+            args:
+              - >-
+                CURRENT_IP = $(curl -4 ifconfig.me)
+                &&
+                echo "Current IP: $CURRENT_IP"
+                &&
+                curl
+                --request PUT
+                --url https://api.cloudflare.com/client/v4/zones/$(CLOUDFLARE_ZONE_ID)/dns_records/$(CLOUDFLARE_DNS_RECORD_ID)
+                --header "Authorization: Bearer $(CLOUDFLARE_API_KEY)"
+                --header "Content-Type: application/json"
+                --data '{"content": "$(CURRENT_IP)", "name": "$(KLUSTER_DOMAIN)", "proxied": false, "type": "A"}'
+
+            env:
+              - name: CLOUDFLARE_ZONE_ID
+                valueFrom:
+                  secretKeyRef:
+                    name: cloudflare-keys
+                    key: CLOUDFLARE_ZONE_ID
+              - name: CLOUDFLARE_API_KEY
+                valueFrom:
+                  secretKeyRef:
+                    name: cloudflare-keys
+                    key: CLOUDFLARE_API_KEY
+              - name: CLOUDFLARE_DNS_RECORD_ID
+                valueFrom:
+                  secretKeyRef:
+                    name: cloudflare-keys
+                    key: CLOUDFLARE_DNS_RECORD_ID
+              - name: KLUSTER_DOMAIN
+                valueFrom:
+                  secretKeyRef:
+                    name: cloudflare-keys
+                    key: KLUSTER_DOMAIN
+              - name: CURRENT_IP
+                value: ???
+
+          restartPolicy: OnFailure
diff --git a/infrastructure/ddns/kustomization.yaml b/infrastructure/ddns/kustomization.yaml
new file mode 100644
index 0000000..231b209
--- /dev/null
+++ b/infrastructure/ddns/kustomization.yaml
@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+namespace: ddns
+
+images:
+  - name: curl
+    newName: curlimages/curl
+    newTag: 8.5.0
+
+resources:
+  - namespace.yaml
+  - cronjob.yaml
+  - cloudflare-keys.sealedsecret.yaml
diff --git a/infrastructure/ddns/namespace.yaml b/infrastructure/ddns/namespace.yaml
new file mode 100644
index 0000000..0a074bd
--- /dev/null
+++ b/infrastructure/ddns/namespace.yaml
@@ -0,0 +1,4 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: placeholder
diff --git a/kluster-deployments/ddns/application.yaml b/kluster-deployments/ddns/application.yaml
new file mode 100644
index 0000000..69d6f7b
--- /dev/null
+++ b/kluster-deployments/ddns/application.yaml
@@ -0,0 +1,18 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+  name: ddns-application
+  namespace: argocd
+spec:
+  project: infrastructure
+  source:
+    repoURL: git@github.com:moll-re/bootstrap-k3s-infra.git
+    targetRevision: main
+    path: infrastructure/ddns
+  destination:
+    server: https://kubernetes.default.svc
+    namespace: ddns
+  syncPolicy:
+    automated:
+      prune: true
+      selfHeal: true
diff --git a/kluster-deployments/ddns/kustomization.yaml b/kluster-deployments/ddns/kustomization.yaml
new file mode 100644
index 0000000..977dcfe
--- /dev/null
+++ b/kluster-deployments/ddns/kustomization.yaml
@@ -0,0 +1,4 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+  - application.yaml
diff --git a/kluster-deployments/kustomization.yaml b/kluster-deployments/kustomization.yaml
index f720ad4..11f4730 100644
--- a/kluster-deployments/kustomization.yaml
+++ b/kluster-deployments/kustomization.yaml
@@ -11,6 +11,7 @@ resources:
 
   # infrastructure apps
   - projects.yaml
+  - ddns/
   - nfs/
   - backup/
   - pg-ha/