assuming the host is up and running already
this is almost a script
as root
guest=bookworm mkdir -p /data/guests/$guest/lala/ cd /data/guests/$guest/ dd if=/dev/zero of=$guest.img bs=1G count=0 seek=26 losetup -a | grep -v snapd loopdevice=`losetup --find --partscan --show $guest.img` echo loopdevice is $loopdevice
manual partitioning
fdisk $loopdevice n p ENTER ENTER ENTER a w fdisk -l $loopdevice
you could otherwise automate this as such
total=`fdisk -l $loopdevice | 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 $loopdevice < vda.sfdisk #partprobe $loopdevice
prepare the file-system
mkfs.btrfs ${loopdevice}p1 mount ${loopdevice}p1 lala/ 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 apt install debian-keyring debian-archive-keyring ls -lF /usr/share/keyrings/debian-archive-keyring.gpg cat /etc/apt/source.list mirror=... time debootstrap --arch=amd64 $guest lala/ $mirror
du -sh lala/
cat lala/etc/fstab cat > lala/etc/fstab <<-EOF # override /dev/vda1 / btrfs 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 vi lala/etc/apt/sources.list deb http://ftp.ru.debian.org/debian bookworm main contrib non-free non-free-firmware deb http://ftp.ru.debian.org/debian bookworm-updates main contrib non-free non-free-firmware # bookworm-backports cp -pi lala/etc/bash.bashrc lala/etc/bash.bashrc.dist vi lala/etc/bash.bashrc export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 export LANGUAGE=en_US:en alias ll='ls --group-directories-first --color=auto -alh' alias ls='ls --group-directories-first --color=auto' alias cp='cp -i' alias mv='mv -i' alias rm='rm -i' cat lala/etc/hostname echo $guest lala/etc/hostname echo "127.0.0.1 bookwworm" >> 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
we need a kernel in there as this is KVM, not XEN
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 butterfs whatever additional module you need at boot-time is in there
grep -i btrfs /boot/config-* grep -i virtio_console /boot/config-* cd /boot/ version=`uname -r` cp initrd.img-$version initrd.img-$version.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-$version | grep -i btrfs lsinitramfs /boot/initrd.img-$version | grep -i console unset version
make sure the serial console prompt goes serial
systemctl disable getty@tty1.service systemctl enable serial-getty@.service systemctl list-unit-files | grep getty 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=$loopdevice mkdir lala/boot/syslinux/ extlinux --install lala/boot/syslinux --device ${loopdevice}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 ${loopdevice}p1 losetup --detach $loopdevice ls -lhF $guest.img du -sh $guest.img
echo $((`grep ^processor /proc/cpuinfo | tail -1 | awk '{print $3}'` + 1)) ls -lhF /usr/bin/qemu-system-x86_64
here with 3 vcpu and 1GiB of RAM
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'>3</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='raw'/> <source file='/data/guests/$guest/$guest.img'/> <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 ^] virsh console $guest ^]
maybe add your SSH pubkey in there and we’re good
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
eventually make it available for GNS3
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'
==> …
https://stackoverflow.com/questions/21596384/cannot-disable-systemd-serial-getty-service
https://unix.stackexchange.com/questions/447070/serial-getty-error-messages