How to install Debian from Debian

Using LVM and debootstrap

Despite the title, this installation method should work for any Debian derivatives including Ubuntu.

This tutorial explains how to re-install a Debian based distribution on a running system. This has the advantage that we do not need to use the Debian Installer and we can minimize the downtime to that of a reboot. It is also especially useful if we want to reuse data on existing logical volumes, like virtual machine disk images on a hypervisor.

Requirements

This guide requires that the system was installed in EFI mode and the usage of the following partition and LVM setup.

NAME           TYPE MOUNTPOINT
sda            disk
├─sda1         part /boot/efi
└─sda2         part
  ├─vg0-root   lvm  /
  ├─vg0-var    lvm  /var
  └─vg0-varlog lvm  /var/log

We have a single disk with two partitions, containing the ESP (EFI System Partition) and the LVM physical volume.

This guide also assumes we have 3 separate logical volumes for the mount points /, /var and /var/log and that we do not use UUIDs for the ext4 file-systems in /etc/fstab as shown below:

/dev/mapper/vg0-root   /         ext4 noatime,nodiratime,errors=remount-ro 0 1
UUID=5E4A-9F35         /boot/efi vfat umask=0077                           0 1
/dev/mapper/vg0-var    /var      ext4 noatime,nodiratime                   0 2
/dev/mapper/vg0-varlog /var/log  ext4 noatime,nodiratime                   0 2

Installation

First rename the existing LVs containing the running system:

lvrename /dev/vg0/var /dev/vg0/var2
lvrename /dev/vg0/varlog /dev/vg0/varlog2
lvrename /dev/vg0/root /dev/vg0/root2

Then create new LVs to contain the new system with initial names of our running system:

lvcreate -L 5G -n root vg0 -y
lvcreate -L 5G -n var vg0 -y
lvcreate -L 2G -n varlog vg0 -y
mkfs.ext4 /dev/vg0/root
mkfs.ext4 /dev/vg0/var
mkfs.ext4 /dev/vg0/varlog

Mount the LVs:

mount /dev/vg0/root /mnt
mkdir -p /mnt/var
mount /dev/vg0/var /mnt/var
mkdir /mnt/var/log
mount /dev/vg0/varlog /mnt/var/log

The next step is to bootstrap a minimal system using debootstrap:

debootstrap buster /mnt http://debian.ethz.ch/debian/

Before we chroot into the new system, we need to mount some special file-systems provided by the Kernel on our running system:

mount --bind /dev /mnt/dev
mount -t sysfs /sys /mnt/sys
mount -t proc none /mnt/proc
mount -t devpts devpts -o noexec,nosuid,gid=5,mode=620 /mnt/dev/pts
mount --bind /run /mnt/run

At this point we can already copy over some configuration files. Here are the files we need on a managed computer at the D-PHYS, adapt this for your setup:

cp -p /etc/apt/sources.list /mnt/etc/apt/sources.list
cp -p /etc/gai.conf /mnt/etc/
cp -p /etc/apt/apt.conf.d/90local /mnt/etc/apt/apt.conf.d/90local
cp -p /etc/default/grub /mnt/etc/default/grub
cp -p /etc/network/interfaces /mnt/etc/network/interfaces
cp -p /etc/systemd/network/* /mnt/etc/systemd/network/
cp -p /etc/hostname /mnt/etc/hostname
cp -rp /root/.ssh /mnt/root/
cp -rp /etc/ssh /mnt/etc/
cp -p /etc/fstab /mnt/etc/

Now we chroot into the new system and install the rest of the required packages, like the Kernel and grub. When grub asks where it should be installed, select nothing and choose not to install grub at this time. Grub should already be installed correctly.

chroot /mnt /bin/bash
apt-get update
apt-get upgrade -y
apt-get install linux-image-amd64 -y
apt-get install locales mdadm ssh dbus firmware-linux firmware-linux-nonfree -y
apt-get install grub2 lvm2 -y
apt-get install python-minimal python-apt vim -y

You should now configure your locales and time zone data:

dpkg-reconfigure locales
dpkg-reconfigure tzdata

and set a root password, for example using a hash:

usermod -p '<sha512-hash>' root

If you use systemd-networkd you need to enable it now:

systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service
rm /etc/resolv.conf
ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

To exit the chroot environment press Ctrl-d or enter:

exit

Now back on the initial system, we need to configure grub:

mkdir /mnt/boot/efi
cp -rp /boot/grub/* /mnt/boot/grub/

Replace the root LV's file-system UUID (see lsblk -f) and LV UUID (lvdisplay) in the following files:

  • /mnt/boot/grub/grub.cfg
  • /boot/efi/EFI/debian/grub.cfg

For example using sed:

sed -i 's/OLDFSUUID/NEWFSUUID/g' /mnt/boot/grub/grub.cfg
sed -i 's/OLDLVUUID/NEWLVUUID/g' /mnt/boot/grub/grub.cfg
sed -i 's/OLDFSUUID/NEWFSUUID/g' /boot/efi/EFI/debian/grub.cfg
sed -i 's/OLDLVUUID/NEWLVUUID/g' /boot/efi/EFI/debian/grub.cfg

Now we can unmount our target system at /mnt:

umount --recursive /mnt

You should also update /etc/fstab of the initial system to the names of the renamed LVs. Just in case should you encounter any problems and want to switch back to old system in /boot/efi/EFI/debian/grub.cfg.

Finally reboot into the new system:

reboot

Using netboot installer from disk

This guide shows how to manually set up a debian netboot installer on a separate disk that could also be installed into another system to boot from.

Alternatively this can also be done on the disk where the system is currently running. In that case the existing grub configuration needs to be modified as shown here.

Installation

Install and mount the disk to prepare with the installer images:

mkfs.ext4 /dev/sdb
mount /dev/sdb /mnt
cd /mnt
mkdir -p boot/newinstall
wget https://debian.ethz.ch/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz -O boot/newinstall/initrd.gz
wget https://debian.ethz.ch/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux -O boot/newinstall/linux

Optionally create and configure a preseed.cfg file for automatic installation and inject it into the initrd:

vim preseed.cfg
gunzip /mnt/boot/newinstall/initrd.gz
echo preseed.cfg | cpio -H newc -o -A -F /mnt/boot/newinstall/initrd
gzip /mnt/boot/newinstall/initrd

Install and configure the extlinux bootloader:

apt install extlinux
extlinux --install /mnt
cat > /mnt/syslinux.cfg << EOF
PROMPT 0
TIMEOUT 0
DEFAULT linux

LABEL linux
    LINUX /boot/newinstall/linux
    APPEND root=/dev/sda preseed/file=/preseed.cfg
    INITRD /boot/newinstall/initrd.gz
EOF
sync

References: