Flash images to a microSD card

Several popular tools exist for flashing images to microSD cards, but this guide uses only basic command line tools (specifically dd(1)), ensuring it can be followed even on console-only systems.

The most dangerous aspect of writing images in this manner is ensuring you are overwriting the correct device. With root authority, dd will happily overwrite any device you point it at, including the device holding your root file-system! To avoid this, we will use inotify-tools to detect the device node representing our microSD card.

Procedure

  1. Start with your target microSD card disconnected from your machine

  2. Install the pre-requisite packages we’re going to be using:

    sudo apt install inotify-tools atool wget
    
  3. Download the image you wish to write. Here we’ll be using the Ubuntu 24.04 Server for Raspberry Pi image, but you should substitute your cdimage.ubuntu.com URL here:

    wget http://cdimage.ubuntu.com/releases/24.04/release/ubuntu-24.04-preinstalled-server-arm64+raspi.img.xz
    
  4. If you wish to verify the download, also get the SHA256SUMS file from the same path, and use it to verify the downloaded file:

    wget http://cdimage.ubuntu.com/releases/24.04/release/SHA256SUMS
    sha256sum --ignore-missing --check SHA256SUMS
    
  5. Start inotifywait(1), watching for new device nodes under /dev:

    inotifywait --event create --format "%w%f" /dev
    
  6. Plug your microSD card into your machine. At this point, inotifywait should exit, displaying the name of a new node under /dev. For example:

    ubuntu@ubuntu:~$ inotifywait --event create --format "%w%f" /dev
    Setting up watches.Watches established./dev/sda1

    It is likely that the node printed will be a device representing a partition of the microSD card, rather than the whole microSD card itself. In the example above, we see /dev/sda1. This is the first partition of /dev/sda, which is the device representing the entire microSD card.

  7. We’re now ready to write the image to the microSD card. If the image you downloaded is compressed (indicated by a .gz, .bz2, .xz, or .zst suffix on the filename) we cannot write it directly. We’ll use the aunpack(1) command to extract the image, then write the result to the microSD device with dd(1):

    aunpack ubuntu-24.04-preinstalled-server-arm64+raspi.img.xz
    sudo dd \
        if=ubuntu-24.04-preinstalled-server-arm64+raspi.img \
        of=/dev/sdX \
        bs=16M status=progress
    

    Warning

    Take care to specify the correct output device after the of= parameter. Bear in mind this should be the device covering the entire microSD card, not just a partition.

    Note

    We are using sudo(8) because dd requires root authority to write to the microSD card device. You will be prompted for your user’s password before the write begins (assuming a typical sudo configuration).

  8. Once dd has completed, run sync(1) to be reasonably certain that everything is flushed:

    sudo sync
    
  9. You can remove the microSD card and insert it into your target board

Alternate device names

In some cases, depending on the microSD interface in use, you may see output like the following from inotifywait:

ubuntu@ubuntu:~$ inotifywait --event create --format "%w%f" /dev
Setting up watches.Watches established./dev/mmcblk0p1

In this case, we are also seeing a device representing the first partition of the microSD card, /dev/mmcblk0p1. However, here we need to remove the p1 suffix; the device representing the entire microSD card is /dev/mmcblk0.

This is often the case where the microSD interface is built into your machine (e.g. the microSD card slot on a Raspberry Pi), or where the interface is connected by something other than USB.

Avoiding decompression

If you have limited disk space and do not wish to unpack the OS image, you can decompress the image on the fly and pipe the result to dd. For this, use the acat(1) command. For example:

acat ubuntu-24.04-preinstalled-server-arm64+raspi.img.xz | \
    sudo dd of=/dev/sdX bs=16M status=progress