Platform agnostic roles #3

Open
opened 2026-07-23 17:43:19 +02:00 by alessandrovitali · 1 comment
Owner

Follow formal Ansible best practices to make roles platform agnostic (without using janky if conditionals / ternary filters), e.g:

  1. Create a vars/ directory in the role.
  2. Create vars/Debian.yml containing:
    ssh_service_name: ssh
    
  3. Create vars/RedHat.yml (and any other families you wish to support) containing:
    ssh_service_name: sshd
    
  4. Load them dynamically at the start of tasks/main.yml:
    - name: Load OS-specific variables
      ansible.builtin.include_vars: "{{ ansible_facts['os_family'] }}.yml"
    
  5. Reference the variable in your handler:
    - name: Restart sshd
      ansible.builtin.service:
        name: "{{ ssh_service_name }}"
        state: restarted
    
Follow formal Ansible best practices to make roles platform agnostic (without using janky if conditionals / ternary filters), e.g: 1. Create a `vars/` directory in the role. 2. Create `vars/Debian.yml` containing: ```yaml ssh_service_name: ssh ``` 3. Create `vars/RedHat.yml` (and any other families you wish to support) containing: ```yaml ssh_service_name: sshd ``` 4. Load them dynamically at the start of `tasks/main.yml`: ```yaml - name: Load OS-specific variables ansible.builtin.include_vars: "{{ ansible_facts['os_family'] }}.yml" ``` 5. Reference the variable in your handler: ```yaml - name: Restart sshd ansible.builtin.service: name: "{{ ssh_service_name }}" state: restarted
Author
Owner

for different tasks: split tasks into OS-specific files, like

docker/
└── tasks
    ├── main.yml      # The "router"
    ├── debian.yml    # Debian/Ubuntu tasks
    ├── redhat.yml    # RHEL/CentOS/Rocky tasks
    └── alpine.yml    # Alpine tasks
  1. The Controller (tasks/main.yml)
    This main file acts as a traffic controller. It checks the host's operating system family and loads the correct tasks dynamically using ansible_os_family:
---
- name: Include OS-specific Docker installation tasks
  ansible.builtin.include_tasks: "{{ ansible_os_family | lower }}.yml"

- name: Start and enable Docker service
  ansible.builtin.service:
    name: docker
    state: started
    enabled: true
(Note: We use ansible.builtin.service at the end because it acts as a generic wrapper that dynamically translates to systemd on Ubuntu/RHEL, and openrc on Alpine.)
  1. Debian/Ubuntu (tasks/debian.yml)
    The modern, warning-free DEB822 approach:
---
- name: Install Debian/Ubuntu prerequisites
  ansible.builtin.apt:
    name:
      - ca-certificates
      - curl
      - python3-debian
    state: present
    update_cache: true

- name: Add Docker official APT repository (DEB822 format)
  ansible.builtin.deb822_repository:
    name: docker
    types: deb
    uris: "https://download.docker.com/linux/{{ ansible_distribution | lower }}"
    suites: "{{ ansible_distribution_release }}"
    components: stable
    signed_by: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
    state: present

- name: Install modern Docker packages
  ansible.builtin.apt:
    name:
      - docker-ce
      - docker-ce-cli
      - containerd.io
      - docker-buildx-plugin
      - docker-compose-plugin
    state: present
  1. RedHat/Rocky/AlmaLinux (tasks/redhat.yml)
    RHEL-based distributions use .repo files managed via dnf/yum:
---
- name: Add Docker official YUM repository
  ansible.builtin.yum_repository:
    name: docker-ce
    description: Docker CE Stable - $basearch
    baseurl: "https://download.docker.com/linux/centos/{{ ansible_distribution_major_version }}/$basearch/stable"
    gpgkey: https://download.docker.com/linux/centos/gpg
    gpgcheck: true
    enabled: true

- name: Install Docker packages
  ansible.builtin.dnf:
    name:
      - docker-ce
      - docker-ce-cli
      - containerd.io
      - docker-buildx-plugin
      - docker-compose-plugin
    state: present
  1. Alpine Linux (tasks/alpine.yml)
    Alpine doesn't use Docker's upstream GPG repositories; instead, Alpine packages Docker natively inside its own official community repository:
---
- name: Install Docker and Docker Compose on Alpine
  community.general.apk:
    name:
      - docker
      - docker-cli-compose
    state: present
    update_cache: true
for different tasks: split tasks into OS-specific files, like ``` docker/ └── tasks ├── main.yml # The "router" ├── debian.yml # Debian/Ubuntu tasks ├── redhat.yml # RHEL/CentOS/Rocky tasks └── alpine.yml # Alpine tasks ``` 1. The Controller (tasks/main.yml) This main file acts as a traffic controller. It checks the host's operating system family and loads the correct tasks dynamically using ansible_os_family: ```yaml --- - name: Include OS-specific Docker installation tasks ansible.builtin.include_tasks: "{{ ansible_os_family | lower }}.yml" - name: Start and enable Docker service ansible.builtin.service: name: docker state: started enabled: true (Note: We use ansible.builtin.service at the end because it acts as a generic wrapper that dynamically translates to systemd on Ubuntu/RHEL, and openrc on Alpine.) ``` 2. Debian/Ubuntu (tasks/debian.yml) The modern, warning-free DEB822 approach: ```yaml --- - name: Install Debian/Ubuntu prerequisites ansible.builtin.apt: name: - ca-certificates - curl - python3-debian state: present update_cache: true - name: Add Docker official APT repository (DEB822 format) ansible.builtin.deb822_repository: name: docker types: deb uris: "https://download.docker.com/linux/{{ ansible_distribution | lower }}" suites: "{{ ansible_distribution_release }}" components: stable signed_by: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg" state: present - name: Install modern Docker packages ansible.builtin.apt: name: - docker-ce - docker-ce-cli - containerd.io - docker-buildx-plugin - docker-compose-plugin state: present ``` 3. RedHat/Rocky/AlmaLinux (tasks/redhat.yml) RHEL-based distributions use .repo files managed via dnf/yum: ```yaml --- - name: Add Docker official YUM repository ansible.builtin.yum_repository: name: docker-ce description: Docker CE Stable - $basearch baseurl: "https://download.docker.com/linux/centos/{{ ansible_distribution_major_version }}/$basearch/stable" gpgkey: https://download.docker.com/linux/centos/gpg gpgcheck: true enabled: true - name: Install Docker packages ansible.builtin.dnf: name: - docker-ce - docker-ce-cli - containerd.io - docker-buildx-plugin - docker-compose-plugin state: present ``` 4. Alpine Linux (tasks/alpine.yml) Alpine doesn't use Docker's upstream GPG repositories; instead, Alpine packages Docker natively inside its own official community repository: ```yaml --- - name: Install Docker and Docker Compose on Alpine community.general.apk: name: - docker - docker-cli-compose state: present update_cache: true ```
alessandrovitali added the enhancement label 2026-08-16 23:53:51 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: studio/ansible#3