diff --git a/defaults/main.yml b/defaults/main.yml
index 899397d..4142463 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -162,3 +162,27 @@ libvirt_host_vnc_tls_enabled: false
 
 # Whether to configure AppArmor for directory storage pools.
 libvirt_host_configure_apparmor: "{{ libvirt_host_install_daemon | bool }}"
+
+# Whether to disable and mask libvirt modular systemd units
+# See: https://libvirt.org/daemons.html
+libvirt_disable_modular_systemd_units: true
+
+# A list of libvirt modular daemon drivers
+libvirtd_modular_daemon_drivers:
+  - qemu
+  - interface
+  - network
+  - nodedev
+  - nwfilter
+  - proxy
+  - secret
+  - storage
+
+# A list of libvirt modular systemd services.
+# The {driver} replacement string is populated
+# from libvirtd_modular_daemon_drivers.
+libvirtd_modular_services:
+  - virt{driver}d.service
+  - virt{driver}d.socket
+  - virt{driver}d-ro.socket
+  - virt{driver}d-admin.socket
diff --git a/tasks/config.yml b/tasks/config.yml
index 49c4e71..1ae4a30 100644
--- a/tasks/config.yml
+++ b/tasks/config.yml
@@ -221,3 +221,7 @@
         enabled: "{{ libvirt_host_tls_listen | bool }}"
       - service: libvirtd
         enabled: true
+
+- name: Disable libvirt modular systemd units
+  include_tasks: disable-modular-systemd-units.yml
+  when: libvirt_disable_modular_systemd_units
diff --git a/tasks/disable-modular-systemd-units.yml b/tasks/disable-modular-systemd-units.yml
new file mode 100644
index 0000000..ec2e961
--- /dev/null
+++ b/tasks/disable-modular-systemd-units.yml
@@ -0,0 +1,13 @@
+---
+
+- name: Disable and mask libvirtd modular systemd services and sockets
+  systemd:
+    name: "{{ service_name }}"
+    state: stopped
+    enabled: false
+    masked: true
+  loop: "{{ libvirtd_modular_daemon_drivers | product(libvirtd_modular_services) }}"
+  vars:
+    service_name: "{{ item[1].format(driver=item[0]) }}"
+  loop_control:
+    label: "{{ service_name }}"