├── .ansible-lint ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .yamllint ├── Dockerfile ├── LICENSE.txt ├── README.md ├── Vagrantfile ├── defaults └── main.yml ├── files └── empty ├── handlers └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── collections.yml │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ └── verify.yml ├── requirements.yml ├── tasks └── main.yml ├── templates └── empty ├── tests ├── inventory ├── test.yml └── vagrant.yml └── vars └── main.yml /.ansible-lint: -------------------------------------------------------------------------------- 1 | --- 2 | warn_list: 3 | - role-name 4 | - name[play] 5 | - name[casing] 6 | - no-handler 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 'on': 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: '30 1 * * 3' 10 | 11 | jobs: 12 | 13 | lint: 14 | name: Lint 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Check out the codebase 18 | uses: actions/checkout@v3 19 | 20 | - name: Set up Python 3 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.x' 24 | 25 | - name: Install test dependencies 26 | run: | 27 | pip install ansible-lint 28 | ansible-galaxy install -r requirements.yml 29 | 30 | - name: Lint code 31 | run: | 32 | yamllint . 33 | ansible-lint 34 | 35 | molecule: 36 | name: Molecule 37 | runs-on: ubuntu-latest 38 | defaults: 39 | run: 40 | working-directory: "${{ github.repository }}" 41 | needs: 42 | - lint 43 | strategy: 44 | fail-fast: false 45 | matrix: 46 | include: 47 | - distro: debian10 48 | ansible-version: '>=9, <10' 49 | - distro: debian11 50 | - distro: debian12 51 | - distro: ubuntu1804 52 | ansible-version: '>=9, <10' 53 | - distro: ubuntu2004 54 | - distro: ubuntu2204 55 | - distro: ubuntu2404 56 | 57 | steps: 58 | - name: Check out the codebase 59 | uses: actions/checkout@v3 60 | with: 61 | path: "${{ github.repository }}" 62 | 63 | - name: Set up Python 3 64 | uses: actions/setup-python@v4 65 | with: 66 | python-version: '3.x' 67 | 68 | - name: Install test dependencies 69 | run: | 70 | pip install 'ansible${{ matrix.ansible-version }}' molecule-plugins[docker] docker 71 | - name: Run Molecule tests 72 | run: | 73 | molecule test 74 | env: 75 | ANSIBLE_FORCE_COLOR: '1' 76 | ANSIBLE_VERBOSITY: '2' 77 | MOLECULE_DEBUG: '1' 78 | MOLECULE_DISTRO: "${{ matrix.distro }}" 79 | PY_COLORS: '1' 80 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release 3 | 'on': 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | 10 | release: 11 | name: Release 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Check out the codebase 15 | uses: actions/checkout@v3 16 | 17 | - name: Publish to Galaxy 18 | uses: robertdebock/galaxy-action@1.2.0 19 | with: 20 | galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | 12 | # IDE files # 13 | ################# 14 | /.settings 15 | /.buildpath 16 | /.project 17 | /nbproject 18 | *.komodoproject 19 | *.kpf 20 | /.idea 21 | 22 | # Vagrant files # 23 | .virtualbox/ 24 | .vagrant/ 25 | vagrant_ansible_inventory_* 26 | ansible.cfg 27 | 28 | # Other files # 29 | ############### 30 | !empty 31 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | braces: 6 | max-spaces-inside: 1 7 | level: error 8 | brackets: 9 | max-spaces-inside: 1 10 | level: error 11 | line-length: disable 12 | truthy: disable 13 | 14 | ignore: | 15 | .tox/ 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | MAINTAINER Mischa ter Smitten 3 | 4 | ENV LANG C.UTF-8 5 | ENV LC_ALL C.UTF-8 6 | 7 | # python 8 | RUN apt-get update && \ 9 | DEBIAN_FRONTEND=noninteractive apt-get install -y python3-minimal python3-dev curl && \ 10 | apt-get clean 11 | RUN curl -sL https://bootstrap.pypa.io/pip/3.6/get-pip.py | python3 - 12 | RUN rm -rf $HOME/.cache 13 | 14 | # ansible 15 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python3-apt && \ 16 | apt-get clean 17 | RUN pip3 install ansible==2.10.7 18 | RUN rm -rf $HOME/.cache 19 | 20 | # provision 21 | COPY . /etc/ansible/roles/ansible-role 22 | WORKDIR /etc/ansible/roles/ansible-role 23 | RUN ansible-playbook -i tests/inventory tests/test.yml --connection=local 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Oefenweb.nl 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## swapfile 2 | 3 | [![CI](https://github.com/Oefenweb/ansible-swapfile/workflows/CI/badge.svg)](https://github.com/Oefenweb/ansible-swapfile/actions?query=workflow%3ACI) 4 | [![Ansible Galaxy](http://img.shields.io/badge/ansible--galaxy-swapfile-blue.svg)](https://galaxy.ansible.com/Oefenweb/swapfile) 5 | 6 | Ansible role to manage a swap file in Debian-like systems. 7 | 8 | #### Requirements 9 | 10 | * `fallocate` (will be installed) 11 | 12 | ## Variables 13 | 14 | * `swapfile_size`: [default: `1G`, `false` to do nothing]: The size of the swap file to create in the format that `fallocate` expects: The length and offset arguments may be followed by binary (2^N) suffixes KiB, MiB, GiB, TiB, PiB and EiB (the "iB" is optional, e.g. "K" has the same meaning as "KiB") or decimal (10^N) suffixes KB, MB, GB, PB and EB. 15 | * `swapfile_swappiness`: [optional]: The swappiness percentage (`vm.swappiness`) -- the lower it is, the less your system swaps memory pages 16 | * `swapfile_vfs_cache_pressure`: [optional]: This percentage value controls the tendency of the kernel to reclaim the memory which is used for caching of directory and inode objects 17 | 18 | ## Dependencies 19 | 20 | None 21 | 22 | #### Example 23 | 24 | ```yaml 25 | - hosts: all 26 | roles: 27 | - oefenweb.swapfile 28 | ``` 29 | 30 | or: 31 | 32 | ```yaml 33 | - hosts: all 34 | roles: 35 | - role: oefenweb.swapfile 36 | swapfile_size: 1GB 37 | swapfile_swappiness: 10 38 | ``` 39 | 40 | #### License 41 | 42 | MIT 43 | 44 | #### Author Information 45 | 46 | Mischa ter Smitten (based on work of [kamaln7](https://github.com/kamaln7)) 47 | 48 | #### Feedback, bug-reports, requests, ... 49 | 50 | Are [welcome](https://github.com/Oefenweb/ansible-swapfile/issues)! 51 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby ts=2 sw=2 tw=0 et : 3 | 4 | role = File.basename(File.expand_path(File.dirname(__FILE__))) 5 | 6 | boxes = [ 7 | { 8 | :name => "ubuntu-1804", 9 | :box => "bento/ubuntu-18.04", 10 | :ip => '10.0.0.13', 11 | :cpu => "50", 12 | :ram => "384" 13 | }, 14 | { 15 | :name => "ubuntu-2004", 16 | :box => "bento/ubuntu-20.04", 17 | :ip => '10.0.0.14', 18 | :cpu => "50", 19 | :ram => "512" 20 | }, 21 | { 22 | :name => "ubuntu-2204", 23 | :box => "bento/ubuntu-22.04", 24 | :ip => '10.0.0.15', 25 | :cpu => "50", 26 | :ram => "512" 27 | }, 28 | { 29 | :name => "ubuntu-2404", 30 | :box => "bento/ubuntu-24.04", 31 | :ip => '10.0.0.16', 32 | :cpu => "50", 33 | :ram => "512" 34 | }, 35 | { 36 | :name => "debian-10", 37 | :box => "bento/debian-10", 38 | :ip => '10.0.0.18', 39 | :cpu => "50", 40 | :ram => "256" 41 | }, 42 | { 43 | :name => "debian-11", 44 | :box => "bento/debian-11", 45 | :ip => '10.0.0.19', 46 | :cpu => "50", 47 | :ram => "256" 48 | }, 49 | { 50 | :name => "debian-12", 51 | :box => "bento/debian-12", 52 | :ip => '10.0.0.20', 53 | :cpu => "50", 54 | :ram => "384" 55 | }, 56 | ] 57 | 58 | Vagrant.configure("2") do |config| 59 | boxes.each do |box| 60 | config.vm.define box[:name] do |vms| 61 | vms.vm.box = box[:box] 62 | vms.vm.hostname = "ansible-#{role}-#{box[:name]}" 63 | 64 | vms.vm.provider "virtualbox" do |v| 65 | v.customize ["modifyvm", :id, "--cpuexecutioncap", box[:cpu]] 66 | v.customize ["modifyvm", :id, "--memory", box[:ram]] 67 | end 68 | 69 | vms.vm.network :private_network, ip: box[:ip] 70 | 71 | vms.vm.provision :ansible do |ansible| 72 | ansible.playbook = "tests/vagrant.yml" 73 | ansible.verbose = "vv" 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | # defaults file 2 | --- 3 | swapfile_size: 1G 4 | -------------------------------------------------------------------------------- /files/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oefenweb/ansible-swapfile/6a69dd8167c6debdf8256d85e006ae5bf8916567/files/empty -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | # handlers file 2 | --- 3 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | # meta file 2 | --- 3 | galaxy_info: 4 | author: oefenweb 5 | role_name: swapfile 6 | company: Oefenweb.nl B.V. 7 | description: Manage a swap file in Debian-like systems 8 | license: MIT 9 | min_ansible_version: 2.10.0 10 | platforms: 11 | - name: Ubuntu 12 | versions: 13 | - bionic 14 | - focal 15 | - jammy 16 | - noble 17 | - name: Debian 18 | versions: 19 | - buster 20 | - bullseye 21 | - bookworm 22 | galaxy_tags: 23 | - system 24 | dependencies: [] 25 | -------------------------------------------------------------------------------- /molecule/default/collections.yml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: [] 3 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | become: true 5 | roles: 6 | - ../../../ 7 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2004}-ansible:latest" 9 | command: ${MOLECULE_DOCKER_COMMAND:-""} 10 | volumes: 11 | - /sys/fs/cgroup:/sys/fs/cgroup:rw 12 | - /var/lib/containerd 13 | cgroupns_mode: host 14 | privileged: true 15 | pre_build_image: true 16 | provisioner: 17 | name: ansible 18 | playbooks: 19 | prepare: prepare.yml 20 | converge: converge.yml 21 | verify: verify.yml 22 | -------------------------------------------------------------------------------- /molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: all 4 | become: true 5 | tasks: [] 6 | -------------------------------------------------------------------------------- /molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: all 4 | become: true 5 | tasks: [] 6 | -------------------------------------------------------------------------------- /requirements.yml: -------------------------------------------------------------------------------- 1 | # requirements file 2 | --- 3 | collections: 4 | - name: ansible.posix 5 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | # tasks file 2 | --- 3 | - name: install dependencies 4 | ansible.builtin.apt: 5 | name: "{{ swapfile_dependencies }}" 6 | state: "{{ apt_install_state | default('latest') }}" 7 | update_cache: true 8 | cache_valid_time: "{{ apt_update_cache_valid_time | default(3600) }}" 9 | tags: 10 | - configuration 11 | - swapfile 12 | - swapfile-install 13 | - swapfile-install-dependencies 14 | 15 | - name: swap file 16 | when: not swapfile_size | bool 17 | tags: 18 | - configuration 19 | - swapfile 20 | block: 21 | - name: write swap file # noqa command-instead-of-module 22 | ansible.builtin.command: > 23 | fallocate -l {{ swapfile_size }} {{ swapfile_file }} 24 | args: 25 | creates: "{{ swapfile_file }}" 26 | register: _write_swapfile 27 | tags: 28 | - swapfile-write-file 29 | 30 | - name: set swap file permissions 31 | ansible.builtin.file: 32 | path: "{{ swapfile_file }}" 33 | owner: root 34 | group: root 35 | mode: '0600' 36 | tags: 37 | - swapfile-set-file-permissions 38 | 39 | - name: create swap file # noqa command-instead-of-module 40 | ansible.builtin.command: > 41 | mkswap {{ swapfile_file }} 42 | register: _create_swapfile 43 | changed_when: true 44 | when: _write_swapfile is changed 45 | tags: 46 | - swapfile-mkswap 47 | 48 | - name: enable swapfile # noqa command-instead-of-module 49 | ansible.builtin.command: > 50 | swapon {{ swapfile_file }} 51 | changed_when: true 52 | when: _create_swapfile is changed 53 | tags: 54 | - swapfile-enable-swapfile 55 | 56 | - name: add swapfile to /etc/fstab 57 | ansible.posix.mount: 58 | name: none 59 | src: "{{ swapfile_file }}" 60 | fstype: swap 61 | opts: sw 62 | passno: '0' 63 | dump: '0' 64 | state: present 65 | tags: 66 | - swapfile-fstab 67 | 68 | - name: configure vm.swappiness 69 | ansible.posix.sysctl: 70 | name: vm.swappiness 71 | value: "{{ swapfile_swappiness | string }}" 72 | reload: true 73 | state: present 74 | when: swapfile_swappiness is defined 75 | tags: 76 | - configuration 77 | - swapfile 78 | - swapfile-vm-swappiness 79 | 80 | - name: configure vm.vfs_cache_pressure 81 | ansible.posix.sysctl: 82 | name: vm.vfs_cache_pressure 83 | value: "{{ swapfile_vfs_cache_pressure | string }}" 84 | reload: true 85 | state: present 86 | when: swapfile_vfs_cache_pressure is defined 87 | tags: 88 | - configuration 89 | - swapfile 90 | - swapfile-vm-vfs-cache-pressure 91 | -------------------------------------------------------------------------------- /templates/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oefenweb/ansible-swapfile/6a69dd8167c6debdf8256d85e006ae5bf8916567/templates/empty -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | # test file 2 | --- 3 | - name: converge 4 | hosts: localhost 5 | connection: local 6 | become: true 7 | roles: 8 | - ../../ 9 | -------------------------------------------------------------------------------- /tests/vagrant.yml: -------------------------------------------------------------------------------- 1 | # test file 2 | --- 3 | - name: converge 4 | hosts: all 5 | remote_user: vagrant 6 | become: true 7 | roles: 8 | - ../../ 9 | vars: 10 | swapfile_swappiness: 1 11 | swapfile_vfs_cache_pressure: 50 12 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | # vars file 2 | --- 3 | swapfile_dependencies: 4 | - util-linux 5 | swapfile_file: /swap 6 | --------------------------------------------------------------------------------