This page describes how to create a minimal bootable EFI Debian system (on a separate partition or an external drive or a qcow2 image) from a command line of another working Debian system.

This page assumes some level of familiarity with the basic structure of a Linux system and its common config files.


Partition the target drive

For a storage device (like an HDD or an NVMe or a qcow2 image) to be a valid boot device for UEFI machines, it needs to have an EFI System Partition (ESP) containing EFI applications. If you are bootstrapping the system on a separate partition of a drive that already has some OS installed on itself, an ESP is most probably already there and you can skip to the next paragraph. Otherwise, follow the below guidelines:

A standard Debian system requires at least one partition or a logical volume for its root filesystem (rootFS). Optionally, separate subvolumes (partitions or logical volumes) may exist for /var, /home, /boot, /opt etc. A rootFS may be formatted as any Linux-supported, POSIX-compliant filesystem (ext4, xfs, btrfs etc). As of Trixie, a text-only Debian system will easily fit within 3GB, for a graphical system at least 10GB is recommended.

There are several different strategies and additional technologies for partition layouts (for example LVM, partitions for swap space, LUKS etc), each with different strengths and goals, but this is beyond the scope of this document: refer to the links in the following subsection.


Mount volumes and run mmdebstrap

Create a temporary mount-point for the target system, for example /mnt/tmp-debstrap, it will be referred hereafter to as ${debstrapFolder}. Mount the rootFS volume there, then mount any subvolumes at their respective mount-points, creating them during the process when necessary (note: if the target system shares its ESP with the host system, you must either umount it on the host first or use --bind option for mount: check the man page for details).

Afterwards run mmdebstrap:

sudo mmdebstrap --skip=output/dev,output/mknod,check/empty \
    --variant=standard trixie "${debstrapFolder}" /etc/apt/sources.list

This will create a basic foundation of the new system using apt sources copied from host's /etc/apt/sources.list.

Other distros

It is also possible to use mmdebstrap to create a base image for any well-behaved apt-based distro by providing its sources and signing key, but the subsequent instructions may need to be adapted somewhat due to a different package structure and names. For example to create an image for Excalibur release of Devuan, run

wget -O excalibur-archive-keyring.asc \
    'https://keyring.devuan.org/pks/lookup?op=get&search=0xB3982868D104092C'
sudo mmdebstrap --skip=output/dev,output/mknod,check/empty \
    --keyring=excalibur-archive-keyring.asc --variant=standard \
    excalibur "${debstrapFolder}" - <<EOF
deb http://deb.devuan.org/merged excalibur main non-free-firmware
deb-src http://deb.devuan.org/merged excalibur main non-free-firmware
deb http://deb.devuan.org/merged excalibur-security main non-free-firmware
deb-src http://deb.devuan.org/merged excalibur-security main non-free-firmware
deb http://deb.devuan.org/merged excalibur-updates main non-free-firmware
deb-src http://deb.devuan.org/merged excalibur-updates main non-free-firmware
EOF

The - tells mmdebstrap to read sources from its standard input. See the official Devuan sources info and keyring info for details.

In case of Excalibur, the subsequent instructions work almost perfectly fine for text-only systems (just install rsyslog additionally), but for full functionality of some of the graphic DEs, installing some additional packages may be required to replace Systemd-coupled ones from Debian.


Create or edit basic config files

/etc/fstab

mmdebstrap creates just an empty stub, so you need to list the rootFS and any subvolumes manually, including the ESP at /boot/efi. See fstab for details.

/etc/hostname

Put a hostname of your choice into this file, for example:

echo my-new-laptop |sudo tee "${debstrapFolder}/etc/hostname"

/etc/hosts

mmdebstrap creates entries necessary for basic networking, so just add an entry for the hostname chosen above:

echo "127.0.1.1 $(cat ${debstrapFolder}/etc/hostname)" | sudo tee -a "${debstrapFolder}/etc/hosts"

If you want to set a static DNS domainame, then instead add an entry that also includes an alias for the desired FQDN, for example:

echo "127.0.1.1 $(cat ${debstrapFolder}/etc/hostname).my-dns-domain $(cat ${debstrapFolder}/etc/hostname)" \
    | sudo tee -a "${debstrapFolder}/etc/hosts"

See hostname for details.

/etc/localtime

mmdebstrap by default sets the timezone to UTC, change the link to point to your desired timezone, for example:

sudo ln -sf /usr/share/zoneinfo/Europe/Warsaw "${debstrapFolder}/etc/localtime"

/etc/default/keyboard

If the target system uses the same keyboard layout as your host system, then to avoid a need for an interactive configuration, you can copy the host's keyboard config:

sudo cp /etc/default/keyboard "${debstrapFolder}/etc/default/keyboard"


chroot to the target system

Consider exporting temporarily LANG=C.UTF-8, then follow the basic procedure as described on chroot wiki.

Update apt DB

mmdebstrap leaves apt's DB uninitialized, so before anything else, run

apt update

Configure locales

If you don't want to change LANG to C.UTF-8, it's useful to perform this step early, to prevent the next steps from complaining. You can perform this step in 1 of 2 ways:

See Locale page for more info.

These packages are necessary for a kernel & firmware to be integrated into the boot process:

apt install grub-efi initramfs-tools fontconfig-config

Next, run grub-install command: if this is the only Debian installation on this physical drive, no arguments are needed and an EFI app named debian will be added to the ESP (as a subfolder in /boot/efi/EFI/). Otherwise you need to provide an alternative name using --bootloader-id, for example:

grub-install --bootloader-id=my-test-trixie

Install a kernel, necessary firmware and other critical packages

Use apt install to install the below packages:

After installing all the above packages, run

update-grub

Create user accounts and set passwords

If password for root user will not be set, it is necessary to create at least 1 user account, for example:

adduser myusername

This will interactively ask for user details and password (replace myusername with a username of your choice, of course).

This account must be able to use sudo, so it must be added to sudo group:

adduser myusername sudo

If you want to change a password for any user (or set it, for example for root user), run

passwd myusername

Install common tools and utils (optional)

You may find some of the below useful:

Install a graphic system (optional)

Install a desktop environment of your choice

ToDo: add other common DEs

Common GUI apps

Exit chroot

Exit the chroot either with exit command or by pressing CTRL+D.


Final cleanup

If you were using a AptCacherNg proxy directly from the host (ie 127.0.0.1), remove the proxy setting from ${debstrapFolder}/etc/apt/apt.conf.d/99mmdebstrap (or the whole file if there's nothing else there).

Finally, umount all the volumes and bind-mounts of the target system:

sudo umount -R "${debstrapFolder}"

The created system is now ready to boot the target machine.


UEFI settings

Modern implementations of UEFI firmware should be able to automatically detect the shim + Grub EFI app installed on the ESP and they will present it in the boot menu or boot it automatically if it's the only one. Some older versions (TianoCore in particular, used by default by QEMU/libvirt) may however need to be pointed to a specific .efi executable file in their UEFI settings, in which case EFI/${BOOTLOADER_ID}/shimx64.efi should be chosen.


Related tools


CategoryQuickInstall