diff --git a/README-dnsconfig.md b/README-dnsconfig.md
index 029ec515a16514984d9d8b742f7a0b1b7eee0028..f7e733fb29a9c9326b91298866f328fddb0828ac 100644
--- a/README-dnsconfig.md
+++ b/README-dnsconfig.md
@@ -126,6 +126,7 @@ Variable | Description | Required
 -------- | ----------- | --------
 `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
 `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
+`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
 `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
   | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
   | `port` - The custom port that should be used on this server. | no
diff --git a/tests/dnsconfig/test_dnsconfig.yml b/tests/dnsconfig/test_dnsconfig.yml
index 3a69bea81dceb72345bbb799e21ba41f1d4d8ad8..b416a0d1762db698a4d6a111a8d80a3806599ea6 100644
--- a/tests/dnsconfig/test_dnsconfig.yml
+++ b/tests/dnsconfig/test_dnsconfig.yml
@@ -1,6 +1,6 @@
 ---
 - name: Test dnsconfig
-  hosts: ipaserver
+  hosts: "{{ ipa_test_host | default('ipaserver') }}"
   become: true
   gather_facts: true
 
@@ -9,6 +9,7 @@
   - name: Ensure forwarders are absent.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
@@ -21,6 +22,7 @@
   - name: Set config to invalid IPv4.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 1.2.3.500
     register: result
@@ -29,6 +31,7 @@
   - name: Set config to invalid IP.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 1.in.va.lid
     register: result
@@ -37,6 +40,7 @@
   - name: Set config to invalid IPv6.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: fd00::invalid
     register: result
@@ -45,6 +49,7 @@
   - name: Set dnsconfig.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
@@ -58,6 +63,7 @@
   - name: Set dnsconfig, with the same values.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
@@ -71,6 +77,7 @@
   - name: Ensure forwarder is absent.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
       state: absent
@@ -80,6 +87,7 @@
   - name: Ensure forwarder is absent, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
       state: absent
@@ -89,6 +97,7 @@
   - name: Disable global forwarders.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forward_policy: none
     register: result
     failed_when: not result.changed or result.failed
@@ -96,6 +105,7 @@
   - name: Disable global forwarders, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forward_policy: none
     register: result
     failed_when: result.changed or result.failed
@@ -103,6 +113,7 @@
   - name: Re-enable global forwarders.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forward_policy: first
     register: result
     failed_when: not result.changed or result.failed
@@ -110,6 +121,7 @@
   - name: Re-enable global forwarders, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forward_policy: first
     register: result
     failed_when: result.changed or result.failed
@@ -117,6 +129,7 @@
   - name: Disable PTR record synchronization.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       allow_sync_ptr: no
     register: result
     failed_when: not result.changed or result.failed
@@ -124,6 +137,7 @@
   - name: Disable PTR record synchronization, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       allow_sync_ptr: no
     register: result
     failed_when: result.changed or result.failed
@@ -131,6 +145,7 @@
   - name: Re-enable PTR record synchronization.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       allow_sync_ptr: yes
     register: result
     failed_when: not result.changed or result.failed
@@ -138,6 +153,7 @@
   - name: Re-enable PTR record synchronization, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       allow_sync_ptr: yes
     register: result
     failed_when: result.changed or result.failed
@@ -145,6 +161,7 @@
   - name: Ensure all forwarders are absent.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
@@ -158,6 +175,7 @@
   - name: Ensure all forwarders are absent, again.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
@@ -171,6 +189,7 @@
   - name: Ensure forwarders are absent.
     ipadnsconfig:
       ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
       forwarders:
         - ip_address: 8.8.8.8
         - ip_address: 8.8.4.4
diff --git a/tests/dnsconfig/test_dnsconfig_client_context.yml b/tests/dnsconfig/test_dnsconfig_client_context.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6db3b62a86eff46213358cea0cf7846386397e5d
--- /dev/null
+++ b/tests/dnsconfig/test_dnsconfig_client_context.yml
@@ -0,0 +1,37 @@
+---
+- name: Test dnsconfig
+  hosts: ipaclients, ipaserver
+  become: no
+  gather_facts: no
+
+  tasks:
+  - name: Include FreeIPA facts.
+    include_tasks: ../env_freeipa_facts.yml
+
+  # Test will only be executed if host is not a server.
+  - name: Execute with server context in the client.
+    ipadnsconfig:
+      ipaadmin_password: SomeADMINpassword
+      ipaapi_context: server
+      forward_policy: none
+    register: result
+    failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
+    when: ipa_host_is_client
+
+# Import basic module tests, and execute with ipa_context set to 'client'.
+# If ipaclients is set, it will be executed using the client, if not,
+# ipaserver will be used.
+#
+# With this setup, tests can be executed against an IPA client, against
+# an IPA server using "client" context, and ensure that tests are executed
+# in upstream CI.
+
+- name: Test dnsconfig using client context, in client host.
+  import_playbook: test_dnsconfig.yml
+  when: groups['ipaclients']
+  vars:
+    ipa_test_host: ipaclients
+
+- name: Test dnsconfig using client context, in server host.
+  import_playbook: test_dnsconfig.yml
+  when: groups['ipaclients'] is not defined or not groups['ipaclients']