Skip to main content

Automate Fedora IoT configuration on a Raspberry Pi 4 with Ansible

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

Photo by Jeff Loucks on Unsplash

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.

[ Get started with IT automation with the Red Hat Ansible Automation Platform beginner's guide. ]

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.

Write your first playbook in this hands-on interactive lab. ]

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. The line "Ensure packages tmux, htop, and cockpit are available" does make a change to the system. This enables the playbook to be idempotent, ensuring the system reboots only if needed.

[ Download now: A system administrator's guide to IT automation. ]

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.

[ Download the Raspberry Pi cheat sheet. ]

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.

Topics:   Automation   Linux   Edge computing  
Author’s photo

Ricardo Gerardi

Ricardo Gerardi is Technical Community Advocate for Enable Sysadmin and Enable Architect. He was previously a senior consultant at Red Hat Canada, where he specialized in IT automation with Ansible and OpenShift.  More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.