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 |
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: falseSee also: How to install Ansible in Alpine Linux 3.20 — Ansible install
Inventory
[alpine]
alpine-01.example.com
[alpine:vars]
ansible_user=root
ansible_python_interpreter=/usr/bin/python3Baseline 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
- cronieSee also: How to install Ansible in Alpine Linux
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: trueOpenRC 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"See also: Install Docker in Debian-like systems - Ansible module apt_key, apt_repository and apt
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 sshdBest practices
- Always bootstrap Python via
rawbefore non-trivial tasks. - Use
community.general.apknot rawapkfor 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.
Installing Ansible on Alpine Linux
# Install via apk
apk add ansible
# Or minimal install
apk add python3 py3-pip
pip3 install ansible
# Verify
ansible --versionAlpine Package Management
- name: Manage Alpine Linux 3.20
hosts: alpine
become: true
vars:
ansible_python_interpreter: /usr/bin/python3
tasks:
- name: Install packages via apk
community.general.apk:
name:
- nginx
- git
- curl
- openssh
- sudo
state: present
update_cache: true
- name: Enable and start services
ansible.builtin.service:
name: "{{ item }}"
state: started
enabled: true
loop:
- nginx
- sshd
- name: Add community repository
ansible.builtin.lineinfile:
path: /etc/apk/repositories
line: "https://dl-cdn.alpinelinux.org/alpine/v3.20/community"
state: presentAlpine Firewall (iptables)
- name: Install iptables
community.general.apk:
name: iptables
state: present
- name: Allow SSH
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
destination_port: "22"
jump: ACCEPTFAQ
Why is Alpine popular for containers?
Alpine's minimal size (~5MB base) makes it ideal for container images. Ansible can manage Alpine containers or build Alpine-based images with consistent configuration.
Does Alpine use systemd?
No. Alpine uses OpenRC as its init system. The ansible.builtin.service module works with OpenRC. Use rc-update commands for service management.
Related Articles
Category: installation