Skip to content

Instantly share code, notes, and snippets.

@bashtheshell
Last active July 1, 2024 12:57
Show Gist options
  • Save bashtheshell/010d70f7643f171096ad9462ea86324b to your computer and use it in GitHub Desktop.
Save bashtheshell/010d70f7643f171096ad9462ea86324b to your computer and use it in GitHub Desktop.
Brief tutorial on how to use Raspberry Pi Imager `rpi-imager --cli` command on macOS to be able to automate image re-creation.

How to Use Raspberry Pi's rpi-imager --cli Command on macOS

With the modern rpi-imager tool, we can automate the imaging process for the Raspberry Pi computer board and make the process extremely painless for us each time we need to re-image.

The official Raspberry Pi's rpi-imager's tool (which can be installed from https://www.raspberrypi.com/software/) contains a command-line option that's not widely documented anywhere at the time of this writing (v1.7.5 was the latest release).

The best official documentation I can possibly find on Raspberry Pi Imager did not cover the command-line option.

As a result, I'll only cover the command-line option for macOS here as it's my daily driver.

Install the Raspberry Pi Imager:

The first step is to simply install the Imager from the second link mentioned above (yes, it's a graphical app... we'll get there). Installation should be straightforward.

The app should be installed in the following location on macOS:

/Applications/Raspberry\ Pi\ Imager.app

Believe it or not, the app itself is a lot better than the alternatives (e.g. balenaEtcher) as there are a set of various Linux distros other than the Raspberry Pi OSes that you can choose from.

I now swear by it as I previously used balenaEtcher only for imaging without the other preloaded customization (i.e. setting up user account, configuring hostname, enabling wifi connectivity, and set up SSH public key for the said user) that I'd have to create separately.

Launch Raspberry Pi Imager from rpi-imager command:

To understand how the rpi-imager would behave on the command line, you'd need to at least understand how the graphical Raspberry Pi Imager tool operates.

The basic command to launch the tool is:

/Applications/Raspberry\ Pi\ Imager.app/Contents/MacOS/rpi-imager

But a more apt command would be the one with the debug option to reinforce our understanding:

/Applications/Raspberry\ Pi\ Imager.app/Contents/MacOS/rpi-imager --debug

Here are the available options listed as indicated from --help output (I slightly modified the output for readability). Although, each one won't be covered here. The --cli option will be covered later.

rpi-imager [--debug] [--version] [--repo <repository URL>] [--qm <custom qm translation file>] [--disable-telemetry] [<image file to write>]

-OR- 

rpi-imager --cli [--disable-verify] [--sha256 <expected hash>] [--debug] [--quiet] <image file to write> <destination drive device>

Image your SD card with the graphical setup:

At this step, you should have the graphical Raspberry Pi Imager launched with the rpi-imager --debug command.

You will be creating an image with the customization here, which you can later re-use if you need to burn the image again with the same customization. Those steps only need to be done once (i.e. the resulting image is what you anticipated). Otherwise, you'd need to redo the steps again.

The steps should be intuitive to follow:

  • Choose your Operating System (hopefully a Raspberry Pi OS would be picked at this step)
  • Choose your Storage
  • Write to Storage

Although, before you proceed to the WRITE step, you should see the cog wheel button to access the Advanced Option for customization.

Once you click on the button, you'd be prompted:

Would you like to prefill the wifi password from the system keychain?

Proceed if you are on a Mac currently connected using wifi as it'd attempt to use the same SSID and password to configure the Raspberry Pi to connect to your wifi network later.

In the Advanced Option, you'd have the ability to set up the following:

  • Hostname
  • Enable SSH server
    • Using password authentication OR
    • ... setup public-key authentication
  • Setup a username and password
  • Configure wireless connection using SSID and password
  • Set the locale settings

The remaining Persistent settings are only for the Raspberry Pi Imager tool itself which I won't cover here.

You can proceed to SAVE and write to the storage card when you are done.

Access your SD card volume after writing:

After you have written the image to your card, your card may be ejected by the Imager.

Now you would need to access your SD card through macOS's Finder or through the /Volumes directory. Physically reinsert the SD card if you can't access the location.

In the SD card's boot/ or bootfs/ directory, you should have the firstrun.sh file as the source code found here was responsible for generating the script file. Back up the file to another location on the computer. For the sake of demonstration here, we'll make a copy to the ~/Desktop directory.

It's important that you can access the same firstrun.sh file again in the future if you wish to re-image using the same Raspberry Pi OS and its customization.

Crafting your very own rpi-imager --cli command:

With the firstrun.sh file you have, which was auto-generated for you during the graphical Raspberry Pi Imager steps, you are ready to use the rpi-imager --cli command.

If you attempt to run rpi-imager --cli with no argument, you'd see more usable options than the ones you see with --help output. See below:

Usage: --cli [--disable-verify] [--sha256 <expected hash> [--cache-file <cache file>]] [--first-run-script <script>] [--debug] [--quiet] <image file to write> <destination drive device>

We'll only cover a few options here.

The --first-run-script option:

Apparently the --first-run-script <script> option is where we'll use the firstrun.sh file.

The required <image file to write> argument:

The mandatory <image file to write> option is where your OS image filepath should be. Unfortunately, the Raspberry Pi Imager doesn't provide us a filepath conveniently accessible to us (e.g. automatically download the OS image file to ~/Downloads directory).

However, all the Raspberry Pi OS images can be found on the website here: https://www.raspberrypi.com/software/operating-systems/.

The Raspberry Pi Imager uses the image download locations defined in a downloadable JSON file hosted at the URL address which is officially documented here.

Here's a small Python script you can use to get direct URL address of a specific Raspberry Pi OS image (a 64-bit version of Raspberry Pi OS Lite was used here):

#!/usr/bin/env python3

import json
import urllib.request

url = "https://downloads.raspberrypi.com/os_list_imagingutility_v3.json"

response = urllib.request.urlopen(url)
data = response.read().decode('utf-8')
json_data = json.loads(data)

# See JSON objects with all Raspberry Pi OSes as shown on
# https://www.raspberrypi.com/software/operating-systems/
# print(json_data['os_list'][1]['subitems'])

# Get 'Raspberry Pi OS Lite (64-bit)' URL address
print(json_data['os_list'][1]['subitems'][3]['url'] )

At the time of this writing, the output was:

https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-05-03/2023-05-03-raspios-bullseye-arm64-lite.img.xz

The required <destination drive device> argument:

Lastly, we need to get the SD card's location. The best way to do this is use the diskutil list. You'd need to look for the physical disk that reflects the size of it. It's usually not /dev/disk0 or /dev/disk1 in most default macOS customization.

In a sample output below, the physical disk is /dev/disk2:

/dev/disk2 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *63.9 GB    disk2
   1:                  Apple_HFS ⁨Untitled⁩                63.8 GB    disk2s1

The complete command:

Assuming that your OS image file and your firstrun.sh script file are in the same directory, here's the complete command below:

/Applications/Raspberry\ Pi\ Imager.app/Contents/MacOS/rpi-imager \
    --cli \
    --debug \
    --first-run-script firstrun.sh \
    2023-05-03-raspios-bullseye-arm64-lite.img.xz \
    /dev/disk2

Once you run the complete command, the Raspberry Pi Imager would prompt you to provide your password to allow it to write to the SD card. Then that's it! You're done.

You would only need 3 things to ensure that you'd be able to recreate the same image again and again indefinitely (assuming the direct URL addresses wouldn't change):

  • Raspberry Pi Imager (you'd probably need to use the same version)
  • firstrun.sh script file
  • OS image file

Although, you may need to resort to using a previous supported macOS version if the Raspberry Pi Imager is no longer compatible with a future version. Let's just hope that the rpi-imager --cli command options and functionalities would be preserved in all future Raspberry Pi Imager releases as they should be compatible with future macOS releases in theory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment