Introduction
Swap space extends available memory by using disk as overflow. Ansible automates swap management — create swap files or partitions, set permissions, activate swap, persist via fstab, and tune swappiness. This is essential for servers that need memory safety nets without manual configuration.
Create a Swap File
---
- name: Create and enable swap file
hosts: all
become: true
vars:
swap_file_path: /swapfile
swap_file_size_mb: 2048
swappiness: 10
tasks:
- name: Check if swap file exists
ansible.builtin.stat:
path: "{{ swap_file_path }}"
register: swap_file
- name: Create swap file
ansible.builtin.command: >
dd if=/dev/zero of={{ swap_file_path }}
bs=1M count={{ swap_file_size_mb }}
args:
creates: "{{ swap_file_path }}"
when: not swap_file.stat.exists
- name: Set swap file permissions
ansible.builtin.file:
path: "{{ swap_file_path }}"
mode: '0600'
owner: root
group: root
- name: Format as swap
ansible.builtin.command: mkswap {{ swap_file_path }}
when: not swap_file.stat.exists
register: mkswap_result
changed_when: mkswap_result.rc == 0
- name: Enable swap
ansible.builtin.command: swapon {{ swap_file_path }}
when: not swap_file.stat.exists
register: swapon_result
changed_when: swapon_result.rc == 0
- name: Add to fstab
ansible.posix.mount:
src: "{{ swap_file_path }}"
path: none
fstype: swap
opts: sw
state: present
- name: Set swappiness
ansible.posix.sysctl:
name: vm.swappiness
value: "{{ swappiness }}"
sysctl_set: true
reload: true
- name: Set vfs_cache_pressure
ansible.posix.sysctl:
name: vm.vfs_cache_pressure
value: "50"
sysctl_set: true
reload: true
Using fallocate (Faster)
- name: Create swap file with fallocate
ansible.builtin.command: >
fallocate -l {{ swap_file_size_mb }}M {{ swap_file_path }}
args:
creates: "{{ swap_file_path }}"
Note: fallocate doesn't work on all filesystems (e.g., XFS with copy-on-write). Use dd as the safe default.
Swap Partition
- name: Create swap partition
community.general.parted:
device: /dev/sdb
number: 1
flags: [swap]
state: present
part_type: primary
fs_type: linux-swap
- name: Format swap partition
ansible.builtin.command: mkswap /dev/sdb1
register: mkswap
changed_when: mkswap.rc == 0
- name: Enable swap partition
ansible.builtin.command: swapon /dev/sdb1
register: swapon
changed_when: swapon.rc == 0
- name: Persist in fstab
ansible.posix.mount:
src: /dev/sdb1
path: none
fstype: swap
opts: sw
state: present
Resize Swap
- name: Resize swap file
hosts: all
become: true
vars:
swap_file_path: /swapfile
new_size_mb: 4096
tasks:
- name: Disable current swap
ansible.builtin.command: swapoff {{ swap_file_path }}
changed_when: true
ignore_errors: true
- name: Resize swap file
ansible.builtin.command: >
dd if=/dev/zero of={{ swap_file_path }}
bs=1M count={{ new_size_mb }}
changed_when: true
- name: Set permissions
ansible.builtin.file:
path: "{{ swap_file_path }}"
mode: '0600'
- name: Reformat
ansible.builtin.command: mkswap {{ swap_file_path }}
changed_when: true
- name: Re-enable
ansible.builtin.command: swapon {{ swap_file_path }}
changed_when: true
Remove Swap
- name: Remove swap file
hosts: all
become: true
tasks:
- name: Disable swap
ansible.builtin.command: swapoff /swapfile
changed_when: true
ignore_errors: true
- name: Remove from fstab
ansible.posix.mount:
path: none
src: /swapfile
fstype: swap
state: absent
- name: Delete swap file
ansible.builtin.file:
path: /swapfile
state: absent
Monitor Swap Usage
- name: Check swap usage
ansible.builtin.shell: |
free -m | awk '/Swap/ {printf "total=%sMB used=%sMB free=%sMB usage=%s%%\n", $2, $3, $4, ($3/$2)*100}'
register: swap_info
changed_when: false
- name: Alert if swap usage > 80%
ansible.builtin.fail:
msg: "High swap usage on {{ inventory_hostname }}: {{ swap_info.stdout }}"
when: swap_info.stdout | regex_search('usage=(\d+)', '\\1') | first | int > 80
ignore_errors: true
Conditional Swap Creation
- name: Create swap only if RAM < 4GB
block:
- name: Create 2GB swap file
ansible.builtin.command: dd if=/dev/zero of=/swapfile bs=1M count=2048
args:
creates: /swapfile
- name: Setup swap
ansible.builtin.shell: |
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
when: ansible_memtotal_mb < 4096
Recommended Swap Sizes
| RAM | Swap (No Hibernation) | Swap (With Hibernation) |
|---|---|---|
| ≤ 2 GB | 2× RAM | 3× RAM |
| 2–8 GB | Equal to RAM | 2× RAM |
| 8–64 GB | ≥ 4 GB | 1.5× RAM |
| > 64 GB | ≥ 4 GB | Not recommended |
# Auto-calculate swap size
- name: Calculate swap size
ansible.builtin.set_fact:
swap_size_mb: >-
{{ [ansible_memtotal_mb, 4096] | min
if ansible_memtotal_mb > 8192
else ansible_memtotal_mb }}
Troubleshooting
"swapon: /swapfile: insecure permissions"
Swap file must be 0600:
- ansible.builtin.file:
path: /swapfile
mode: '0600'
owner: root
"swapon failed: Invalid argument"
The file wasn't formatted with mkswap:
- ansible.builtin.command: mkswap /swapfile
Swap Not Persisting After Reboot
Ensure fstab entry exists:
- ansible.posix.mount:
src: /swapfile
path: none
fstype: swap
opts: sw
state: present
Related Articles
Conclusion
Ansible manages swap with dd or fallocate to create the file, mkswap to format, swapon to enable, and ansible.posix.mount to persist in fstab. Tune vm.swappiness (10 for servers, 60 for desktops) and vm.vfs_cache_pressure via ansible.posix.sysctl. Auto-calculate swap sizes from ansible_memtotal_mb for dynamic provisioning across heterogeneous fleets.