diff --git a/handlers/main.yml b/handlers/main.yml
index 47da8fb..6813eab 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -144,4 +144,11 @@
   when:
     - config is defined
     - config.changed | bool
+
+# dyndns
+- name: restart dyndns  # noqa no-changed-when
+  ansible.builtin.command: /usr/local/etc/rc.d/ddclient_opn restart
+  when:
+    - config is defined
+    - config.changed | bool
 ...
diff --git a/tasks/dyndns.yml b/tasks/dyndns.yml
new file mode 100644
index 0000000..0e24a91
--- /dev/null
+++ b/tasks/dyndns.yml
@@ -0,0 +1,77 @@
+---
+# opn_dyndns_general:
+#  settings:
+#    - key: enabled
+#      value: "1"
+#    - key: verbose
+#      value: "0"
+#    - key: allowipv6
+#      value: "0"
+#    - key: daemon_delay
+#      value: "300"
+#    - key: backend
+#      value: "opnsense"
+# opn_dyndns_accounts:
+#  - uuid: "8e4627c4-21ff-4252-a331-3d1adee0a023"
+#    settings:
+#      - key: enabled
+#        value: "1"
+#      - key: service
+#        value: "testservice"
+#      - key: protocol
+#        value: ""
+#      - key: server
+#        value: ""
+#      - key: username
+#        value: "user"
+#      - key: password
+#        value: "pass"
+#      - key: resourceId
+#        value: ""
+#      - key: hostnames
+#        value: "all.ddnskey.com"
+#      - key: wildcard
+#        value: "0"
+#      - key: zone
+#        value: ""
+#      - key: checkip
+#        value: "web_noip-ipv4"
+#      - key: checkip_timeout
+#        value: "10"
+#      - key: force_ssl
+#        value: "1"
+#      - key: ttl
+#        value: "300"
+#      - key: interface
+#        value: "wan"
+#      - key: description
+#        value: "dyndns-description"
+
+- name: DynDNS -  Update general DynDNS settings
+  delegate_to: localhost
+  community.general.xml:
+    path: "{{ local_config_path }}"
+    xpath: "/opnsense/OPNsense/DynDNS/general/{{ item.key }}"
+    value: "{{ item.value }}"
+    state: present
+    pretty_print: true
+  notify: restart dyndns
+  with_items:
+    - "{{ opn_dyndns_general }}"
+  when:
+    - opn_dyndns_general is defined
+
+- name: DynDNS - Apply settings for each DynDNS account
+  delegate_to: localhost
+  community.general.xml:
+    path: "{{ local_config_path }}"
+    xpath: "/opnsense/OPNsense/DynDNS/accounts/account[@uuid='{{ item.0.uuid }}']/{{ item.1.key }}"
+    value: "{{ item.1.value }}"
+    state: present
+    pretty_print: true
+  notify: restart dyndns
+  with_subelements:
+    - "{{ opn_dyndns_accounts }}"
+    - settings
+  when:
+    - opn_dyndns_accounts is defined
diff --git a/tasks/main.yml b/tasks/main.yml
index f79b3e3..850900d 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -25,6 +25,15 @@
         - dnsserver
         - dns
 
+- name: dyndns
+  tags:
+    - always
+  ansible.builtin.include_tasks:
+    file: dyndns.yml
+    apply:
+      tags:
+        - dyndns
+
 - name: user
   tags:
     - always
diff --git a/test/dyndns-test-expect.xml b/test/dyndns-test-expect.xml
new file mode 100644
index 0000000..16ad005
--- /dev/null
+++ b/test/dyndns-test-expect.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<opnsense>
+  <system>
+  </system>
+  <OPNsense>
+    <DynDNS>
+      <general>
+        <enabled>1</enabled>
+        <verbose>0</verbose>
+        <allowipv6nano>0</allowipv6nano>
+        <daemon_delay>300</daemon_delay>
+        <backend>opnsense</backend>
+      </general>
+      <accounts>
+        <account uuid="8e4627c4-21ff-4252-a331-3d1adee0a023">
+          <enabled>1</enabled>
+          <service>noip</service>
+          <protocol/>
+          <server/>
+          <username/>
+          <password>user</password>
+          <resourceId>pass</resourceId>
+          <hostnames>all.ddnskey.com</hostnames>
+          <wildcard>0</wildcard>
+          <zone/>
+          <checkip>web_noip-ipv4</checkip>
+          <checkip_timeout>10</checkip_timeout>
+          <force_ssl>1</force_ssl>
+          <ttl>300</ttl>
+          <interface>wan</interface>
+          <description>dyndns-description</description>
+        </account>
+      </accounts>
+    </DynDNS>
+  </OPNsense>
+</opnsense>
diff --git a/test/dyndns-test.xml b/test/dyndns-test.xml
new file mode 100644
index 0000000..38af667
--- /dev/null
+++ b/test/dyndns-test.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<opnsense>
+  <system>
+  </system>
+  <OPNsense>
+  </OPNsense>
+</opnsense>
diff --git a/test/dyndns-test.yml b/test/dyndns-test.yml
new file mode 100644
index 0000000..51c1735
--- /dev/null
+++ b/test/dyndns-test.yml
@@ -0,0 +1,48 @@
+---
+
+opn_dyndns_general:
+    - key: enabled
+      value: "1"
+    - key: verbose
+      value: "0"
+    - key: allowipv6nano 
+      value: "0"
+    - key: daemon_delay
+      value: "300"
+    - key: backend
+      value: "opnsense"
+opn_dyndns_accounts:
+  - uuid: "8e4627c4-21ff-4252-a331-3d1adee0a023"
+    settings:
+      - key: enabled
+        value: "1"
+      - key: service
+        value: "noip"
+      - key: protocol
+        value: ""
+      - key: server
+        value: ""
+      - key: username
+        value: ""
+      - key: password
+        value: "user"
+      - key: resourceId
+        value: "pass"
+      - key: hostnames
+        value: "all.ddnskey.com"
+      - key: wildcard
+        value: "0"
+      - key: zone
+        value: ""
+      - key: checkip
+        value: "web_noip-ipv4"
+      - key: checkip_timeout
+        value: "10"
+      - key: force_ssl
+        value: "1"
+      - key: ttl
+        value: "300"
+      - key: interface
+        value: "wan"
+      - key: description
+        value: "dyndns-description" 
diff --git a/test/test.yml b/test/test.yml
index 2e8a39b..68c5711 100644
--- a/test/test.yml
+++ b/test/test.yml
@@ -26,6 +26,9 @@
     - name: stop ipsec  # TODO: test this action; use community.general.xml and add a tag to the resulting xml
       debug:
         msg: fake handler - stop ipsec
+    - name: restart dyndns
+      debug:
+        msg: fake handler - restart dyndns
   tasks:
     - name: include default vars
       ansible.builtin.include_vars:
@@ -44,6 +47,7 @@
         - ipsec
         - dnsserver
         - openvpn
+        - dyndns
       when:
         - test | default(_testtask) == _testtask
     - ansible.builtin.meta: flush_handlers