Ansible modprobe: Load & Unload Linux Kernel Modules (Guide)
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to load and unload Linux kernel modules with Ansible modprobe module. Manage drivers, configure module parameters, and persist across reboots with examples.

How to Load and Unload Kernel Modules in Linux with Ansible?
I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.See also: Configuring Kernel Parameters in RedHat-like Linux Systems with Ansible System Role
Ansible Load and Unload Kernel Modules in Linux
• community.general.modprobe • Load or unload kernel modulesToday we're talking about the Ansible module modprobe.
The full name is community.general.modprobe, which means that is part of the collection of modules "community.general" maintained by the Ansible Community.
The purpose of the module is to Load or unload kernel modules.
Parameters
• name string - Name of kernel module • params string - Modules parameters • state string - present/absent - Load / UnloadThe parameters of the module modprobe. The only required parameter is "name", with the full Linux kernel module name. The parameter "params" allows you to specify some module parameters. Default is an empty string. The parameter "state" specifies the status of the Linux Kernel module. The option "present" means that the module must be loaded. The option "absent" means that the module must be unloaded.
See also: ansible.posix.sysctl Module: Set Kernel Parameters Persistently (Guide)
Links
• https://docs.ansible.com/ansible/latest/collections/community/general/modprobe_module.html## Playbook
Load and Unload Kernel Modules in Linux with Ansible Playbook.
code
---
- name: modprobe module Playbook
hosts: all
become: true
vars:
module_name: "dummy"
module_params: "numdummies=2"
tasks:
- name: load the module
community.general.modprobe:
name: "{{ module_name }}"
state: present
params: "{{ module_params }}"
execution
$ ansible-playbook -i virtualmachines/demo/inventory modprobe/modprobe.yml
PLAY [modprobe module Playbook] ***********************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [Add the dummy module] ***********************************************************************
changed: [demo.example.com]
PLAY RECAP ****************************************************************************************
demo.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
idempotency
$ ansible-playbook -i virtualmachines/demo/inventory modprobe/modprobe.yml
PLAY [modprobe module Playbook] ***********************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [Add the dummy module] ***********************************************************************
ok: [demo.example.com]
PLAY RECAP ****************************************************************************************
demo.example.com : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
before execution
$ ssh devops@demo.example.com
Last login: Tue Jan 11 21:12:15 2022 from 192.168.0.102
[devops@demo ~]$ sudo su
[root@demo devops]# lsmod
Module Size Used by
nft_fib_inet 16384 1
nft_fib_ipv4 16384 1 nft_fib_inet
nft_fib_ipv6 16384 1 nft_fib_inet
nft_fib 16384 3 nft_fib_ipv6,nft_fib_ipv4,nft_fib_inet
nft_reject_inet 16384 4
nf_reject_ipv4 16384 1 nft_reject_inet
nf_reject_ipv6 16384 1 nft_reject_inet
nft_reject 16384 1 nft_reject_inet
nft_ct 20480 9
nf_tables_set 49152 12
nft_chain_nat 16384 12
nf_nat 45056 1 nft_chain_nat
nf_conntrack 172032 2 nf_nat,nft_ct
nf_defrag_ipv6 20480 1 nf_conntrack
nf_defrag_ipv4 16384 1 nf_conntrack
ip_set 49152 0
nf_tables 172032 259 nft_ct,nft_reject_inet,nft_fib_ipv6,nft_fib_ipv4,nft_chain_nat,nf_tables_set,nft_reject,nft_fib,nft_fib_inet
nfnetlink 16384 3 nf_tables,ip_set
intel_rapl_msr 16384 0
intel_rapl_common 24576 1 intel_rapl_msr
intel_pmc_core_pltdrv 16384 0
intel_pmc_core 45056 0
intel_powerclamp 16384 0
crct10dif_pclmul 16384 1
crc32_pclmul 16384 0
ghash_clmulni_intel 16384 0
rapl 20480 0
pcspkr 16384 0
joydev 24576 0
video 49152 0
i2c_piix4 24576 0
xfs 1544192 2
libcrc32c 16384 4 nf_conntrack,nf_nat,nf_tables,xfs
sd_mod 53248 3
t10_pi 16384 1 sd_mod
sg 40960 0
ata_generic 16384 0
vboxvideo 45056 1
drm_ttm_helper 16384 1 vboxvideo
ttm 77824 2 vboxvideo,drm_ttm_helper
drm_kms_helper 253952 1 vboxvideo
drm 573440 5 drm_kms_helper,vboxvideo,drm_ttm_helper,ttm
ata_piix 36864 2
libata 270336 2 ata_piix,ata_generic
crc32c_intel 24576 1
serio_raw 16384 0
e1000 151552 0
syscopyarea 16384 1 drm_kms_helper
sysfillrect 16384 1 drm_kms_helper
sysimgblt 16384 1 drm_kms_helper
vboxguest 385024 1
fb_sys_fops 16384 1 drm_kms_helper
dm_mirror 28672 0
dm_region_hash 20480 1 dm_mirror
dm_log 20480 2 dm_region_hash,dm_mirror
dm_mod 151552 9 dm_log,dm_mirror
[root@demo devops]# lsmod | grep dummy
[root@demo devops]# uname -a
Linux demo.example.com 4.18.0-348.el8.x86_64 #1 SMP Mon Oct 4 12:17:22 EDT 2021 x86_64 x86_64 x86_64 GNU/Linux
[root@demo devops]#
after execution
$ ssh devops@demo.example.com
Last login: Wed Jan 12 07:35:19 2022 from 192.168.0.101
[devops@demo ~]$ sudo su
[root@demo devops]# lsmod | grep dummy
dummy 16384 0
[root@demo devops]# less /var/log/messages
[root@demo devops]# tail /var/log/messages
Jan 12 07:35:04 Playbook systemd-udevd[4297]: Using default interface naming scheme
'rhel-8.0'.
Jan 12 07:35:04 Playbook systemd-udevd[4297]: link_config: autonegotiation is unset
or enabled, the speed and duplex are not writable.
Jan 12 07:35:04 Playbook systemd-udevd[4297]: Could not generate persistent MAC addr
ess for dummy1: No such file or directory
Jan 12 07:35:18 Playbook ansible-ansible.legacy.setup[4440]: Invoked with gather_sub
set=['all'] gather_timeout=10 filter=[] fact_path=/etc/ansible/facts.d
Jan 12 07:35:19 Playbook ansible-community.general.modprobe[4593]: Invoked with name
=dummy state=present params=numdummies=2
Jan 12 07:35:19 Playbook chronyd[826]: Selected source 94.124.107.190 (2.rhel.pool.n
tp.org)
Jan 12 07:35:19 Playbook chronyd[826]: Selected source 213.192.54.227 (2.rhel.pool.n
tp.org)
[root@demo devops]# modinfo dummy
filename: /lib/modules/4.18.0-348.el8.x86_64/kernel/drivers/net/dummy.ko.xz
version: 1.0
alias: rtnl-link-dummy
license: GPL
rhelversion: 8.5
srcversion: FF01F2D4C53E7F939842380
depends:
intree: Y
name: dummy
vermagic: 4.18.0-348.el8.x86_64 SMP mod_unload modversions
sig_id: PKCS#7
signer: Red Hat Enterprise Linux kernel signing key
sig_key: 77:A4:0E:A4:5E:89:11:3E:DC:EE:6E:4B:55:AA:F2:1A:6C:4A:91:21
sig_hashalgo: sha256
signature: 25:AD:03:5D:FD:85:A6:3D:E4:8F:3F:70:52:0F:97:20:C9:6A:C3:32:
F9:15:C3:AE:E6:03:FB:7B:04:3E:0E:B3:50:0C:49:1A:D1:31:96:C3:
6D:02:C4:32:C1:2A:D4:28:41:5B:CD:D9:C1:B2:D0:68:9C:24:D4:0E:
EA:B6:8C:41:4A:76:49:64:02:D8:6E:9A:3F:92:91:C6:DF:3C:14:88:
05:BE:62:CE:E9:19:F0:84:28:19:38:3A:D4:F8:28:C2:51:0F:46:6D:
7A:9D:D5:8B:D5:A2:3C:93:08:4E:37:39:EA:98:7D:DE:15:9A:A3:54:
D3:25:42:28:EF:72:A9:74:BA:8E:0B:3D:E3:84:38:BA:4D:4B:43:F2:
DD:8D:BC:FF:6B:C0:41:31:8B:2B:88:C4:77:1E:8E:A0:4D:40:23:6E:
BF:00:E1:2A:E2:04:49:F9:7F:8E:6C:1C:92:3D:68:D2:38:26:7B:75:
2C:E5:56:73:A8:6A:7D:2E:15:06:34:87:2B:8F:6B:36:BC:08:48:9E:
55:9E:D7:16:F7:5A:94:7F:BA:06:F8:85:3F:D1:91:7A:CB:33:E8:73:
A9:2E:C8:B9:1F:F9:10:BB:D1:9A:FF:9B:CA:38:26:C2:A4:02:06:07:
35:20:91:75:FA:D7:8A:AA:A7:44:76:97:2D:A5:73:6C:1E:F5:D6:BD:
26:03:48:CA:96:34:48:5A:34:A0:7C:F1:C1:A8:73:D3:89:2B:EC:F3:
73:9B:FC:A1:C3:32:84:1A:05:2B:D2:6B:E4:3C:AD:FE:22:AC:20:D7:
2F:5B:38:52:B9:F8:EB:93:FE:95:2B:A5:E2:CB:A3:24:C1:4E:29:EE:
6F:DD:49:45:31:DF:21:9B:09:D4:10:06:0D:AA:99:38:78:2E:72:3C:
8D:F0:80:C8:A8:B7:E1:72:11:E1:08:0A:A4:20:0F:D2:98:4A:32:30:
2C:7D:14:68:F6:A8:21:3F:DD:B5:42:A3:35:7A:BC:7A:52:2B:0E:CC:
92:23:4D:7E
parm: numdummies:Number of dummy pseudo devices (int)
[root@demo devops]#
Conclusion
Now you know how to Load and Unload Kernel Modules in Linux with Ansible.
See also: Ansible code in RHSB-2021-009 Log4Shell - Remote Code Execution - log4j (CVE-2021-44228)
Load Kernel Module
- name: Load br_netfilter
community.general.modprobe:
name: br_netfilter
state: present
become: true
Unload Module
- modprobe:
name: usb_storage
state: absent
become: true
Load with Parameters
- modprobe:
name: bonding
state: present
params: "mode=4 miimon=100"
become: true
Persist Across Reboots
# Load now
- modprobe:
name: br_netfilter
state: present
become: true
# Persist for boot
- copy:
content: "br_netfilter\n"
dest: /etc/modules-load.d/br_netfilter.conf
become: true
Kubernetes Prerequisites
- name: Load required kernel modules
modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
become: true
- name: Persist modules
copy:
content: |
overlay
br_netfilter
dest: /etc/modules-load.d/k8s.conf
become: true
- name: Set sysctl params
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
sysctl_file: /etc/sysctl.d/k8s.conf
reload: true
loop:
- { key: net.bridge.bridge-nf-call-iptables, value: "1" }
- { key: net.bridge.bridge-nf-call-ip6tables, value: "1" }
- { key: net.ipv4.ip_forward, value: "1" }
become: true
Blacklist Module
# Prevent module from loading
- copy:
content: "blacklist nouveau\n"
dest: /etc/modprobe.d/blacklist-nouveau.conf
become: true
- command: update-initramfs -u
become: true
when: ansible_os_family == "Debian"
Module Parameters Persistent
# /etc/modprobe.d/bonding.conf
- copy:
content: "options bonding mode=4 miimon=100\n"
dest: /etc/modprobe.d/bonding.conf
become: true
Check Module Status
- command: lsmod | grep br_netfilter
register: mod_status
changed_when: false
failed_when: false
- debug:
msg: "{{ 'loaded' if mod_status.rc == 0 else 'not loaded' }}"
Common Modules
| Module | Purpose |
|--------|---------|
| br_netfilter | Bridge netfilter (Kubernetes) |
| overlay | OverlayFS (containers) |
| bonding | Network bonding |
| 8021q | VLAN tagging |
| ip_vs | IPVS load balancing |
| nf_conntrack | Connection tracking |
| vhost_net | Virtio networking |
| kvm / kvm_intel | KVM virtualization |
Full Server Setup Example
---
- name: Configure kernel modules
hosts: all
become: true
vars:
required_modules:
- overlay
- br_netfilter
- ip_vs
- ip_vs_rr
- ip_vs_wrr
- nf_conntrack
blacklisted_modules:
- nouveau
- floppy
tasks:
- name: Load required modules
modprobe: { name: "{{ item }}", state: present }
loop: "{{ required_modules }}"
- name: Persist required modules
copy:
content: "{{ required_modules | join('\n') }}\n"
dest: /etc/modules-load.d/custom.conf
- name: Blacklist modules
copy:
content: "blacklist {{ item }}\n"
dest: "/etc/modprobe.d/blacklist-{{ item }}.conf"
loop: "{{ blacklisted_modules }}"
FAQ
modprobe vs insmod?
modprobe handles dependencies automatically. insmod loads a single module without dependency resolution. Always use modprobe.
How do I check available modules?
find /lib/modules/$(uname -r) -name "*.ko*"
modinfo br_netfilter
Module won't load — how to debug?
dmesg | tail -20
modprobe -v br_netfilter # Verbose
modinfo br_netfilter # Check if available
Related Articles
• privilege escalation with Ansible become • inventory configuration in Ansible • role variables and defaults in AnsibleCategory: troubleshooting
Watch the video: Ansible modprobe: Load & Unload Linux Kernel Modules (Guide) — Video Tutorial