Installation of Debian 12 UEFI on internal SSD using debootstrap

Preface

This guide assumes that you already have Debian installed either on the internal drive, on external drive, or on USB stick.

Requirements

Warning: all data on the SSD will be destroyed during the installation!

In this guide the installation is performed on 1 TiB internal SSD. Change the size of your partitions accordingly to your SSD's maximum capacity.

Preparation

Install 'debootstrap'.

sudo apt update
sudo apt upgrade -y
sudo apt install debootstrap

Find the device name.

Run 'lsblk' to list all avaliable devices.

lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 953.9G  0 disk 
nvme0n1     259:0    0 931.5G  0 disk 
├─nvme0n1p1 259:1    0   560M  0 part /boot/efi
├─nvme0n1p2 259:2    0     4G  0 part [SWAP]
├─nvme0n1p3 259:3    0   120G  0 part /
└─nvme0n1p4 259:4    0   807G  0 part /home

My SSD is brand new and does not have any partitions on it. In my case, SSD's name is /dev/sda.

Warning: if you select the wrong device during the installation, all the data on that device will be destroyed.

Partitioning the SSD

Make sure you are working with the correct device! Use 'su -l' command to switch user to root.

su -l
cd /

Check your $PATH variable.

echo "$PATH" | tr ':' '\n'

If it lacks '/sbin' and '/usr/sbin', add them (bash syntax).

declare -x PATH="$PATH:/sbin:/usr/sbin"

Use 'gdisk' to partition the device.

gdisk /dev/sda

On 'gdisk' prompt type 'o' and press 'Enter' to create a new empty GUID partition table (GPT).

Type 'n' to create a new partiton, press 'Enter' on prompts to select partiton number and the first sector. For last sector type '+560M'. If the boot partition will be smaller than 560 mebibytes, some buggy UEFI firmware may fail to read the contents of boot partition. Type 'ef00' in the 'Hex code or GUID' prompt to change the type of partition to the 'EFI System' type. You can always press 't' to change the partition's type code, if you've accidentally chosen a wrong partition type.

Type 'n' to create a new partition, press 'Enter' on prompts to select partiton number and the first sector. For last sector type '+4G'. Type '8200' in the 'Hex code or GUID' prompt to change the type of partition to the 'Linux swap' type. It is important to have a swap partition on Linux system. Without swap, if the kernel runs out of memory, it will kill random process to free the memory. Depending on the process, the system may crash resulting in data loss.

Type 'n' to create a new partition, press 'Enter' on prompts to select partiton number and the first sector. For last sector type '+120G'. Type '8304' in the 'Hex code or GUID' prompt to change the type of partition to the 'Linux x86-64 root (/)' type.

Type 'n' to create a new partiton, press 'Enter' on prompts to select partiton number, the first sector and the last sector. Type '8302' in the 'Hex code or GUID' prompt to change the type of partition to the 'Linux /home' type.

Type 'p' to view the full partition table, type 'i' to view detailed information on each individual partition. It is advisable to save that information into a text file, for you to be able to restore partitions manually if partition table gets damaged in the future.

Type 'w' and press 'Enter' to save partition table and exit 'gdisk'.

An automatic backup of the partition table can be performed with this command:

sgdisk -b wdSSDbackup.gpt /dev/sda

To restore the partition table from 'wdSSDbackup.gpt' file, run 'gdisk /dev/sda', press 'r' to enter 'recovery and transformation' menu, then press 'l' to load partition data from 'wdSSDbackup.gpt' file. Type 'w' to save partition table.

Run 'lsblk' to list all avaliable devices.

lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 953.9G  0 disk 
├─sda1        8:1    0   560M  0 part 
├─sda2        8:2    0     4G  0 part 
├─sda3        8:3    0   120G  0 part 
└─sda4        8:4    0 829.3G  0 part 
nvme0n1     259:0    0 931.5G  0 disk 
├─nvme0n1p1 259:1    0   560M  0 part /boot/efi
├─nvme0n1p2 259:2    0     4G  0 part [SWAP]
├─nvme0n1p3 259:3    0   120G  0 part /
└─nvme0n1p4 259:4    0   807G  0 part /home

Formatting the SSD disk

EFI partition must have FAT32 filesystem. Make sure to specity '-F 32' parameter to 'mkfs.fat' or it may automatically choose FAT16 filesystem. Some UEFI systems are unable to boot from EFI partition formatted as FAT16. Use '-n' to set the volume name (label) to be able to easily identify it later. For FAT32 partition labels must be no longer than 11 characters and contain only uppercase letters.

mkfs.fat -F 32 -n 'WDBOOT' /dev/sda1

Format /dev/sda2 as swap. '-L' parameter sets the label of the partition.

mkswap -L 'WDSWAP' /dev/sda2

Format /dev/sda3 as ext4 filesystem. '-L' parameter sets the label of the partition.

mkfs.ext4 -L 'WDROOT' /dev/sda3

Format /dev/sda4 as ext4 filesystem. '-L' parameter sets the label of the partition.

mkfs.ext4 -L 'WDHOME' /dev/sda4

Run 'blkid' with 'grep' to check newly created and formatted partitions.

blkid | grep 'sda'

Mounting the SSD's partitions

Mount the /dev/sda3 partition on /mnt using 'mount' command.

mount /dev/sda3 /mnt

Create the /mnt/boot/efi directories using 'mkdir -p' command.

mkdir -p /mnt/boot/efi

Mount the /dev/sda1 partition on /mnt/boot/efi using 'mount' command.

mount /dev/sda1 /mnt/boot/efi

Create the /mnt/home directory using 'mkdir' command.

mkdir /mnt/home

Mount the /dev/sda4 partition on /mnt/home using 'mount' command.

mount /dev/sda4 /mnt/home

Installation of Debian 12 on the SSD disk

Temporarily move swap space from the device on which you are currently booted to the SSD disk to not interfere with the installation of the new system.

Change the swap space accordingly to your devices, in my case they are /dev/nvme0n1p2 and /dev/sda2.

swapon /dev/sda2
swapoff /dev/nvme0n1p2

Run 'lsblk' ensure everything is done correctly.

lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 953.9G  0 disk 
├─sda1        8:1    0   560M  0 part /mnt/boot/efi
├─sda2        8:2    0     4G  0 part [SWAP]
├─sda3        8:3    0   120G  0 part /mnt
└─sda4        8:4    0 829.3G  0 part /mnt/home
nvme0n1     259:0    0 931.5G  0 disk 
├─nvme0n1p1 259:1    0   560M  0 part /boot/efi
├─nvme0n1p2 259:2    0     4G  0 part 
├─nvme0n1p3 259:3    0   120G  0 part /
└─nvme0n1p4 259:4    0   807G  0 part /home

Install Debian 12 system on /mnt using 'debootstrap'. 'bookworm' is the codename of Debian 12. The process will take some time, so be patient.

debootstrap bookworm /mnt

If your current installation was performed without Internet connection from a 'Live DVD', you will need to add online sources to your /etc/apt/sources.list to be able to update.

Example of Debian 12/Bookworm (stable) /etc/apt/sources.list containing only free software:

deb http://deb.debian.org/debian bookworm main
deb http://deb.debian.org/debian-security/ bookworm-security main
deb http://deb.debian.org/debian bookworm-updates main

Example of Debian 12/Bookworm (stable) /etc/apt/sources.list containing free software and proprietary firmware:

deb http://deb.debian.org/debian bookworm main non-free-firmware
deb http://deb.debian.org/debian-security/ bookworm-security main non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main non-free-firmware

Example of Debian 12/Bookworm (stable) /etc/apt/sources.list containing free software, proprietary firmware and proprietary software:

deb http://deb.debian.org/debian bookworm main non-free-firmware contrib non-free
deb http://deb.debian.org/debian-security/ bookworm-security main non-free-firmware contrib non-free
deb http://deb.debian.org/debian bookworm-updates main non-free-firmware contrib non-free

If you are currently running Debian 12, copy your /etc/apt/sources.list to /mnt/etc/apt/ directory using 'cp'.

cp /etc/apt/sources.list /mnt/etc/apt/

If you are currently running Debian 10, or Debian 11, create /mnt/etc/apt/sources.list file with the contents from the appropriate listing above.

If you are planning to use desktop environment based on the GTK toolkit, you will need to install and use 'qt5ct' program (after you install the desktop environment) to be able to change appearance of programs based on the Qt toolkit such as 'VLC media player', 'KchmViewer' and 'ghostwriter'. For the 'qt5ct' program to be able to work, this line must be present in /mnt/etc/environment file: 'QT_QPA_PLATFORMTHEME=qt5ct'. This line will only affect desktop environments not based on Qt toolkit and will have no effect on those based on Qt toolkit such as 'KDE' and 'LXQt'.

Edit /mnt/etc/environment file by adding 'QT_QPA_PLATFORMTHEME=qt5ct' line to the list of existing variables (if any).

nano /mnt/etc/environment

Example of /mnt/etc/environment:

QT_QPA_PLATFORMTHEME=qt5ct

Copy /etc/fstab to /mnt/etc/ and edit it changing UUIDs to those listed by your 'blkid' command. Add 'noatime' to increase the lifespan of the SSD.

cp /etc/fstab /mnt/etc/
blkid | grep 'sda'
nano /mnt/etc/fstab

If you are using 'vim' text editor, there is a convenient way to import the ouput of 'blkid' into the /mnt/etc/fstab file to be able to copy UUIDs from that output and then edit /mnt/etc/fstab: open /mnt/etc/fstab, create an empty line at the bottom of the file, move to that line, while in normal mode type ':' to enter command mode, then type:

.!blkid | grep 'sda'

Example of /mnt/etc/fstab:

UUID=9593ebc5-b95c-fec7-48a8-6c5f64a2bfdf / ext4 noatime,errors=remount-ro 0 1
UUID=4973-2DEF /boot/efi vfat noatime,umask=0077 0 1
UUID=ae82bbb5-e108-922d-7869-22a364a2c064 /home ext4 defaults,noatime 0 2
UUID=43ee645d-ba32-13fa-7812-d43a64a2c089 none swap sw 0 0
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0

If you have at least 16GiB of system memory, it is advisable to mount /tmp on 'tmpfs' - a memory file system. Doing so will increase the lifespan of the SSD.

Example of /mnt/etc/fstab with /tmp mounted on 'tmpfs':

UUID=9593ebc5-b95c-fec7-48a8-6c5f64a2bfdf / ext4 noatime,errors=remount-ro 0 1
UUID=4973-2DEF /boot/efi vfat noatime,umask=0077 0 1
UUID=ae82bbb5-e108-922d-7869-22a364a2c064 /home ext4 defaults,noatime 0 2
UUID=43ee645d-ba32-13fa-7812-d43a64a2c089 none swap sw 0 0
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
tmpfs /tmp tmpfs defaults,nosuid,nodev,size=7G 0 0

'size=7G' is the maximum amount of system memory /tmp is allowed to use, it will only be allocated when it is actually needed. For example, if the /tmp is only 200 MiB, the 'tmpfs' will allocate only 200 MiB of system memory.

Set the hostname by editing /mnt/etc/hostname. It must contain one line with one word in it. Default is 'debian'. Then add your hostname to /mnt/etc/hosts.

nano /mnt/etc/hostname
nano /mnt/etc/hosts

Example of /mnt/etc/hostname:

yourhostname

Example of /mnt/etc/hosts:

127.0.0.1	localhost
127.0.1.1	yourhostname
::1		localhost ip6-localhost ip6-loopback
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters

Create /mnt/etc/papersize file to set the default printer paper size for your region. It must contain one line with either 'letter', or 'a4' word in it. Default is 'letter'.

nano /mnt/etc/papersize

Example of /mnt/etc/papersize:

a4

Copy /etc/resolv.conf to /mnt/etc/ to have Internet connection while being in chrooted environment.

cp /etc/resolv.conf /mnt/etc/

Edit /mnt/etc/security/limits.conf to disable core dumps. Unless you are software developer and/or willing to debug the core files, there is no reason for the system to generate those files when programs crash.

nano /mnt/etc/security/limits.conf

Scroll down below the line '#<domain> <type> <item> <value>' and add the following:

* soft core 0
* hard core 0
root soft core 0
root hard core 0

Mount virtual filesystems on /mnt.

mount -v --bind /dev /mnt/dev
mount -vt devpts /dev/pts /mnt/dev/pts
mount -vt proc /proc /mnt/proc
mount -vt sysfs /sys /mnt/sys
mount -vt tmpfs /run /mnt/run

Changing root into SSD

Use 'chroot' command to change root into /mnt, which is the / filesystem of the SSD.

chroot /mnt

Check your $PATH variable.

echo "$PATH" | tr ':' '\n'

If it lacks '/sbin' and '/usr/sbin', add them (bash syntax).

declare -x PATH="$PATH:/sbin:/usr/sbin"

Set password for user 'root' using 'passwd' command.

passwd

Update and upgrade the system using 'apt'.

apt update
apt upgrade -y

Install locales.

apt install locales

Select your locale settings by running 'dpkg-reconfigure locales' command.

dpkg-reconfigure locales

Select your time zome settings by running 'dpkg-reconfigure tzdata' command.

dpkg-reconfigure tzdata

Install Linux kernel, sudo, network-manager.

apt install linux-image-amd64 sudo network-manager

You can obtain the UUID of your swap partition by using 'grep' and 'cut' commands:

grep 'sw[[:blank:]]' /etc/fstab | cut -c '6-41'

If it looks correct, create /etc/initramfs-tools/conf.d/resume file with sting 'RESUME=UUID=' and UUID of your swap partition by redirecting the output of 'printf' command into /etc/initramfs-tools/conf.d/resume file:

> /etc/initramfs-tools/conf.d/resume printf 'RESUME=%s\n' "$(grep 'sw[[:blank:]]' /etc/fstab | cut -c '-41')"

Example of /etc/initramfs-tools/conf.d/resume:

RESUME=UUID=43ee645d-ba32-13fa-7812-d43a64a2c089

Install 'grub2' bootloader.

apt install grub-efi-amd64

Open /etc/default/grub file and remove 'quiet' from 'GRUB_CMDLINE_LINUX_DEFAULT' line to be able to see kernel messages during system boot. Then uncomment 'GRUB_DISABLE_OS_PROBER=false' line by removing '#' symbol from the beginning of the line to allow 'grub2' to detect other operating systems installed on the computer. Read the commentary above that line explaining why it is disabled by default in Debian 12.

nano /etc/default/grub

Example of modified 'GRUB_CMDLINE_LINUX_DEFAULT' line:

GRUB_CMDLINE_LINUX_DEFAULT=""

Example of modified 'GRUB_DISABLE_OS_PROBER=false' line:

GRUB_DISABLE_OS_PROBER=false

Update bootloader's configuration.

grub-install --target=x86_64-efi --force-extra-removable /dev/sda
update-initramfs -u
update-grub

The '--force-extra-removable' parameter is required to make SSD bootable on cheap motherboards and also allows the operating system on the SSD to be detected when plugged into any computer with UEFI firmware. This allows you to install this SSD into a new computer without changing anything related to the boot process. The '--force-extra-removable' parameter will force 'grub2' to create /boot/efi/EFI/BOOT/ directory with files bootx64.efi, fbx64.efi, grub.cfg, grubx64.efi in it. On any motherboards the UEFI firmware will search for the /boot/efi/EFI/BOOT/bootx64.efi file on the device's EFI partition during the boot process of the computer.

You will need to reinstall 'grub2' with '--force-extra-removable' parameter after every kernel upgrade to update the /boot/efi/EFI/BOOT/ directory.

grub-install --target=x86_64-efi --force-extra-removable /dev/sda
update-initramfs -u
update-grub

On some cheap motherboards it is possible that UEFI firmware will only boot from /boot/efi/EFI/MICROSOFT/BOOT/bootmgfw.efi, which is a location of Windows boot manager. In that case you need to copy contents of /boot/efi/EFI/BOOT/ to /boot/efi/EFI/MICROSOFT/BOOT/ and rename bootx64.efi to bootmgfw.efi. The FAT32 filesystem is case-insensitive, in your case it may be /boot/efi/efi/boot/, BOOTX64.EFI, or any combination of the above. If your motherboard boots only from /boot/efi/EFI/MICROSOFT/BOOT/bootmgfw.efi file, you will have to repeat this procedure every time the kernel gets upgraded.

mkdir -p /boot/efi/EFI/MICROSOFT/BOOT/
cd /boot/efi/EFI/MICROSOFT/BOOT/
cp /boot/efi/EFI/BOOT/* ./
cp bootx64.efi bootmgfw.efi
cd /

Install the 'X11' graphical server and client.

apt install xorg

Install login manager and desktop environment.

apt install lightdm xfce4 xfce4-goodies xfce4-power-manager gvfs-backends gvfs-fuse qt5ct

Install other packages:

apt install cups-bsd printer-driver-cups-pdf dc bc groff gawk vim-gtk3 htop mupdf firefox-esr libreoffice gimp

If you are using Debian 12 and got a prompt to enter root's password while installing 'printer-driver-cups-pdf', press 'ENTER' instead of typing root's password. You will have to reinstall some packages later, when you'll boot from this SSD. Refer to 'Troubleshooting' section at the bottom of this guide on how to reinstall packages.

Add user with administrative priviledges using 'useradd' command (user must be a member of the 'sudo' group to be able to use 'sudo' command), set user's password using 'passwd' command.

useradd -mG cdrom,floppy,sudo,audio,dip,video,plugdev,netdev,lpadmin,scanner -s /usr/bin/bash -c 'Name' username
passwd username

Exit chrooted environment using 'exit' command.

exit

Unmount the /mnt

Change swap space back to your drive currently running the operating system. In my case it's /dev/nvme0n1p2.

swapon /dev/nvme0n1p2
swapoff /dev/sda2

Unmount the virtual filesystems.

umount /mnt/run
umount /mnt/sys
umount /mnt/proc
umount /mnt/dev/pts
umount /mnt/dev

Unmount physical filesystems.

umount /mnt/boot/efi/
umount /mnt/home
umount /mnt

Exit from root's shell.

exit

Booting from the SSD

Read you motherboard's manual to find which key will launch the 'Boot menu' during system boot. Usually it's 'F8' or 'F12'.

Reboot your computer, during boot sequence in the beginning rapidly press the boot key ('F8' in my case) to launch the 'Boot menu'. Using arrow keys on the keyboard, navigate to your SSD menu entry. If you have 'Legacy mode' enabled, select the entry with 'UEFI:' text in it. If everything was done correctly, you'll be booting into new Debian 12 system that is located on your SSD.

Troubleshooting

• If the graphical login manager did not lauch, press 'Ctrl+Alt+F1', or 'Ctrl+Alt+F2' keys to launch text console, login as 'root', enable and start 'lightdm' using 'systemctl' command.

systemctl enable lightdm
systemctl start lightdm

Reboot using 'reboot' command.

reboot

• If you are using Debian 12 you may experience some errors while installing packages in chrooted environment. In Debian 12 some activity is forbidden in chrooted environment due to security reasons. You will have to reinstall problematic packages using 'sudo apt reinstall' command after you have been booted from this SSD.

sudo apt reinstall linux-image-amd64 pkexec policykit-1 polkitd cups-bsd printer-driver-cups-pdf

• On a freshly installed Debian 12 system look at '/var/log/boot.log' right after the boot process is complete by using 'sed' and 'date' commands.

sudo sed -n "/$(date '+%a %b %d %H')/,\$p" /var/log/boot.log | less -r

If there is no output, change the '%H' to numeric value of previous hour (double-digit 24-hour format).

Example of the same command with explicitly set hour value:

sudo sed -n "/$(date '+%a %b %d 03')/,\$p" /var/log/boot.log | less -r

If this error is present:

[FAILED] Failed to start logrotate.service - Rotate log files.
See 'systemctl status logrotate.service' for details.

Enable 'logrotate.service' by using 'systemctl' command.

sudo systemctl daemon-reload
sudo systemctl start logrotate

Check the status of 'logrotate.service'.

systemctl status logrotate.service