Brian's answer is what I'd recommend: receive the image from the network as you go. There's no other way, because you clearly can't put the image on the storage device you're overwriting.
But that exact problem will also become with Brian's approach: Assuming you did the image receiving from your currently booted full debian, then you'll start overwriting the software that's currently on the file system. Uh, what happens if some hardware interrupt, some timer / cron job, or some file system maintenance tool kick in while you're downloading and extracting to raw disk? Your whole system might, or might not crash.
If it crashes, you're left with an embedded device that's not bootable in a location you potentially can't access. That makes the effort much worse.
So, what you need to do is that the receiving&unpacking software doesn't overwrite what you're currently running. Two approaches:
- Have two root volumes, say, A and B. Your current debian be running from A, you can safely overwrite all of B. After that's finished, you can tell your boot process to boot from B, and properly reboot your system. (Typically, you have a separate "boot" partition from which your bootloader runs, and which contains the boot configuration files for the RPi's boot hardware, which is… peculiar.)
You'd need twice your system's size needs in storage space.
I drafted a version how you'd do that, exactly on a RPi, in this very recent answer
- Have one root volume (A) that you overwrite, but don't do it while you're running from that volume. Instead, add an entry to your bootloader, and an initial RAM file system file to your boot drive, which boots from a couple-of-megabytes image which gets loaded into RAM, and does the receiving and unpacking to A from there. Or, you have another (C) small volume that contains a minimal version of your operating system entailing very little but networking setup, SSH and a decompressor.
Looking at Raspberry Pi's foremost hardware failure mode being SD cards stopping to work due to write fatigue, and looking at how low SD card prices are, I'd probably go with the first approach (A/B booting, no separate "maintenance" OS), and if the new system works flawlessly, I'd blkdiscard
the now unused volume, so that the SD card's wear leveling has space to work with.
So, to conclude, assuming you're going with Method 1.:
- get a 64 GB card if your system needs a bit less than 32 GB of space
- Install debian on that system; but modify the default partitioning scheme a bit:
- use "Guided - use entire disk and set up LVM" when asked to Partition Disks, and either "All files in one partition" or "Separate /home partition" on the "Partitioning Scheme" dialog, depending on whether you want the files in your home directory on the pi to survive an upgrade or not (you can change that later, as well, no big deal).
- make sure that the sum of sizes in the overview of volumes to be created is a bit less than half the SD card size (for simplicity, 30 GB). If necessary, reduce the size of / (and /home if present) accordingly.
- write the changes to disk, finish installation, boot RPi: should work.
- (Of course, you can also achieve this by reducing the size of a partition of an existing installation, with some caveats, and trouble later on; I'd recommend you start from a clean LVM installation, you'll not regret that. I honestly don't know why debian doesn't default to LVM in 2023, but prefers to use a partitioning scheme that was specific to a specific brand of personal computer with a 8 bit CPU @ 5MHz with 16 kB of RAM, literally from 1983, forty years ago)
So, after your new system runs (and before you set up anything further), we'll describe the update process:
- On the Pi:
- Check whether there's an
oldsystem
logical volume (Look into /dev/mapper
)
- if so, delete it,
sudo lvremove your-volume-group-name/oldsystem
- On the Pi: Make a new volume of your uncompressed image size (assuming 30 GB here):
sudo lvcreate -L 30G --name image_prep your-volume-group-name
- On the end with the image you want to send:
- Compress the image, using something like
zstd -12 -T0 < /what/you/want/to/compress > /path/to/images/filesystem.image.zst
(-12
is already quite high compression, and thus not very fast, but it saves you time on the network, so there's that; values between 1 and 18 work, and .)
- take the checksum of your compressed image:
sha256sum /path/to/images/filesystem.image.zst >> checksums
- Get the image from the hosting computer to the receiving one; I'm lazy, I usually just set up a small python webserver (because copying through SSH will make the poor RPi's CPU a bit warm):
cd /path/to/images; python -m http.server -p HTTP/1.1 8765
(if necessary, I'll open port 8765; note down this computer's IP address)
- On the Pi:
- get the image, uncompress it to the new volume, and simultaneous calculate the checksum:
mkfifo checksumpipe; sha256sum > checksum < checksumpipe &
curl http://ip.address.as.noted:8765/filesystem.image.zst | tee checksumpipe | zstd -d > /dev/your-volume-group-name/image_prep
- verify that the checksum in
checksum
is the same as you saved in checksums
on the transmitting host
- figure out what your current root volume is called (if in doubt,
cat /proc/cmdline
, look for root=/dev/mapper/your--volume--group--name-???
), and rename it to oldsystem
: sudo lvrename your-volume-group-name ??? oldsystem
- rename the freshly imaged volume to the former name
sudo lvrename your-volume-group-name image_prep ???
- mount that volume, bind-mount
/dev/
, /proc
/sys
, /boot
into it, chroot
into the mount and run a boot loader update
- reboot
A less "debian" way would that's a lot more streamline probably would be using mender
; there's actually an official guide for RPi; ignore the part about registering for "hosted mender", you're looking for "standalone" mode.
dd
when a simplecat
would do: dd vs cat -- is dd still relevant these days? – terdon Sep 19 '23 at 17:16