/guestfish

An OCI container for modifying disk images without needing root

Primary LanguageShell

ghcr.io/justinlex/guestfish

This is an OCI container (aka "Docker container") for modifying disk images without needing root.

The Dockerfile is roughly based off of djui's docker-guestfs container, with additional scripts written by me to run guestfish properly and automate the guestfish commands.

How it works

The container uses guestfs and guestfish to mount a partition from the disk image with QEMU, and then it allows you to write scripts that copy in/out files, or make other modifications to the files on the disk images.

Purpose

Being able to edit disk images in an automated way like this is super useful for modifying disk images for hands-free, bare-metal servers, such as Raspberry Pis.

I will be publishing a project allowing someone to create a disk image for running Fedora CoreOS on a Raspberry Pi, and the user will be able to bake in an ignition file that will install and configure all the software that they need.

Users can run software like Kubernetes or zigbee2mqtt on a Raspberry Pi by just specifying some parameters to a script, which can then burn an SD card that can be inserted into a Pi and be immediately ready to go. No manual installation required, no more connecting a keyboard and monitor to your tiny Pi system board.

Edge computing benefits

This script helps enable rapid deployment to edge systems using infrastructure-as-code, without any cloud-init/ignition infrastructure. Everything the edge machine needs can be baked into the disk image, no external servers are needed to provision the machine.

Consistent builds

Automating the creation of the disk image with code like this allows for consistent builds, building up from a base image to a specific disk image finely tailored for a specific system. This is infrastructure-as-code for bare-metal edge servers.

Security benefits

Allowing users to create the final disk image themselves without needing root access has major benefits when it comes to supply-chain security. Users can be sure that the image that they're building has nothing unwanted or malicious installed, and because this container doesn't require root/privileged, the user can run these scripts without worrying about their workstation being attacked by a malicious script.

Technical features

The container comes with guestfs and guestfish installed, and includes a script that allows you to run guestfish commands without needing to fiddle with QEMU and docker quirks.

How to use it

The container has the guestfish.sh script set as the container ENTRYPOINT, so all that is needed is to specify the disk image you wish to modify and the guestfish commands you want to run.

The directory containing your disk image should be mounted as a volume in /root/src. Make sure to use the :Z flag in your volume arguments if you are using a linux distro like Fedora that has SELinux enabled, or guestfish will crash.

You can therefore run the container with Docker or Podman, specifying the disk image name and partition number like so:

# Docker, no SELinux, partition number 2
docker run -v $PWD:/root/src --rm ghcr.io/justinlex/guestfish my_disk_image.img 2

# Docker, SELinux enabled, partition number 2
docker run -v $PWD:/root/src:Z --rm ghcr.io/justinlex/guestfish my_disk_image.img 2

# Podman, SELinux enabled, partition number 2
podman run -v $PWD:/root/src:Z --rm ghcr.io/justinlex/guestfish my_disk_image.img 2

Giving guestfish commands

Of course, you will need to specify the commands that you want guestfish to run.

An example command

An example guestfish command is the following:

copy-in /root/src/manifest.yaml /

This command takes the file manifest.yaml from the /root/src/ directory in the container, and copies it to the root (/) directory of the partition you have mounted. (In the docker command examples given above, your workstation commandline's working directory is mounted as a volume to /root/src/, so in this example, manifest.yaml would be on your workstation next to my_disk_image.img)

commands documentation

The Guestfish documentation can be found here.

The commands section starts here, but the table of contents at the top of the page is really useful.

commands.txt

In order to pass your commands to the guestfish script included with this container, you specify the list of commands in a file called commands.txt and mount it to /root/src/.

Insiqe commands.txt, every command should be on its own line, and there should not be any blank lines, or a newline at the end of the file.