AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible on Alpine Linux 3.20 Automation Complete Guide

By Luca Berton · Published 2024-01-01 · Category: installation

Automate Alpine Linux 3.20 with Ansible: apk, OpenRC, musl, BusyBox, Docker/Podman hosts, lightweight container images, hardening.

Alpine Linux 3.20 (released May 2024) is the minimal, musl-based, BusyBox-anchored distribution behind most container base images. It ships OpenRC instead of systemd, the apk package manager, kernel 6.6 LTS, Python 3.12, and OpenSSH 9.7. Support runs 2 years from GA. Ansible's role on Alpine is twofold: build container images and manage Alpine VMs / hypervisor hosts. This is the master Ansible guide for Alpine 3.20.

Alpine Linux 3.20 release facts

| Item | Value | |---|---| | GA | 2024-05-22 | | Supported until | 2026-05 | | Default kernel | 6.6 LTS | | libc | musl | | Init | OpenRC | | Package manager | apk |

See also: How to install Ansible in Alpine Linux 3.20 — Ansible install

Ansible-core compatibility

Use ansible-core 2.18 LTS. The managed node needs Python:

- name: Bootstrap Python on Alpine before any module runs
  hosts: alpine
  gather_facts: false
  tasks:
    - name: Install python3 (raw)
      ansible.builtin.raw: apk add --no-cache python3 py3-pip
      changed_when: false

Inventory

[alpine]
alpine-01.example.com

[alpine:vars] ansible_user=root ansible_python_interpreter=/usr/bin/python3

See also: How to install Ansible in Alpine Linux

Baseline playbook

- name: Alpine 3.20 baseline
  hosts: alpine
  tasks:
    - name: Update apk index
      community.general.apk: { update_cache: true }

- name: Upgrade all packages community.general.apk: { upgrade: true }

- name: Install baseline packages community.general.apk: name: - vim - curl - htop - chrony - openssh - sudo - openrc - iptables - cronie state: present

- name: Enable services with OpenRC community.general.runit: # placeholder ansible.builtin.command: rc-update add {{ item }} default register: rc changed_when: "'added to runlevel' in rc.stdout" loop: - chronyd - sshd - cronie

Container engine setup (Podman or Docker)

- name: Install Podman on Alpine
  hosts: alpine
  tasks:
    - name: Install podman
      community.general.apk:
        name: [podman, fuse-overlayfs, slirp4netns]
        state: present

- name: Enable cgroups v2 ansible.builtin.lineinfile: path: /etc/rc.conf regexp: '^rc_cgroup_mode' line: 'rc_cgroup_mode="unified"'

- name: Add containers user ansible.builtin.user: name: containers shell: /bin/ash create_home: true

See also: Install Docker in Debian-like systems - Ansible module apt_key, apt_repository and apt

OpenRC service authoring

- name: Custom OpenRC service for an app
  hosts: alpine
  tasks:
    - name: Drop service file
      ansible.builtin.copy:
        dest: /etc/init.d/myapp
        mode: "0755"
        content: |
          #!/sbin/openrc-run
          name="myapp"
          command="/usr/local/bin/myapp"
          command_background=true
          pidfile="/run/myapp.pid"
          depend() {
              need net
              after firewall
          }

- name: Add to default runlevel ansible.builtin.command: rc-update add myapp default register: rc changed_when: "'added to runlevel' in rc.stdout"

- name: Start ansible.builtin.command: rc-service myapp start register: ss changed_when: "'Starting' in ss.stdout"

Hardening

- name: SSH hardening on Alpine
  hosts: alpine
  handlers:
    - name: restart sshd
      ansible.builtin.command: rc-service sshd restart
  tasks:
    - name: Hardened sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?{{ item.k }}'
        line: '{{ item.k }} {{ item.v }}'
      loop:
        - { k: 'PermitRootLogin',        v: 'no' }
        - { k: 'PasswordAuthentication', v: 'no' }
      notify: restart sshd

Best practices

• Always bootstrap Python via raw before non-trivial tasks. • Use community.general.apk not raw apk for idempotency. • Pin Alpine versions in container Dockerfiles (alpine:3.20) to match VM hosts. • Replace BusyBox with full coreutils only when scripts demand it; otherwise embrace minimalism.

Conclusion

Ansible on Alpine 3.20 needs slightly different patterns (raw Python bootstrap, OpenRC, apk) but delivers fast, lean hosts ideal for container runners, edge devices, and minimal VMs.

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home