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.
Contents
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:
- GPT partitioning scheme is recommended over MBR.
- It is a common practice for an ESP to be the first physical partition on a given disk, but this is not mandatory.
Per UEFI spec, ESP must be formatted as fat and fat32 is the safest choice in practice.
- UEFI spec does not limit the number of ESPs on a single physical disk to 1, but bootloaders will most likely get confused if there's more than 1.
Debian and other distros using Grub as their bootloader, put just a few to few dozen of MB on ESPs (shim + 1st stage of Grub), so a 100MB ESP will be more than enough for them. However those using Systemd-boot need to put kernel images on the ESP as well, so in such case even 300MB may be needed (depending on the number of installed kernel versions). Finally Windows-11 requires at least 200MB and recommends 260MB+ for its disposal.
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.
Related tools and guides
parted yet another disk partitioning tool (GUI version: gparted)
General info on partitioning
qemu-img tool for creating disk images (qcow2 or raw) for QEMU VMs
qemu-nbd tool for connecting qcow2 disk images to a system's device nodes
A mini-HowTo on mounting qcow2 images
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.listThis will create a basic foundation of the new system using apt sources copied from host's /etc/apt/sources.list.
Replace /etc/apt/sources.list, if you want to use different sources (this is mandatory if you want to bootstrap a different release than the one of your host).
Replace trixie with the desired release codename (it must match the passed sources).
In certain scenarios, you probably can getaway with just important or even minbase as --variant instead of standard.
If qemu-user-binfmt is installed, you can create a system for any foreign arch it supports by specifying it with --architectures flag.
If you often use mmdebstrap, consider setting up AptCacherNg either on the host system or some very nearby server and add --aptopt='Acquire::http { Proxy "http://127.0.0.1:3142"; }' option to mmdebstrap (replace 127.0.0.1 as needed in case of a nearby server). In case of setting it up on the host system, you need to remove the proxy setting at the end of the procedure from ${debstrapFolder}/etc/apt/apt.conf.d/99mmdebstrap (or the whole file if there's nothing else there).
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
EOFThe - 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:
Interactively: run
dpkg-reconfigure locales
...and it will ask which locales to enable and which of these should be the default.- Non-Interactively:
Put your desired locales into /etc/locale.gen file, 1 per line, for example:
en_IE.UTF-8 UTF-8 vi_VN UTF-8
See /usr/share/i18n/SUPPORTED file for the full list of supported options.
Run
locale-gen
If you want to set a system-wide default locales, use update-locale program to set values for Lang and optionally also LANGUAGE vars in /etc/locale.conf file, for example:
update-locale LANG=en_IE.UTF-8 LANGUAGE="en_IE:en"
Make sure that /etc/default/locale link points to ../locale.conf file, if it doesn't, run
ln -sf ../locale.conf /etc/default/locale
See Locale page for more info.
Install Grub bootloader and its related packages
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:
Kernel: linux-image-generic
- Necessary firmware: this depends on the specific hardware of a given target system and typically includes:
- CPU microcode and integrated controllers' firmware, unless it's a VM:
On AMD and Intel x86_64 machines, either amd64-microcode or intel-microcode respectively (this is automatically installed if standard was passed as --variant to mmdebstrap).
On Snapdragon ARM machines, firmware-qcom-soc and firmware-qcom-dsp.
On Mediatek ARM machines, firmware-mediatek.
- GPU firmware, unless it's a headless machine or a VM without any physical GPUs redirected to it:
On x86_64 machines, it's usually at least one of firmware-{amd,intel,nvidia}-graphics.
On Snapdragon machines as of Trixie, iGPU's firmware is included in firmware-qcom-soc mentioned previously, on older releases firmware-qcom-media may be needed.
On Mediatek machines, iGPU's firmware is included in firmware-mediatek mentioned previously.
WiFi firmware, if such a card is present, usually one of firmware-iwlwifi (Intel), firmware-mediatek, firmware-brcm80211 (Broadcom), firmware-atheros, firmware-ath9k-htc (also Atheros).
wired ethernet firmware, if such a card is present (ToDo: list typical wired eth firmware).
- CPU microcode and integrated controllers' firmware, unless it's a VM:
If any critical devices are connected via a Thunderbolt/USB4 dock or PCIe adapter (like the machine's only keyboard/display or its main NIC when NIS or NFS are used), then bolt is necessary and at least initially, Thunderbolt security needs to be disabled in UEFI settings (note that this concerns only "real" Thunderbolt/USB4 devices, like multi-port docks or PCIe adapters: standard USB-3.x (or older) devices don't need bolt nor any other special setup, even when connected to the machine's Thunderbolt/USB4 port).
It is a common practice to not set a password for root user, in which case sudo is necessary.
keyboard-configuration: this ensures a proper functioning of different keyboard layouts. By default, an installation of this package will interactively ask for layout options, if you want to avoid it, either provide /etc/default/keyboard or create it manually and then install the package with DEBIAN_FRONTEND env var set to noninteractive:
DEBIAN_FRONTEND=noninteractive apt install keyboard-configuration
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:
curl: universal network fetching tool
network-manager: network configuration tool
fwupd: firmware updater
unattended-upgrades: installs security upgrades automatically
gpm: allows copy-pasting with a mouse on text consoles
bluetooth: allows to pair Bluetooth devices
console-based text editor of your choice: by default only nano and vim.tiny are installed
If the target system is a QEMU VM, then qemu-guest-agent
ssh: OpenSSH client and server
Install a graphic system (optional)
Install a desktop environment of your choice
MATE: apt install mate-desktop-environment-extras lightdm package-update-indicator
Gnome: apt install gnome-session gnome-software
ToDo: add other common DEs
Common GUI apps
synaptic: package manager
web-browser of your choice, for example firefox-esr, chromium etc
network-manager-applet: GUI for network-manager
gufw: GUI for ufw firewall
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
debvm-create wrapper script around mmdebstrap creating QEMU VMs
mmdebstrapbootable wrapper script around mmdebstrap creating Debian installations using supplied /etc/fstab
