Automate Fedora IoT Configuration on a Raspberry Pi 4 with Ansible

Creating a Reusable Playbook

Ricardo Gerardi
The Pragmatic Programmers
5 min readDec 28, 2023

--

https://pragprog.com/newsletter/
https://pragprog.com/newsletter/
In this article:
* Test Connectivity with Raspberry Pi
* Create the Ansible Playbook
* Execute the Playbook
* What's Next?

Create an Ansible playbook that sets the hostname, adds a new user, layers additional packages, and more on your Fedora IoT-based Raspberry Pi.

In Install Fedora IoT on Raspberry Pi 4, I explained how to install Fedora IoT. If you followed along with the article, you have a functional Raspberry Pi 4 system with the latest updates but no configuration.

In this article, I’ll use Ansible to automate the device configuration by creating a playbook that sets the hostname, adds a new user, layers additional packages, and more.

By default, Fedora IoT comes with Python preinstalled. Together with Secure Shell (SSH), it has everything needed to support Ansible automation as a client. To follow along with this example, you need Ansible installed in a “control” machine that has access to the Raspberry Pi.

Test Connectivity with Raspberry Pi

Before working on the playbook, ensure Ansible can talk to the Raspberry Pi. To do this, first create an inventory file with connection details. You’ll use this inventory file again later to execute the playbook.

Create the inventory file inventory.yaml with this content, replacing the IP address and SSH key with the ones appropriate for your environment:

all:
children:
edge:
vars:
ansible_ssh_private_key_file: /home/ricardo/.ssh/id_rsa
ansible_ssh_user: root
hosts:
rpi4iot:
ansible_host: 192.168.10.152

Then run ansible with the ping module to test connectivity:

$ ansible edge -i inventory.yaml -m ping
rpi4iot | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}

Create the Ansible Playbook

Ansible is highly flexible and you can use it to configure every aspect of your Raspberry Pi, including deploying the applications you want to run on it. For this example, I’m starting with the basic configuration.

This playbook has four goals:

  1. Adding a new unprivileged user with sudo access to avoid using root to connect to the system.
  2. Configure the system hostname.
  3. Deploy additional required packages layered on top of the base image: tmux
    htop
    cockpit
    cockpit-podman
  4. Enable Cockpit to start on boot

You can use this playbook as a starting point to add your own configurations later.

In addition to the builtin collection, you need to install two additional collections to enable Ansible to support these goals: ansible.posix to update firewall rules and community.general to manage sudoers files and layer new packages to ostree. Install them using ansible-galaxy:

$ ansible-galaxy collection install ansible.posix community.general

Then create the playbook playbook.yaml with this content. Replace the variables with values that are appropriate for your environment:

---
- name: Configure Fedora IoT on Raspberry Pi
hosts: edge
gather_facts: true
vars:
user_name: ricardo
user_full_name: Ricardo
user_ssh_pub_key: /home/ricardo/.ssh/id_rsa.pub
tasks:
- name: Define hostname
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"

- name: Add unprivileged user
ansible.builtin.user:
name: "{{ user_name }}"
comment: "{{ user_full_name }}"
uid: 1000
group: wheel
state: present

- name: Set authorized key for new user
ansible.posix.authorized_key:
user: "{{ user_name }}"
state: present
key: "{{ lookup('file', user_ssh_pub_key) }}"

- name: Allow group wheel sudo access no password
community.general.sudoers:
name: wheel-all
group: wheel
commands: ALL
nopassword: true

- name: Ensure packages tmux, htop, and cockpit are available
community.general.rpm_ostree_pkg:
name:
- tmux
- htop
- cockpit
- cockpit-podman
state: present
register: ostree_results

- name: Reboot system to enable new packages
ansible.builtin.reboot:
reboot_timeout: 600
when:
- ostree_results is changed

- name: Ensure Cockpit socket is started and enabled
ansible.builtin.systemd:
name: cockpit.socket
state: started
enabled: true

- name: Allow access to Cockpit
ansible.posix.firewalld:
service: cockpit
permanent: true
state: enabled
immediate: true

Notice that I added a when condition to the "Reboot" task to execute only if the previous task makes a change to the system. This enables the playbook to be idempotent, ensuring the system reboots only if needed.

Execute the Playbook

Now, run the playbook using the inventory file inventory.yaml that you created before:

$ ansible-playbook -i inventory.yaml playbook.yaml 

PLAY [Configure Fedora IoT on Raspberry Pi] ***********************************

TASK [Gathering Facts] ********************************************************
ok: [rpi4iot]

TASK [Define hostname] ********************************************************
changed: [rpi4iot]

TASK [Add unprivileged user] **************************************************
changed: [rpi4iot]

TASK [Set authorized key for new user] ****************************************
changed: [rpi4iot]

TASK [Allow group wheel sudo access no password] ******************************
changed: [rpi4iot]

TASK [Ensure packages tmux, htop, and cockpit are available] ******************
changed: [rpi4iot]

TASK [Reboot system to enable new packages] ***********************************
changed: [rpi4iot]

TASK [Ensure Cockpit socket is started and enabled] ***************************
changed: [rpi4iot]

TASK [Allow access to Cockpit] ************************************************
changed: [rpi4iot]

PLAY RECAP ********************************************************************
rpi4iot : ok=9 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Now you can access the Raspberry Pi with the regular user you created instead of root:

$ ssh -i /home/ricardo/.ssh/id_rsa 192.168.10.152
Boot Status is GREEN - Health Check SUCCESS
Web console: https://rpi4iot:9090/ or https://192.168.10.152:9090/

Last login: Thu Mar 9 05:28:28 2023 from 192.168.10.122
[ricardo@rpi4iot ~]$

Notice that the hostname is updated and Cockpit is available.

What’s Next?

Your Fedora IoT on Raspberry Pi looks much better now — even with a basic configuration. Use this Ansible automation playbook as a starting point and add remaining configurations according to your requirements. The best part is that it’s reproducible. If you have an issue or need to reinstall the system, you can use the same playbook and, in a few minutes, your Raspberry Pi will be ready again.

Now the system is ready to run workloads like the container-based home automation application I want to run on mine. But before that, in the next article, I’ll show how to use Greenboot to run health checks and ensure the system runs smoothly and resiliently.

--

--

Ricardo Gerardi
The Pragmatic Programmers

Geek, father, consultant, writer. Author of Powerful Command-Line Applications in Go. I also write for many online technical publications. Go, Linux, k8s, Vim.