How to Properly Clean Up Unused Ansible Roles (Uninstall Packages, Remove Configs & Firewall Rules)


3 views

When transitioning a server's role (like converting a web server to a different purpose), we face a common infrastructure-as-code dilemma: Ansible excels at declaring desired states but lacks native "undo" functionality. Unlike Puppet's ensure => absent paradigm, Ansible requires explicit cleanup tasks.

For our NGINX example, we need to modify the role to include removal logic. Here's a task file (tasks/remove.yml) that should be included in your role:

---
- name: Remove NGINX package
  ansible.builtin.package:
    name: nginx
    state: absent

- name: Purge configuration files
  ansible.builtin.file:
    path: "{{ item }}"
    state: absent
  loop:
    - /etc/nginx
    - /var/www/html
    - /var/log/nginx

- name: Remove firewall rules
  ansible.posix.firewalld:
    service: "{{ item }}"
    permanent: yes
    state: disabled
    immediate: yes
  loop:
    - http
    - https
  when: ansible_os_family == 'RedHat'

Create a role variable (defaults/main.yml) to control removal behavior:

nginx_cleanup: false

Then modify your main tasks file (tasks/main.yml) with conditional inclusion:

---
- import_tasks: install.yml
  when: not nginx_cleanup

- import_tasks: remove.yml
  when: nginx_cleanup

For host-specific cleanup, use group variables. First remove the host from [webservers], then in group_vars/all.yml:

nginx_cleanup: "{{ 'webservers' not in group_names }}"

For comprehensive firewall cleanup, consider these additional approaches:

- name: Remove specific port rules
  ansible.posix.ufw:
    rule: deny
    port: "{{ item }}"
    proto: tcp
  loop:
    - 80
    - 443
  when: ansible_os_family == 'Debian'

Or for more complex scenarios using iptables directly:

- name: Remove NGINX-related iptables rules
  ansible.builtin.command: iptables -D INPUT -p tcp --dport {{ item }} -j ACCEPT
  loop:
    - 80
    - 443
  ignore_errors: yes

When transitioning servers between roles in Ansible infrastructure, residual configurations often remain. Unlike Puppet's declarative approach with ensure => absent, Ansible requires more deliberate cleanup strategies.

For complete removal of packages and configurations, create a removal playbook that reverses installation steps:

- name: Remove nginx and clean configurations
  hosts: former_webservers
  become: yes
  tasks:
    - name: Stop nginx service
      ansible.builtin.service:
        name: nginx
        state: stopped
        enabled: no

    - name: Remove nginx package
      ansible.builtin.package:
        name: nginx
        state: absent

    - name: Remove configuration directories
      ansible.builtin.file:
        path: "{{ item }}"
        state: absent
      loop:
        - /etc/nginx
        - /var/www/html
        - /var/log/nginx

Firewall rules require explicit removal in Ansible. The ansible.posix.firewall module provides clean removal:

- name: Clean up firewall rules
  ansible.posix.firewall:
    rule: "{{ item.rule }}"
    permanent: yes
    immediate: yes
    state: absent
  loop:
    - { rule: "service name=http" }
    - { rule: "service name=https" }

Implement a tagging system for reversible operations during initial role creation:

- name: Install nginx
  ansible.builtin.package:
    name: nginx
    state: present
  tags: nginx_install

- name: Configure firewall
  ansible.posix.firewall:
    rule: "service name=http"
    permanent: yes
    state: enabled
  tags: firewall_config

This allows selective cleanup using --tags when running the playbook in reverse.

Create a removal playbook that checks current state before removal:

- name: Verify nginx exists before removal
  ansible.builtin.command: which nginx
  register: nginx_exists
  ignore_errors: yes
  changed_when: false

- name: Remove nginx if exists
  ansible.builtin.package:
    name: nginx
    state: absent
  when: nginx_exists.rc == 0

Maintain separate inventory groups for transition periods:

[webservers:children]
active_webservers
decommissioning_webservers

This allows phased removal while maintaining visibility of servers in transition.