Home     Blog     Rss     Contact     Donate

Quickly Build a Custom Debian Live ISO with Live-Build


Debian’s rigid stability doesn’t appeal to everyone, but there is one thing clear: its stability makes it the king of live USBs. Thanks to Debian’s own Live-Build package, creating a custom iso (that can also be installed) is very easy.

First, this isn’t meant to be an in-depth guide. Debian’s ‘live-build’ tool has a ton (and I do mean a TON) of options, and for more detailed options, I suggest you have a look at the man pages related to it.

Second, the ideal is to do this in a virtual machine that is a perfect clone of the live system you wish to build. This is optional, of course.

In any case, here are the steps to easily create your own custom iso.

Hint: commands preceded by a '#' must be run as root,
while commands preceded by a '$' must be run as a regular user.

Get the dependencies and Configure


First, install live-build, create a build directory and cd into it.


    # apt install live-build
    $ mkdir -p .build
    cd .build

Next, create a config.


    $ lb config -d bookworm --debian-installer live --debian-installer-distribution bookworm \  
      --archive-areas "main non-free-firmware" --debootstrap-options "--variant=minbase"

This will generate the necessary files for a minimal Bookworm iso. There are much more config options available, and they are well documented in the lb_config manpage[1].

Example of various config options in use:
https://github.com/RagnarokOS/iso/blob/main/Makefile#L27

Customizing the iso


Now is the time to customize the content of the iso. You can add your preferred window manager or desktop environment, packages you need, as well as your dotfiles.

Add packages

Create a file named pkgs.list.chroot which should be saved to config/package-lists/. Add the name of the packages you wish to have in the iso. This needs to be a list separated by white-spaces, or each package on a new live, e.g.


    xserver-xorg-core
    xinit
    xwallpaper
    cwm
    vim
    tmux
    vifm

Example pkgs.list.chroot file:
https://github.com/IanLeCorbeau/debian-live-build/blob/main/config/package-lists/pkgs.list.chroot

You can create multiple package lists for convenience if you plan on installing a lot.

Example setup for multiple package lists:
https://github.com/RagnarokOS/iso/tree/main/config/package-lists

Make sure there are no typing error in the package names, or else the package will be missing from the finished iso.

Add your dotfiles

Create a skeleton directory in config/includes.chroot_after_packages:


    $ mkdir -p config/includes.chroot_after_packages/etc/skel

Then copy all your dotfiles over. The etc/skel directory should contain all files that will be copied to the live user's home directory, so its structure is the same. This config/includes.chroot_after_packages/ directory is, in fact, where all files you wish to add to the iso should go. Treat it as the iso's file system.

Example skel directory:
https://github.com/IanLeCorbeau/debian-live-build/tree/main/config/includes.chroot_after_packages/etc/skel.

Example of a populated config/includes.chroot__after_packages directory:
https://github.com/RagnarokOS/iso/tree/main/config/includes.chroot_after_packages.

At this point, you could build the iso, or customize further using hooks.

Hooks

Hooks are just shell scripts where you run any command needed to tweak the live system.

For example


    #!/bin/sh

    set -e    # use set -e so that build fails in case of error

    sed -i '15 s/^# //' /etc/pam.d/su
    addgroup --system wheel
    touch /etc/doas.conf
    echo "permit :wheel" > /etc/doas.conf

This would essentially enable the wheel group and configure doas on the live system.

All hook scripts should be saved in config/hooks/normal, and a name starting with a number and ending with .hook.chroot, e.g. 0001-instenv.hook.chroot.

Example hook scripts:
https://github.com/RagnarokOS/iso/blob/main/config/hooks/normal/0001-instenv.hook.chroot
https://github.com/RagnarokOS/iso/blob/main/config/hooks/normal/0002-buildsrc.hook.chroot

Boot time hooks

Because the live user is only created when the iso boots, there are certain customizations that can't be done with normal hooks, e.g. changing the live user's password. Modifications to the live user can be made by creating the config/includes.chroot_after_packages/lib/live/config-hooks/ directory, and placing hook scripts there.

Example scripts:
https://github.com/RagnarokOS/iso/blob/main/config/includes.chroot_after_packages/lib/live/config-hooks/01ksh-default
https://github.com/RagnarokOS/iso/blob/main/config/includes.chroot_after_packages/lib/live/config-hooks/02sendmail.sh

Building the iso


Once you're reasonably satisfied with your configuration, you can build the iso, by running:


    # lb build

This may take a while depending on network speed and the amount of packages added. If the build fails, don't sweat it. In my experience, live-build can be a bit, let's say, capricious. Other times, a simple typo or inadvertent misconfiguration can cause seemingly random issues. Carefully read lb build's output to investigate any problem. You could even save the output to a log file using


    # lb build 2>&1 | tee build-log.txt

It may take several tries before the build is both successful, and accurate. Patience is most definitely required.

When the building process is done, the iso will be here in the .build directory, named something along the lines of live-image-amd64.hybrid.iso (unless a name was provided at config time).

Subsequent rebuilds

To rebuild the iso, run:


    # lb clean
    $ lb config
    # lb build

It is not necessary to run lb config with all options when simply doing a rebuild.

If you want to restart from scratch, lb build has a number of options, such as --all, --remove, and --purge which can help, but in my experience, you're better off just backing up all directories/files you modified, removing the .build directory then re-run your full lb config ... command.

Backing up your config


I highly recommend backing up your config/ directory in git for convenience, being careful not to track the files produced by the lb config command, besides these: config/common, config/bootstrap, config/chroot and config/source.

Keeping these files around will allow you to rebuild without always reconfiguring. The lb config command will not overwrite these files unless an option is specified. For example, if you want to modify the name of the resulting iso:


    $ lb config --image-name customname-live

Final thoughts


Building a custom live iso is relatively easy once everything is properly set up. Needless to say, though, patience is required. It does pay off down the line and once you successfully built your iso, rebuilds are trivial.

Originally posted on January 9, 2021.
Updated on June 19, 2023.

[1] https://manpages.debian.org/unstable/live-build/lb_config.1.en.html