KVM // Bootstrap Debian / Ubuntu / Kali

assuming the host is up and running already

this is almost a script

prepare vdisk

as root

    guest=bookworm

    mkdir -p /data/guests/$guest/lala/
    cd /data/guests/$guest/

    qemu-img create -f qcow2 $guest.qcow2 25G
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 $guest.qcow2
device=/dev/nbd0

manual partitioning

fdisk $device

n
p
ENTER
ENTER
ENTER
a
w

you could otherwise automate this as such

total=`fdisk -l $device | head -1 | awk '{print $7}'`

# 2048 * 512 = 1048576
echo -n writing vda.sfdisk...
cat > vda.sfdisk <<-EOF && echo done
label: dos
label-id: 0x8ae$((RANDOM % 10))$((RANDOM % 10))3cc
device: vda
unit: sectors

/dev/sda1 : start=2048, size=$((total-2048)), type=83, bootable
EOF
sfdisk $device < vda.sfdisk
#partprobe $device

further requirements

    mkfs.ext4 ${device}p1
    mount ${device}p1 lala/

# from an ubuntu system
apt install debian-keyring debian-archive-keyring
ls -lF /usr/share/keyrings/debian-archive-keyring.gpg

country_code=ru

bootstrap

cat /etc/apt/source.list
mirror=http://ftp.$country_code.debian.org/debian/
    time debootstrap --arch=amd64 $guest lala/ $mirror
du -sh lala/
# 357M bookworm
# 361M bookworm may '25

Guest setup

cat lala/etc/fstab
cat > lala/etc/fstab <<-EOF # override
/dev/vda1 / ext4 defaults 0 0
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs rw,nodev,nosuid,noatime,relatime 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
EOF
cat lala/etc/hostname
echo $guest > lala/etc/hostname

echo "127.0.0.1       $guest" >> lala/etc/hosts

rmdir lala/etc/network/interfaces.d/
vi lala/etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    address 192.168.122.9/24
    gateway 192.168.122.1

cat lala/etc/resolv.conf
    echo nameserver 192.168.122.1 > lala/etc/resolv.conf

Boot-blocks & kernel

we need a kernel in there as this is KVM, not XEN

    mount -o bind /dev lala/dev
    mount -o bind /dev/pts lala/dev/pts
    mount -o bind /sys lala/sys
    mount -o bind /proc lala/proc

chroot lala/ bash

passwd -d root

apt update
apt install locales
dpkg-reconfigure locales

==> en_US.UTF-8

    perl -e exit

apt install mlocate net-tools openssh-server manpages man-db
# ifupdown

apt install linux-image-cloud-amd64
# btrfs-progs
# linux-image-kvm
# linux-image-amd64

those links should have been created by the linux-image package already

ls -lF /vmlinuz
ls -lF /initrd.img

make sure whatever additional module you need at boot-time is in there

#grep -i btrfs /boot/config-*
grep -i virtio_console /boot/config-*

cd /boot/
cp -pi initrd.img-6.1.0-32-cloud-amd64 initrd.img-6.1.0-32-cloud-amd64.dist

cd /etc/initramfs-tools/
cp -pi modules modules.dist
vi modules

#btrfs
virtio_console

update-initramfs -k all -u

    apt install initramfs-tools
#lsinitramfs /boot/initrd.img-* | grep -i btrfs
lsinitramfs /boot/initrd.img-* | grep -i console

make sure the serial console prompt goes serial

systemctl list-unit-files | grep tty
systemctl disable getty@tty1.service
systemctl enable serial-getty@tty1.service
ls -lF /etc/systemd/system/getty.target.wants/

ready to leave the chroot

^D

now setup the kvm guest boot-loader and kernel-time serial console

ls -lh /usr/lib/syslinux/mbr/mbr.bin

    dd if=/usr/lib/syslinux/mbr/mbr.bin of=$device
    mkdir lala/boot/syslinux/
    extlinux --install lala/boot/syslinux --device ${device}p1
    cp -f /usr/lib/syslinux/modules/bios/mboot.c32 lala/boot/syslinux/
    cp -f /usr/lib/syslinux/modules/bios/libcom32.c32 lala/boot/syslinux/
vi lala/boot/syslinux/syslinux.cfg

    serial 0 115200
    console 1
    nohalt 1

    default linux
    prompt 1
    timeout 30

    label linux
      linux /vmlinuz
      initrd /initrd.img
      append root=/dev/vda1 ro console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 mitigations=off

umount -R lala/
rmdir lala/

#btrfsck ${device}p1
fsck.ext4 ${device}p1

#losetup --detach $device
qemu-nbd -d $device

ls -lhF $guest.qcow2
    du -sh $guest.qcow2
# 1.4G bookworm

Ready to go

ls -lhF /usr/bin/qemu-system-x86_64
cd /data/guests/$guest/
cat > $guest.xml <<EOF
<domain type='kvm'>
  <name>$guest</name>
  <memory unit='GiB'>1</memory>
  <currentMemory unit='GiB'>1</currentMemory>
  <vcpu placement='static'>2</vcpu>
  <os>
    <type arch='x86_64' machine='q35'>hvm</type>
    <boot dev='hd'/>
  </os>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/data/guests/$guest/$guest.qcow2'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <interface type='bridge'>
      <source bridge='virbr0'/>
      <model type='virtio'/>
    </interface>
    <serial type='pty'>
      <target type='isa-serial' port='0'>
    <model name='isa-serial'/>
      </target>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
  </devices>
</domain>
EOF
virsh list --all
virsh create $guest.xml --console

^]

maybe add your SSH pubkey in there and we’re good

Acceptance and template

ping opendns.com
poweroff

as root

virsh list --all | grep $guest # empty
cd /data/guests/
time nice tar cSf /data/templates/$guest.tar $guest/
ls -lh /data/templates/$guest.tar
# 1,1G

GNS3-ready

eventually make it available for GNS3

Troubleshooting

grub-install: error: unknown filesystem.

==> you need to see the partition, use losetup for that

while trying to launch the guest as user

error: Failed to create domain from bookworm.xml
error: internal error: /usr/lib/qemu/qemu-bridge-helper --use-vnet --br=virbr0 --fd=31: failed to communicate with bridge helper: Transport endpoint is not connected
stderr=failed to parse default acl file `/etc/qemu/bridge.conf'

==> …

Resources

https://stackoverflow.com/questions/21596384/cannot-disable-systemd-serial-getty-service

https://unix.stackexchange.com/questions/447070/serial-getty-error-messages


HOME | GUIDES | LECTURES | LAB | SMTP HEALTH | HTML5 | CONTACT
Copyright © 2024 Pierre-Philipp Braun