The letter A styled as Alchemists logo. lchemists
Published February 1, 2026 Updated September 15, 2026
Pi Icon

Pi

0.3.0

This project automates the setup of Raspberry Pi devices by flashing your microSSD card with a fully customized Raspberry Pi OS for immediate use. This allows you to spend more time putting your Raspberry Pis to good use.

Features

  • Allows you to setup and configure multiple Raspberry Pi devices.

  • Allows you to manage multiple device profiles.

  • Allows you to install and run multiple services on your devices.

Setup

Ensure you have the Raspberry Pi Imager installed for your operating system because this project depends on the Raspberry Pi Imager to format the micro SSD for your Raspberry Pi. If on macOS, use Homebrew as follows:

brew install --cask raspberry-pi-imager

Next, clone this project:

git clone https://github.com/bkuhlmann/pi.git
cd pi
git checkout 0.3.0

Configuration

By default, this project assumes you want to use the Raspberry Pi Imager. You can override the defaults by setting the following environment variables (see settings/main.sh for details):

  • EDITOR: This has no default but assumes you have this configured to run your favorite text editor. For example, if using Sublime Text, the value would be: sublime.

  • PI_CLI: The path to where the Raspberry Pi Imager is installed. By default, this assumes a macOS installation.

  • PI_URI: The Raspberry Pi OS to be installed. By default, this assumes 64-bit, Lite OS.

  • PI_INTEGRITY: The integrity SHA used to verify the OS you are installing is valid. You can find the corresponding SHA for each OS on the Raspberry Pi OS page. You’ll want to update this each time you change the PI_URI.

This project comes preconfigured with several scripts to help you get up and running quickly. You can find them in the scripts folder:

  • services: A directory of executable scripts for managing multiple services. This is meant to be customized with your own logic for installing, configuring, and running your services. The docker service is provided for you, by default, so you can use Docker to run multiple projects at once.

  • setup: The primary script that first updates your system and then runs all services.

  • update: Ensures your Raspberry Pi OS is upgraded and up-to-date with latest software. You can also use this script to keep your OS updated on a scheduled basis.

If you’d like to customize any of the above scripts, you can do so by making a copy of them using identical script name in your XDG configuration folder. Example:

$XDG_CONFIG_HOME/pi/scripts/services
$XDG_CONFIG_HOME/pi/scripts/setup
$XDG_CONFIG_HOME/pi/scripts/update

This is also a good way to zero them out entirely if you want them to do nothing.

Raspberry Pi Imager

When first getting set up, you’ll want to use the Raspberry Pi Imager to walk through setting up your device for the first time. Afterwards, you can copy and customize the files created by the Raspberry Pi Imager. This is only necessary if you’ve never used this project before and don’t feel comfortable writing all of the configuration files by default.

  1. Insert the micro SSD into your machine you want to format.

  2. Launch Raspberry Pi Imager.

  3. Select your Raspberry Pi hardware.

  4. Click on Raspberry Pi OS (other) software.

  5. Select Raspberry Pi OS Lite (64-bit).

  6. Select your micro SSD card (example: "Generic- SD/MMC Media").

  7. Enter your desired hostname.

  8. Fill in your capital city, time zone, and keyboard layout.

  9. Fill in your username and password for your desired Raspberry user account.

  10. Fill in your SSID and password for your local network.

  11. Enable SSH by supplying the path to your public key (i.e. $HOME/.ssh/*.pub).

  12. Choose whether to enable/disable Raspberry Pi Connect.

  13. Write image to disk.

When the above is complete, you’ll be able to inspect the files created for you by running the following:

cd /Volumes/bootfs
cat network-config
cat user-data

You’ll want to make a copy of each of the above files so you can customize them for different networks and hosts as follows:

cp /Volumes/bootfs/network-config $XDG_CONFIG_HOME/pi/networks/demo.yml
cp /Volumes/bootfs/user-data $XDG_CONFIG_HOME/pi/hosts/demo.yml

This allows you to have multiple profiles, so-to-speak, for different networks and hosts. Due to these being YAML configurations, you can quickly adjust your host name, SSH public key, time zone, WiFi SSID, etc. You can learn more about the structure and configuration of each of these files via the Raspberry Pi Documentation.

Usage

To run, use:

bin/run

You’ll then be greeted with the following options:

Usage: run OPTION

Script Options:
  s: Setup
  e: Edit configuration
  o: Open configuration
  E: Eject Card
  q: Quit/Exit

Enter selection:

The above breaks down as follows:

  • Setup: Formats, configures, and sets up your micro SSD card so you can boot your Raspberry Pi with desired operating system and custom configuration. A wizard will prompt you for further information.

  • Edit configuration: Allows you to select and edit an individual XDG configuration in your default editor.

  • Open configuration: Allows you to open and view your entire XDG configuration in your default editor.

  • Eject Card: Allows you to eject (unmount) the micro SSD card created during setup.

  • Quit/Exit: Allows you to quit the CLI.

If you know which option you want to run, like setup, you can skip the interactive options shown above. Example:

bin/run s

SSH

Once you’ve configured your Raspberry Pi settings, you can insert your micro SSD card into your Raspberry Pi, and connect power. Then you can look for your device to show up on your local network with whatever host name you gave it. To make SSH’ing into your device more convenient, edit your SSH configuration (i.e. $HOME/.ssh/config) to add your new host. Example:

Host demo.local
  HostName 192.168.0.123
  User admin
  IdentityFile ~/.ssh/demo

With SSH configured, you can SSH into your Raspberry Pi. Example:

ssh admin@demo.local

Scripts

After SSH’ing into your Raspberry Pi, run the setup script from your home directory to complete the setup of your device. Example:

/boot/firmware/setup

This’ll run all of the scripts/services (default or custom) based on the configuration you used when setting up your micro SSD card.

Example

The following is an example of what the output can look like when running setup (i.e. bin/run s) where I walk through all options to configure my Raspberry Pi 5 (a.k.a. five) using my demo network complete with default services and my custom Terminus service:

Setup Output Example
Have you inserted your micro SSD card for formatting (y/n)? y

Please select your host configuration:

1) /Users/demo/.config/pi/hosts/five.yml
2) /Users/demo/.config/pi/hosts/zero.yml
#? 1

Please select your network configuration:

1) /Users/demo/.config/pi/networks/demo.yml
#? 1

Using host configuration: /Users/demo/.config/pi/hosts/five.yml.
Using network configuration: /Users/demo/.config/pi/networks/demo.yml.
Using setup script: /Users/demo/Engineering/OSS/pi/scripts/setup.
Using update script: /Users/demo/Engineering/OSS/pi/scripts/update.

The following external disks are detected for your micro SSD:

/dev/disk4 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                        +5.4 GB     disk4
   1:        Apple_partition_map                         32.3 KB    disk4s1
   2:                  Apple_HFS projects                5.4 GB     disk4s2

/dev/disk5 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.7 GB    disk5
   1:             Windows_FAT_32 bootfs                  536.9 MB   disk5s1
   2:                      Linux                         31.2 GB    disk5s2

Please enter your disk number (i.e. 1, 2, 3) for /dev/disk to format: 5
CacheManager initialized with background thread
Detected total system memory: 24576 MB on "macOS"
Optimal async queue depth: 256 (available: 9093 MB, budget: 1363 MB, block size: 1024 KB, baseline: 256 )
FileOperations log callback installed
Starting background cache operations
Found cached file info, starting background verification: "/Users/demo/Library/Caches/Raspberry Pi/Raspberry Pi Imager/lastdownload.cache"
Starting background drive list polling
Opening macOS device: /dev/rdisk5
Device path detected, using macOS authorization...
Successfully opened device with authorization, fd=13 (direct I/O enabled)
Block device size: 31719424000 bytes (blocks=61952000, block_size=512)
PrepareForSequentialRead: fd=13 path=/dev/rdisk5
  F_RDAHEAD result: 0 (OK)
  F_NOCACHE result: 0 (OK)
Write successful.

Copied: /Users/demo/Engineering/OSS/pi/scripts/setup to /Volumes/bootfs/setup.
Copied: /Users/demo/Engineering/OSS/pi/scripts/update to /Volumes/bootfs/update.
Copied: /Users/demo/Engineering/OSS/pi/scripts/services/docker to /Volumes/bootfs/services/docker.
Copied: /Users/demo/.config/pi/scripts/services/terminus to /Volumes/bootfs/services/terminus.

Raspberry Pi SSD card is ready!
Please eject card before using.

Development

To contribute, run:

git clone https://github.com/bkuhlmann/pi.git
cd pi

Credits