Getting started
david_igou.armbian manages Armbian-based ARM SBCs end to end: building
a custom Armbian image, writing it to a board, and provisioning a regular
login user — all with single-purpose, parameter-driven roles composed by
workflow playbooks. This page walks through the simplest use: build a
regular Armbian image, flash it to an SD card, and bootstrap a login user.
No netboot server, no router, no PXE patches.
For the PXE-netboot workflow (custom PXE-first image, NFS rootfs, and RouterOS-driven boot-mode convergence), see PXE netboot. Per-role inputs and outputs are documented in the role reference.
Every example threads the same concrete board — orange-pi-5-pro-01 —
so the variables read straight across.
Note
Early-stage 0.0.x — expect breaking changes between releases. Pin a
specific version in your requirements.yml.
The setup
Install the collection:
ansible-galaxy collection install david_igou.armbian
The examples below assume this inventory shape: a Docker-capable
builder that runs armbian/build, and the board itself.
Replace the two hosts with your own and adjust addresses; everything
else is verbatim:
# inventory/hosts.yml
all:
children:
armbian_builders:
hosts:
builder-01:
ansible_host: 192.0.2.5
boards:
hosts:
orange-pi-5-pro-01:
ansible_host: 192.0.2.111
ansible_user: armbian
# inventory/group_vars/all.yml
armbian_default_password: "1234"
The build
image_build runs armbian/build in Docker mode on the builder
host and writes a .img.xz plus a manifest.json to
$HOME/armbian_build/output/<host>/. A regular SD-bootable image
needs no userpatches — board, branch, and release are the only inputs.
Drop this into playbooks/local/build.yml:
---
- name: Build a regular Armbian image for orange-pi-5-pro-01
hosts: builder-01
gather_facts: true
tasks:
- ansible.builtin.include_role:
name: david_igou.armbian.image_build
vars:
armbian_build_board: orangepi5pro
armbian_build_host: orange-pi-5-pro-01
armbian_build_branch: current
armbian_build_release: bookworm
ansible-playbook playbooks/local/build.yml
The output on the builder:
$HOME/armbian_build/output/
└── orange-pi-5-pro-01/
├── Armbian_26.2.0-trunk_Orangepi5pro_bookworm_current_6.12.img.xz
├── Armbian_26.2.0-trunk_Orangepi5pro_bookworm_current_6.12.img.xz.sha
└── manifest.json
The accompanying manifest.json records what was built; the role uses
it as its idempotency key on subsequent runs (re-running build.yml
is a no-op until board, branch, release, armbian_build_ref,
or armbian_build_userpatches change):
{
"patch_hash": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"armbian_build_ref": "v26.2.0-trunk.844",
"board": "orangepi5pro",
"branch": "current",
"release": "bookworm",
"image_filename": "Armbian_26.2.0-trunk_Orangepi5pro_bookworm_current_6.12.img.xz",
"built_at": "2026-05-30T12:34:56Z"
}
Flash the SD card
The image_build role only produces the .img.xz; flashing is a
manual step because disk_image can’t write to a board’s own boot
disk. Copy the image off the builder and write it to an SD card on your
workstation:
scp builder-01:armbian_build/output/orange-pi-5-pro-01/Armbian_26.2.0-trunk_Orangepi5pro_bookworm_current_6.12.img.xz .
# Identify the SD card; double-check before running dd.
lsblk
xz -dc Armbian_26.2.0-trunk_Orangepi5pro_bookworm_current_6.12.img.xz \
| sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
Insert the SD card in the board, power it on, and confirm it’s reachable on the address you set in inventory:
ssh root@192.0.2.111 # password: 1234
Bootstrap the board
A freshly flashed Armbian image only has the root user with the
default password ("1234"). bootstrap_armbian connects as root,
provisions your inventory user with passwordless sudo + SSH-key login,
drops Armbian’s first-login TUI, and disables password authentication.
Drop this into playbooks/local/bootstrap.yml:
---
- name: Bootstrap orange-pi-5-pro-01 with an SSH-key login user
hosts: orange-pi-5-pro-01
gather_facts: false
vars:
# Connect as root with the default Armbian password — this is the
# only user that exists before bootstrap runs. After this playbook
# succeeds, subsequent plays connect as `armbian` (ansible_user in
# inventory) using key auth.
ansible_user: root
ansible_password: "1234"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
ansible_become: false
roles:
- role: david_igou.armbian.bootstrap_armbian
vars:
armbian_bootstrap_user: armbian
armbian_bootstrap_ssh_keys:
- "ssh-ed25519 AAAA...your-public-key... you@workstation"
ansible-playbook playbooks/local/bootstrap.yml
The role leaves the board in this state — a regular armbian user
with key-only login and passwordless sudo:
/home/armbian/.ssh/authorized_keys # the supplied public key(s)
/etc/sudoers.d/armbian # mode 0440, visudo-validated
# /etc/sudoers.d/armbian
armbian ALL=(ALL) NOPASSWD: ALL
It also removes /root/.not_logged_in_yet (Armbian’s first-login TUI)
and sets PasswordAuthentication no in /etc/ssh/sshd_config so the
next reboot is key-only. Verify with key auth:
ssh armbian@192.0.2.111
From here the board is a regular Ansible target. Re-running
bootstrap.yml reconciles authorized_keys and is otherwise a no-op.
Where to next
Other roles work standalone too — disk_image streams an .img.xz
onto a block device (run from a board booted from a different device),
and disk_provision applies a declarative GPT layout to a local disk.
For the full PXE-netboot workflow that builds a PXE-first image, carves out per-host NFS rootfs on a netboot server, and drives boot-mode convergence via RouterOS, see PXE netboot.