this is almost a script
as root
guest=buster guest=jammy 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/ apt install debian-keyring debian-archive-keyring ls -lF /usr/share/keyrings/debian-archive-keyring.gpg mirror=... time debootstrap --arch=amd64 $guest lala/ $mirror # 1m52,078s buster # 4m4,939s jammy
cat > lala/etc/fstab <<-EOF # override /dev/vda1 / btrfs defaults 0 1 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
ls -lF lala/etc/hostname # no exist echo $guest > lala/etc/hostname
To make Perl packages happy, you need to tweak bash.bashrc, not profile
cp -pi lala/etc/bash.bashrc lala/etc/bash.bashrc.dist cat >> lala/etc/bash.bashrc <<-EOF source /usr/share/bash-completion/bash_completion export LANGUAGE="en_US:en" export LC_ALL="C.UTF-8" export LC_COLLATE="C.UTF-8" export LANG="C.UTF-8" 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' EOF zone=Europe/Moscow ls -lF lala/etc/localtime ln -sf ../usr/share/zoneinfo/$zone lala/etc/localtime cat lala/etc/timezone echo $zone > lala/etc/timezone # override
point to the closest mirror
cat lala/etc/apt/sources.list
echo $mirror echo $release # debian cat > lala/etc/apt/sources.list <<-EOF deb $mirror $release main contrib non-free deb $mirror $release-updates main contrib non-free # $release-backports EOF # ubuntu cat > lala/etc/apt/sources.list <<-EOF deb $mirror $release main restricted universe multiverse deb $mirror $release-updates main restricted universe multiverse deb $mirror $release-security main restricted universe multiverse #deb $mirror $release-backports main restricted universe multiverse EOF
eventually setup a package proxy
vi lala/etc/apt/apt.conf.d/02proxy Acquire::http { Proxy "http://x.x.x.x:3142"; };
mv -i lala/etc/hosts lala/etc/hosts.dist cat > lala/etc/hosts <<-EOF 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters 10.1.0.7 $guest 10.1.255.254 gw EOF rmdir lala/etc/network/interfaces.d/ cat > lala/etc/network/interfaces <<-EOF # override auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.1.0.7/24 gateway 10.1.255.254 EOF
moar options
#dns-nameservers 208.67.222.222 208.67.220.220 #dns-search DOMAIN.TLD
we use our own stub-resolver
ls -lF lala/etc/resolv.conf* # not a symlink cat lala/etc/resolv.conf # kvm echo nameserver 192.168.122.1 > lala/etc/resolv.conf # dedibox echo 62.210.16.6 > lala/etc/resolv.conf echo 62.210.16.7 >> lala/etc/resolv.conf # opendns echo nameserver 208.67.222.222 > lala/etc/resolv.conf echo nameserver 208.67.222.220 >> lala/etc/resolv.conf # pmr nobudget echo nameserver 10.1.255.254 > lala/etc/resolv.conf echo nameserver 10.1.255.253 >> lala/etc/resolv.conf echo nameserver 10.1.255.252 >> lala/etc/resolv.conf echo nameserver 10.1.255.251 >> lala/etc/resolv.conf
now let’s proceed with the insider stuff
mount -o bind /dev/pts lala/dev/pts mount -o bind /proc lala/proc # rsyslog:systemd-tmpfiles chroot lala/ bash perl -e exit
console requires a password unless you tweak getty like hell – disabling it instead
passwd -d root #usermod -p '*' root
tune the guest userland serial console
systemctl get-default systemctl set-default multi-user # kvm-only #systemctl enable serial-getty@ttyS0.service
No NTP is required, this is a guest system
dpkg -l | grep ntp # not installed dpkg -l | grep chrony # not installed systemctl list-unit-files | grep ntp # not present systemctl list-unit-files | grep chrony # not present # ubuntu systemctl disable systemd-timesyncd
also disable the stub-on-steroids
dpkg -l | grep resolv # absent systemctl list-unit-files | grep resolv # systemd-resolved.service disabled already #systemctl disable systemd-resolved
perform a system upgrade before making a template out of it
export DEBIAN_FRONTEND=noninteractive apt update apt dist-upgrade apt autoremove --purge
you might also want those additional packages
apt install \ ifupdown \ locales \ net-tools \ man-db \ manpages \ openssh-server \ openssh-client \ mlocate \ netcat-openbsd \ nmap \ wget \ elvis-tiny \ bash-completion dpkg-reconfigure locale # en_US.UTF-8 ls -lF /usr/share/bash-completion/bash_completion
note bsd-mailx would install postfix or exim - we don’t want that
ls -lF /etc/postfix/main.cf # absent ls -lF /etc/exim4/ # absent
get rid of the generated keys
rm -f /etc/ssh/ssh_host_* systemctl list-unit-files | grep ssh
finally exit the chroot
updatedb ls -lF ~/.bash_history # nope history -c ^D
we’re done!
ls -lF lala/root/.bash_history # nope umount -R lala/ rmdir lala/
we need a kernel in there as this is KVM not XEN
chroot lala/ bash apt install linux-image-kvm btrfs-progs ^D ln -s boot/vmlinuz lala/vmlinuz
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
and see syslinux
umount -R lala/ rmdir lala/ btrfsck ${loopdevice}p1 losetup --detach $loopdevice ls -lh $guest.img du -sh $guest.img # 493M jammy.img
cat > $guest.xml <<EOF <domain type='kvm'> <name>$guest</name> <memory unit='GiB'>1</memory> <currentMemory unit='GiB'>1</currentMemory> <vcpu placement='static'>$((`grep ^processor /proc/cpuinfo | tail -1 | awk '{print $3}'` + 1))</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 chown ADMIN.adm $guest.xml
as user
guest=buster guest=jammy cd /data/guests/$guest/ 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