Skip to main content
ⓘ

Downloads Downloads Coverage Status Lines of code Hits-of-Code Tests Lint Python versions PyPI version Checked with mypy License: MIT Ruff DeepWiki

logo

piburn prepares removable microSD cards that boot Raspberry Pis with Ubuntu Server for use as cluster nodes. By default, it downloads the latest stable Ubuntu Server image for Raspberry Pi and verifies its published SHA-256 checksum. It writes settings that Ubuntu applies on first boot through cloud-init, safely ejects each card, and can generate an Ansible inventory (a list of nodes to manage).

The tool is intentionally conservative: it only lets you select physical, writable, removable media of at least 4 GiB and rechecks the selected device's identifying attributes before erasing or writing to it.

Table of Contents

Installation

piburn requires macOS and Python 3.8 or newer. It has no third-party runtime dependencies. Writing to a card requires macOS administrator privileges.

Install it from PyPI:

pip install piburn

The piburn command is now available:

piburn --help

Quick start

Warning: flashing and integrity testing can destroy existing data on the selected card. Integrity testing overwrites its entire reported capacity. Always verify the device name, model, and capacity before confirming it.

Insert a microSD card and run:

piburn

The interactive interface first asks how many cards to prepare and whether to run the full integrity test, then collects the Wi-Fi, hostname, and login settings. After those initial questions, it requests administrator authentication and asks you to select the first target card before downloading and verifying the image. The selected card is checked again before any destructive operation. For additional cards, target selection happens after the previous card is finished. The starting hostname number defaults to 1. Cards are prepared one at a time, so a single card reader is enough.

Press Ctrl+C at any step to stop. The display may turn off and the screen may lock while a card is being prepared; neither interrupts the operation.

After the last card, the tool asks whether to generate an Ansible inventory. If you accept, it creates or replaces ansible/inventory.ini by default; this file lists the nodes managed by Ansible. It then prints one SSH command per node:

SSH commands:
ssh pomponchik@pi-1.local
ssh pomponchik@pi-2.local

Insert each ejected card into a Raspberry Pi and power it on. Use the corresponding command after the first boot completes.

What gets configured

Every card receives:

  • the selected OS image;
  • a numbered hostname such as pi-1;
  • the pomponchik user by default, configurable with --username;
  • Wi-Fi and Ethernet configured to obtain network settings automatically;
  • either an SSH public key or a shared login password;
  • Avahi for discovery of .local names such as pi-1.local;
  • cloud-init configuration that expands Ubuntu to use the card's full capacity on first boot.

Downloaded images are temporary; local files supplied through --image are left untouched.

Login methods

For SSH-key login, piburn looks for an existing SSH public key in common ~/.ssh locations, starting with ~/.ssh/id_ed25519.pub. Create one when needed:

ssh-keygen -t ed25519

Alternatively, choose password login. piburn displays a random password; press Enter to accept it or type your own, and save whichever password you use. Only its hash is written to the card.

In interactive mode, the Wi-Fi password is hidden while you type, and piburn does not save a persistent copy on the Mac. It must still be written to the card so the Raspberry Pi can join the network.

Card integrity test

The optional full integrity test writes a newly randomized, position-dependent pattern across the card's entire reported capacity and reads it back without using the local read cache. This can detect corrupted or counterfeit media, including stale data from an earlier test, but it is destructive and may take longer than flashing Ubuntu itself.

After Ubuntu is written, piburn performs a separate byte-for-byte comparison between the card and a freshly verified and decompressed source image. The full-card test and this post-flash verification cover different write operations: passing the first does not guarantee that a later image write cannot fail. Writes request an explicit fsync. During raw image writing and verification, a separate Disk Arbitration helper denies automatic mounts only for the selected card and its partitions; piburn also unmounts any partition that was already mounted. This prevents macOS services from changing the FAT boot partition before verification. The guard is released before piburn deliberately mounts that partition to write cloud-init configuration. Verification reads bypass the macOS cache. If data differs, piburn reports the first differing byte, full and per-block SHA-256 values, and whether repeated direct reads are stable, transient, or inconsistent. Any inconsistent read remains an error.

If Disk Arbitration is briefly still settling after a write, piburn makes up to five ordinary whole-disk unmount attempts at one-second intervals. It never uses a forced unmount, and it rechecks the complete card fingerprint before every attempt.

Downloaded images are normally removed after the run, including after automatic mismatch diagnostics. To retain the downloaded image and a secret-free diagnostic report after a failure, pass a destination directory:

piburn --keep-image-on-failure ./piburn-diagnostics

For a remote image, piburn stages the temporary download on the destination filesystem so it can be preserved by an atomic rename without creating another multi-gigabyte copy. A successful run removes that staging directory without creating a failure subdirectory. After a failed or cancelled run, piburn creates a unique subdirectory and prints the resulting paths. A local image is not duplicated; the report refers to its existing path. Failure to preserve these artifacts is reported separately and never replaces the original write or verification error.

Sleep and recovery on macOS

After a particular card is selected, piburn creates macOS power assertions until that card has been successfully ejected. These assertions prevent idle/system sleep during the integrity test, image write, direct verification, cloud-init changes, and eject. They deliberately do not prevent display sleep: the display can turn off and the Mac can lock normally. Image download, initial questions, waiting for a card, pauses between cards, and inventory creation are outside this protected interval.

Power assertions are best-effort. macOS can still enter a forced sleep requested by the user or required by the system. piburn detects that event and discards the current attempt; it never resumes a partial raw write from an assumed byte offset. After wake, the image is written again from byte zero. Attempts are numbered, have no fixed limit, and can always be stopped with Ctrl+C.

A fully completed integrity test is retained across these sleep attempts, as is an explicit decision to skip a failed test. If sleep interrupted the integrity test itself, the complete test starts again with a new randomized pattern. Ordinary card, image, sudo, cloud-init, and helper failures are not retried automatically.

Before retrying, piburn waits for the original card on its original /dev/diskN path and compares the complete recorded fingerprint, not only the path. A reader may need the card to be physically removed and reinserted after wake. If a different device appears at that path, piburn stops before sending it any unmount, write, or eject command.

Non-interactive usage

--non-interactive disables piburn's own prompts, but sudo may still request administrator authentication once before image preparation starts. piburn keeps that authorization active during image download and verification as well as long card writes and checks; macOS may ask again only if the authorization is revoked or the system uses an unusually short timeout. Passwords are read from environment variables rather than command-line arguments. Replace wifi-password, MyNetwork, and the sample device paths with your own values; --yes authorizes writing to those devices without confirmation.

export PIBURN_WIFI_PASSWORD='wifi-password'

piburn \
  --non-interactive \
  --count 2 \
  --no-check \
  --ssid 'MyNetwork' \
  --wifi-password-env PIBURN_WIFI_PASSWORD \
  --prefix pi \
  --start-number 1 \
  --auth-mode ssh-key \
  --device /dev/disk4 \
  --device /dev/disk5 \
  --inventory \
  --inventory-path ansible/inventory.ini \
  --yes

unset PIBURN_WIFI_PASSWORD

This example uses --no-check, so it skips both the full card integrity test and post-flash read-back verification.

To reuse one card reader, repeat the same --device value. After ejecting a completed card, piburn waits for the next one.

To adapt this example for password login, add this export before the piburn command:

export PIBURN_USER_PASSWORD='node-password'

Also replace --auth-mode ssh-key in the command with --auth-mode password --user-password-env PIBURN_USER_PASSWORD. Unset both password variables after the run.

Metadata

Release files for piburn 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for piburn 0.0.7
File Size Uploaded
piburn-0.0.7.tar.gz 95.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for piburn 0.0.7
File Interpreter ABI Platform
piburn-0.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 134.3 kB

Release files / piburn-0.0.7.tar.gz

Download URL piburn-0.0.7.tar.gz
Size 95.4 kB
Tags Source
SHA-256 checksum
How to use checksums
0b64292b5733653bd37059ffd538228f4a79d0e60b96916185e04c4908242df1
BLAKE2b-256 checksum
How to use checksums
a2663f524c4834afee332ca76d987f778e152203d44eb074aa5bbef32fe91748
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / piburn-0.0.7-py3-none-any.whl

Download URL piburn-0.0.7-py3-none-any.whl
Size 38.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a19258b4efa11d0b37b5a493d0861ba83b90d7501c8163584e5da0ba0182d9a1
BLAKE2b-256 checksum
How to use checksums
80853de6d3221238d1f84dcdc0428e65d32a5e9463b9e97e7378c0110ebd1f9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.7 This release

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page