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