--- # ============================================================================= # Configure Swap on Systems Without It # ============================================================================= # This playbook creates and enables a swap file on systems that don't have # swap configured, bringing them into CLAUDE.md compliance. # # Usage: # ansible-playbook playbooks/configure_swap.yml # ansible-playbook playbooks/configure_swap.yml --limit pihole # # Tags: # - swap: All swap-related tasks # - validate: Validation tasks only # ============================================================================= - name: Configure Swap on Systems Without Adequate Swap hosts: all become: yes gather_facts: yes vars: swap_file_path: /swapfile swap_size_mb: 2048 # 2GB - CLAUDE.md compliant swap_minimum_mb: 512 # Only configure if less than this tasks: - name: Check current swap configuration command: swapon --show --bytes register: current_swap changed_when: false failed_when: false tags: [swap, validate] - name: Parse current swap size set_fact: current_swap_mb: >- {% if current_swap.stdout_lines | length > 1 %} {{ (current_swap.stdout_lines[1].split()[2] | int / 1024 / 1024) | int }} {% else %} 0 {% endif %} tags: [swap] - name: Display current swap status debug: msg: - "Current swap size: {{ current_swap_mb }} MB" - "Target swap size: {{ swap_size_mb }} MB" - "Will configure swap: {{ current_swap_mb | int < swap_minimum_mb }}" tags: [swap] - name: Configure swap if needed block: - name: Check if swap file already exists stat: path: "{{ swap_file_path }}" register: swap_file_stat - name: Check available disk space shell: df -BM {{ swap_file_path | dirname }} | tail -1 | awk '{print $4}' | sed 's/M//' register: available_space changed_when: false - name: Verify sufficient disk space assert: that: - available_space.stdout | int > swap_size_mb | int fail_msg: "Insufficient disk space. Available: {{ available_space.stdout }}MB, Required: {{ swap_size_mb }}MB" success_msg: "Sufficient disk space available: {{ available_space.stdout }}MB" - name: Create swap file command: dd if=/dev/zero of={{ swap_file_path }} bs=1M count={{ swap_size_mb }} args: creates: "{{ swap_file_path }}" register: swap_file_created tags: [swap] - name: Set correct permissions on swap file file: path: "{{ swap_file_path }}" mode: '0600' owner: root group: root tags: [swap] - name: Format swap file command: mkswap {{ swap_file_path }} when: swap_file_created is changed register: swap_formatted tags: [swap] - name: Enable swap file command: swapon {{ swap_file_path }} when: - swap_file_path not in current_swap.stdout - swap_formatted is succeeded or swap_file_stat.stat.exists register: swap_enabled tags: [swap] - name: Check if swap is in fstab lineinfile: path: /etc/fstab regexp: "^{{ swap_file_path }}" state: absent check_mode: yes register: fstab_check changed_when: false tags: [swap] - name: Add swap to fstab for persistence lineinfile: path: /etc/fstab line: "{{ swap_file_path }} none swap sw 0 0" state: present backup: yes when: fstab_check is not changed tags: [swap] - name: Verify swap is active command: swapon --show register: final_swap changed_when: false tags: [swap, validate] - name: Get swap usage statistics command: free -h register: swap_stats changed_when: false tags: [swap, validate] - name: Display swap configuration success debug: msg: - "=== Swap Configuration Complete ===" - "Swap file: {{ swap_file_path }}" - "Size: {{ swap_size_mb }} MB" - "Active swaps:" - "{{ final_swap.stdout_lines }}" - "" - "Memory status:" - "{{ swap_stats.stdout_lines }}" tags: [swap] rescue: - name: Swap configuration failed - cleanup debug: msg: - "=== Swap Configuration Failed ===" - "Error occurred during swap configuration" - "Attempting cleanup..." - name: Disable swap file if partially configured command: swapoff {{ swap_file_path }} failed_when: false tags: [swap] - name: Remove incomplete swap file file: path: "{{ swap_file_path }}" state: absent when: swap_file_created is changed failed_when: false tags: [swap] - name: Fail with error message fail: msg: | Swap configuration failed. Please check: 1. Sufficient disk space ({{ swap_size_mb }}MB required) 2. Permissions to create {{ swap_file_path }} 3. System logs: journalctl -xe when: current_swap_mb | int < swap_minimum_mb - name: Swap already configured adequately debug: msg: - "Swap is already configured with {{ current_swap_mb }}MB" - "No action needed (minimum: {{ swap_minimum_mb }}MB)" when: current_swap_mb | int >= swap_minimum_mb tags: [swap, validate] - name: Update system swappiness (optional optimization) sysctl: name: vm.swappiness value: '10' state: present reload: yes when: current_swap_mb | int >= swap_minimum_mb or swap_enabled is changed tags: [swap]