Thursday, November 27, 2025

Cloud-init on Raspberry Pi OS

As some of you may have already noticed, the latest Raspberry Pi OS release based on Debian Trixie now includes cloud-init. This marks the beginning of a transition away from our legacy first-boot customisation system based on the firstrun.sh script.

Cloud-init is a cross-platform, distribution-agnostic tool used to automatically configure systems on first boot. (Definition adapted from the official cloud-init documentation.) With it, you can provision your Raspberry Pi images with users, network settings, SSH keys, storage configurations, and much more — all without manually logging in after flashing the image.

How can I use it?

If you’ve downloaded the latest image (released on 2 October 2025), you’ll find that three new files have appeared on the boot partition. This is the FAT32 partition that your computer automatically mounts when you insert a freshly flashed Raspberry Pi OS microSD card. It already contains familiar files like config.txt, but now you’ll also see:

  • meta-data
  • network-config
  • user-data

For most users, meta-data can be left untouched — it simply enables cloud-init to process the other configuration files correctly. Advanced users may use it for more complex provisioning workflows, but it’s safe to ignore in typical setups.

Cloud-init uses YAML for its configuration files. If you’re new to YAML, it’s worth taking a quick look at the official documentation, as indentation and formatting matter. For now, we’ll focus on the two most relevant files: user-data and network-config.

General configuration (user-data)

The user-data file is the central place for your configuration. With the exception of networking, almost everything cloud-init sets up on first boot is controlled from here.

You can use it to create a default user, define your locale, install additional packages, configure SSH access, and much more — all of which is covered in the official cloud-init documentation.

Unlike many other distributions, Raspberry Pi OS includes a few Raspberry Pi–specific extensions for cloud-init configuration. These allow you to enable hardware interfaces such as I2C, SPI, serial, and 1-Wire, and even activate USB gadget mode (rpi-usb-gadget) automatically.

Here’s an example configuration that sets up a user and demonstrates all the currently supported Raspberry Pi–specific options:

#cloud-config

# Set the hostname for this device. This will also update /etc/hosts if manage_etc_hosts is enabled.
hostname: mypi2025
manage_etc_hosts: true

# Set the system timezone
timezone: Europe/London

# Create a default user account and apply permissions
users:
  - name: pi
    groups: users,adm,dialout,audio,netdev,video,plugdev,cdrom,games,input,gpio,spi,i2c,render,sudo
    shell: /bin/bash
    lock_passwd: false  # Set to true to disable password login entirely
    plain_text_password: mysecretpassword123  # Alternatively, use 'passwd:' with a hashed password for better security
    ssh_authorized_keys:
      - ssh-ed25519 mykeystuff  # Replace with your actual SSH public key
    sudo: ALL=(ALL) NOPASSWD:ALL  # Allow passwordless sudo for this user

# Raspberry Pi–specific options (provided by the cc_raspberry_pi module)
rpi:
    spi: true               # Enable SPI interface
    i2c: true               # Enable I2C interface
    serial: true            # Enable serial console and UART interface
    onewire: true           # Enable 1-Wire interface
    enable_usb_gadget: true # Enable USB gadget mode

# Additional Raspberry Pi OS option (not available on generic cloud-init images)
enable_ssh: true  # Enables the SSH server on first boot

# Optional: Disable SSH password authentication if using SSH keys only (recommended for security)
# ssh_pwauth: false

For more details, you can refer to the cc_raspberry_pi module in the official cloud-init documentation.

Note:
The #cloud-config header at the top of the file is mandatory — cloud-init will not process the file correctly without it.

Networking configuration (network-config)

The network-config file defines how your Raspberry Pi should set up its network interfaces on first boot. As the name suggests, this is where you configure Wi-Fi or Ethernet settings before ever powering on the device.

Here’s a simple example that connects your Raspberry Pi to a Wi-Fi network:

network:
  version: 2
  wifis:
    # Make sure the target is NetworkManager which is the default on Raspberry Pi OS
    renderer: NetworkManager
    # The connection name
    wlan0:
      dhcp4: true
      # !VERY IMPORTANT! Change this to the ISO/IEC 3166 country code for the country you want to use this microSD card in.
      regulatory-domain: "GB"
      access-points:
        "My Net-Work":
          password: "mysupersecretpassword"
      # Don’t wait at boot for this connection to connect successfully
      optional: true

When you power on your Raspberry Pi with this microSD card inserted, cloud-init will process this configuration and attempt to connect to the specified network automatically — allowing you to SSH in or continue working without needing to attach a screen or a keyboard.

You can configure far more than just basic Wi-Fi credentials: multiple networks, priority fallback, static IP assignments, VLANs, and more are supported. For a full reference, see the official cloud-init networking documentation.

With the introduction of cloud-init, Raspberry Pi OS also includes Netplan, a unified abstraction layer for network configuration used by several modern Linux distributions.

More about Netplan

Netplan is now the primary source of truth for networking on Raspberry Pi OS. It uses its own YAML-based configuration format and can render network settings for both systemd-networkd and NetworkManager, depending on which renderer you choose. The major advantage of this approach is portability — a Netplan configuration can be reused across any Linux distribution that supports it, regardless of whether it uses NetworkManager or networkd underneath.

To use Netplan directly, place your configuration files in /etc/netplan/ — this is also where cloud-init stores your generated network configuration from network-config without modification. From there, you can generate the active configuration using:

sudo netplan generate

This writes the appropriate configuration files for the selected backend (NetworkManager on Raspberry Pi OS). To activate the configuration, run:

sudo netplan apply

You can still use nmcli as usual to inspect or manage connections. Since many existing tools and scripts rely on nmcli or the NetworkManager D-Bus API, there needs to be a communication layer between Netplan and NetworkManager. Canonical provides three patches that enable this two-way interoperability, allowing NetworkManager to signal configuration changes back to Netplan.

For Raspberry Pi OS, we’ve gone a step further and introduced additional patches to improve this workflow:

  • NetworkManager will only interact with connections that use the netplan- prefix. If you want a new connection to be persisted by Netplan, give it that prefix when creating it, and it will be stored in Netplan’s configuration.
  • When generating profiles, NetworkManager loads all Netplan-defined connections and writes its interpreted runtime configuration back in a format Netplan can understand.
  • During this process, all .yaml and .yml files under /etc/netplan/ are cleared to avoid conflicting definitions across multiple layers.
  • This does not affect manually created connections stored in /etc/NetworkManager/system-connections/.
  • Any profiles generated at runtime by Netplan will appear under /run/NetworkManager/system-connections/ and will also use the netplan- prefix.

This approach ensures consistency between both systems and prevents configuration drift when editing or reloading profiles via NetworkManager tools.

Wrapping up

With cloud-init and Netplan now integrated into Raspberry Pi OS, first-boot provisioning becomes far more powerful, repeatable, and portable across different setups. Whether you’re configuring a single device or preparing dozens of Raspberry Pis for a classroom, a lab, or an IoT deployment, these new tools make it easy to define everything up front — users, networking, interfaces, and more — before the system even powers on.

With the release of Raspberry Pi Imager 2.0, cloud-init configuration for Raspberry Pi OS is now generated by default. This makes it easy to further customise your setup after writing the image — simply edit the generated user-data or network-config files on the boot partition. Imager 2.0 also understands the Raspberry Pi–specific rpi: options, so features like SPI or I2C can be enabled directly in the customisation UI.

The legacy method still works, but cloud-init and Netplan open the door to a much more flexible and modern workflow. We’ll continue expanding support for Raspberry Pi–specific cloud-init modules and streamlined provisioning features in future releases.

If you create interesting user-data or network-config templates, or have feedback about the new system, we’d love to hear from you in the forums.


Header image resources: Background designed by Freepik. Icons by ziadarts, Dimas Anom, and Gregor Cresnar via Flaticon.

The post Cloud-init on Raspberry Pi OS appeared first on Raspberry Pi.



from News - Raspberry Pi https://ift.tt/id3reS0

Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home