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
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 tasksansible.builtin.include_tasks:"{{ ansible_os_family | lower }}.yml"- name:Start and enable Docker serviceansible.builtin.service:name:dockerstate:startedenabled: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.)
Debian/Ubuntu (tasks/debian.yml)
The modern, warning-free DEB822 approach:
RedHat/Rocky/AlmaLinux (tasks/redhat.yml)
RHEL-based distributions use .repo files managed via dnf/yum:
---- name:Add Docker official YUM repositoryansible.builtin.yum_repository:name:docker-cedescription:Docker CE Stable - $basearchbaseurl:"https://download.docker.com/linux/centos/{{ ansible_distribution_major_version }}/$basearch/stable"gpgkey:https://download.docker.com/linux/centos/gpggpgcheck:trueenabled:true- name:Install Docker packagesansible.builtin.dnf:name:- docker-ce- docker-ce-cli- containerd.io- docker-buildx-plugin- docker-compose-pluginstate:present
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 Alpinecommunity.general.apk:name:- docker- docker-cli-composestate:presentupdate_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
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow formal Ansible best practices to make roles platform agnostic (without using janky if conditionals / ternary filters), e.g:
vars/directory in the role.vars/Debian.ymlcontaining:vars/RedHat.yml(and any other families you wish to support) containing:tasks/main.yml:for different tasks: split tasks into OS-specific files, like
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:
The modern, warning-free DEB822 approach:
RHEL-based distributions use .repo files managed via dnf/yum:
Alpine doesn't use Docker's upstream GPG repositories; instead, Alpine packages Docker natively inside its own official community repository: