I’m migrating some self-hosted virtual machines to Trisquel, and noticed that Trisquel does not offer cloud-images similar to the Debian Cloud and Ubuntu Cloud images. Thus my earlier approach based on virt-install --cloud-init and cloud-localds does not work with Trisquel. While I hope that Trisquel will eventually publish cloud-compatible images, I wanted to document an alternative approach for Trisquel based on preseeding. This is how I used to install Debian and Ubuntu in the old days, and the automated preseed method is best documented in the Debian installation manual. I was hoping to forget about the preseed format, but maybe it will become one of those legacy technologies that never really disappears? Like FAT16 and 8-bit microcontrollers.
Below I assume you have a virtual machine host server up that runs libvirt and has virt-install and similar tools; install them with the following command. I run a pre-release version of Trisquel 11 aramo on my VM-host, but I believe any recent dpkg-based distribution like Trisquel 9/10, PureOS 10, Debian 11 or Ubuntu 20.04/22.04 would work.
apt-get install libvirt-daemon-system virtinst genisoimage cloud-image-utils osinfo-db-tools
The approach can install Trisquel 9 (etiona), Trisquel 10 (nabia) and the pre-release of Trisquel 11. First download and verify the integrity of the netinst images that we will need. Unfortunately the Trisquel 11 netinst beta image does not have any checksum or signature available.
mkdir -p /root/isocd /root/isowget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_9.0.2\_amd64.isowget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_9.0.2\_amd64.iso.ascwget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_9.0.2\_amd64.iso.sha256wget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_10.0.1\_amd64.isowget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_10.0.1\_amd64.iso.ascwget -q https://mirror.fsf.org/trisquel-images/trisquel-netinst\_10.0.1\_amd64.iso.sha256wget -q -O- https://archive.trisquel.info/trisquel/trisquel-archive-signkey.gpg | gpg --importsha256sum -c trisquel-netinst\_9.0.2\_amd64.iso.sha256gpg --verify trisquel-netinst\_9.0.2\_amd64.iso.ascsha256sum -c trisquel-netinst\_10.0.1\_amd64.iso.sha256gpg --verify trisquel-netinst\_10.0.1\_amd64.iso.ascwget -q https://cdbuilds.trisquel.org/aramo/trisquel-netinst\_11.0-20221225\_amd64.isoecho '179566639ca8f14f0c3d5658209c59a0916d9e3bf9c026660cc07b28f2311631 trisquel-netinst\_11.0-20221225\_amd64.iso' | sha256sum -c
I have developed the following fairly minimal preseed file that works with all three Trisquel releases. Compare it against the official Trisquel 11 preseed skeleton and the Debian 11 example preseed file. You should modify obvious things like SSH key, host/IP settings, partition layout and decide for yourself how to deal with passwords. While Ubuntu/Trisquel usually wants to setup a user account, I prefer to login as root hence setting ‘passwd/root-login‘ to true and ‘passwd/make-user‘ to false.
root@trana:~# cat>trisquel.preseed d-i debian-installer/locale select en\_USd-i keyboard-configuration/xkb-keymap select usd-i netcfg/choose\_interface select autod-i netcfg/disable\_autoconfig boolean trued-i netcfg/get\_ipaddress string 192.168.10.201d-i netcfg/get\_netmask string 255.255.255.0d-i netcfg/get\_gateway string 192.168.10.46d-i netcfg/get\_nameservers string 192.168.10.46d-i netcfg/get\_hostname string trisqueld-i netcfg/get\_domain string sjd.sed-i clock-setup/utc boolean trued-i time/zone string UTCd-i mirror/country string manuald-i mirror/http/hostname string ftp.acc.umu.sed-i mirror/http/directory string /mirror/trisquel/packagesd-i mirror/http/proxy stringd-i partman-auto/method string regulard-i partman-partitioning/confirm\_write\_new\_label boolean trued-i partman/choose\_partition select finishd-i partman/confirm boolean trued-i partman/confirm\_nooverwrite boolean trued-i partman-basicfilesystems/no\_swap boolean falsed-i partman-auto/expert\_recipe string myroot :: 1000 50 -1 ext4 \ $primary{ } $bootable{ } method{ format } \ format{ } use\_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ .d-i partman-auto/choose\_recipe select myrootd-i passwd/root-login boolean trued-i user-setup/allow-password-weak boolean trued-i passwd/root-password password r00tmed-i passwd/root-password-again password r00tmed-i passwd/make-user boolean falsetasksel tasksel/first multiselectd-i pkgsel/include string openssh-serverpopularity-contest popularity-contest/participate boolean falsed-i grub-installer/only\_debian boolean trued-i grub-installer/with\_other\_os boolean trued-i grub-installer/bootdev string defaultd-i finish-install/reboot\_in\_progress noted-i preseed/late\_command string mkdir /target/root/.ssh ; echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzCFcHHrKzVSPDDarZPYqn89H5TPaxwcORgRg+4DagE cardno:FFFE67252015 > /target/root/.ssh/authorized\_keys^Droot@trana:~#
Use the file above as a skeleton for preparing a VM-specific preseed file as follows. The environment variables HOST and IPS will be used later on too.
root@trana:~# HOST=fooroot@trana:~# IP=192.168.10.197root@trana:~# sed -e "s,get\_ipaddress string.*,get\_ipaddress string $IP," -e "s,get\_hostname string.*,get\_hostname string $HOST," < trisquel.preseed > vm-$HOST.preseedroot@trana:~#
The following script is used to prepare the ISO images with the preseed file that we will need. This script is inspired by the Debian Wiki Preseed EditIso page and the Trisquel ISO customization wiki page. There are a couple of variations based on earlier works. Paths are updated to match the Trisquel netinst ISO layout, which differ slightly from Debian. We modify isolinux.cfg to boot the auto label without a timeout. On Trisquel 11 the auto boot label exists, but on Trisquel 9 and Trisquel 10 it does not exist so we add it in order to be able to start the automated preseed installation.
root@trana:~# cat gen-preseed-iso #!/bin/sh# Copyright (C) 2018-2022 Simon Josefsson -- GPLv3+# https://wiki.debian.org/DebianInstaller/Preseed/EditIso# https://trisquel.info/en/wiki/customizing-trisquel-isoset -eset -xISO="$1"PRESEED="$2"OUTISO="$3"LASTPWD="$PWD"test -f "$ISO"test -f "$PRESEED"test ! -f "$OUTISO"TMPDIR=$(mktemp -d)mkdir "$TMPDIR/mnt"mkdir "$TMPDIR/tmp"cp "$PRESEED" "$TMPDIR"/preseed.cfgcd "$TMPDIR"mount "$ISO" mnt/cp -rT mnt/ tmp/umount mnt/chmod +w -R tmp/gunzip tmp/initrd.gzecho preseed.cfg | cpio -H newc -o -A -F tmp/initrdgzip tmp/initrdchmod -w -R tmp/sed -i "s/timeout 0/timeout 1/" tmp/isolinux.cfgsed -i "s/default vesamenu.c32/default auto/" tmp/isolinux.cfgif ! grep -q auto tmp/adtxt.cfg; then cat<<EOF >> tmp/adtxt.cfglabel automenu label ^Automated installkernel linuxappend auto=true priority=critical vga=788 initrd=initrd.gz --- quietEOFficd tmp/find -follow -type f | xargs md5sum > md5sum.txtcd ..cd "$LASTPWD"genisoimage -r -J -b isolinux.bin -c boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -o "$OUTISO" "$TMPDIR/tmp/"rm -rf "$TMPDIR"exit 0^Droot@trana:~# chmod +x gen-preseed-iso root@trana:~#
Next run the command on one of the downloaded ISO image and the generated preseed file.
root@trana:~# ./gen-preseed-iso /root/iso/trisquel-netinst\_10.0.1\_amd64.iso vm-$HOST.preseed vm-$HOST.iso+ ISO=/root/iso/trisquel-netinst\_10.0.1\_amd64.iso+ PRESEED=vm-foo.preseed+ OUTISO=vm-foo.iso+ LASTPWD=/root+ test -f /root/iso/trisquel-netinst\_10.0.1\_amd64.iso+ test -f vm-foo.preseed+ test ! -f vm-foo.iso+ mktemp -d+ TMPDIR=/tmp/tmp.mNEprT4Tx9+ mkdir /tmp/tmp.mNEprT4Tx9/mnt+ mkdir /tmp/tmp.mNEprT4Tx9/tmp+ cp vm-foo.preseed /tmp/tmp.mNEprT4Tx9/preseed.cfg+ cd /tmp/tmp.mNEprT4Tx9+ mount /root/iso/trisquel-netinst\_10.0.1\_amd64.iso mnt/mount: /tmp/tmp.mNEprT4Tx9/mnt: WARNING: source write-protected, mounted read-only.+ cp -rT mnt/ tmp/+ umount mnt/+ chmod +w -R tmp/+ gunzip tmp/initrd.gz+ echo preseed.cfg+ cpio -H newc -o -A -F tmp/initrd5 blocks+ gzip tmp/initrd+ chmod -w -R tmp/+ sed -i s/timeout 0/timeout 1/ tmp/isolinux.cfg+ sed -i s/default vesamenu.c32/default auto/ tmp/isolinux.cfg+ grep -q auto tmp/adtxt.cfg+ cat+ cd tmp/+ find -follow -type f+ xargs md5sum+ cd ..+ cd /root+ genisoimage -r -J -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o vm-foo.iso /tmp/tmp.mNEprT4Tx9/tmp/I: -input-charset not specified, using utf-8 (detected in locale settings)Using GCRY\_000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/gcry\_sha512.mod (gcry\_sha256.mod)Using XNU\_U000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/xnu\_uuid.mod (xnu\_uuid\_test.mod)Using PASSW000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/password\_pbkdf2.mod (password.mod)Using PART\_000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/part\_sunpc.mod (part\_sun.mod)Using USBSE000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/usbserial\_pl2303.mod (usbserial\_ftdi.mod)Using USBSE001.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/usbserial\_ftdi.mod (usbserial\_usbdebug.mod)Using VIDEO000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/videotest.mod (videotest\_checksum.mod)Using GFXTE000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/gfxterm\_background.mod (gfxterm\_menu.mod)Using GCRY\_001.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/gcry\_sha256.mod (gcry\_sha1.mod)Using MULTI000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/multiboot2.mod (multiboot.mod)Using USBSE002.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/usbserial\_usbdebug.mod (usbserial\_common.mod)Using MDRAI000.MOD;1 for /tmp/tmp.mNEprT4Tx9/tmp/boot/grub/x86\_64-efi/mdraid09.mod (mdraid09\_be.mod)Size of boot image is 4 sectors -> No emulation 22.89% done, estimate finish Thu Dec 29 23:36:18 2022 45.70% done, estimate finish Thu Dec 29 23:36:18 2022 68.56% done, estimate finish Thu Dec 29 23:36:18 2022 91.45% done, estimate finish Thu Dec 29 23:36:18 2022Total translation table size: 2048Total rockridge attributes bytes: 24816Total directory bytes: 40960Path table size(bytes): 64Max brk space used 4600021885 extents written (42 MB)+ rm -rf /tmp/tmp.mNEprT4Tx9+ exit 0root@trana:~#
Now the image is ready for installation, so invoke virt-install as follows. The machine will start directly, launching the preseed automatic installation. At this point, I usually click on the virtual machine in virt-manager to follow screen output until the installation has finished. If everything works OK the machines comes up and I can ssh into it.
root@trana:~# virt-install --name $HOST --disk vm-$HOST.img,size=5 --cdrom vm-$HOST.iso --osinfo linux2020 --autostart --noautoconsole --waitUsing linux2020 default --memory 4096Starting install...Allocating 'vm-foo.img' | 0 B 00:00:00 ... Creating domain... | 0 B 00:00:00 Domain is still running. Installation may be in progress.Waiting for the installation to complete.Domain has shutdown. Continuing.Domain creation completed.Restarting guest.root@trana:~#
There are some problems that I have noticed that would be nice to fix, but are easy to work around. The first is that at the end of the installation of Trisquel 9 and Trisquel 10, the VM hangs after displaying Sent SIGKILL to all processes followed by Requesting system reboot. I kill the VM manually using virsh destroy foo and start it up again using virsh start foo. For production use I expect to be running Trisquel 11, where the problem doesn’t happen, so this does not bother me enough to debug further. The remaining issue that once booted, a Trisquel 11 VM has lost its DNS nameserver configuration, presumably due to poor integration with systemd-resolved. Both Trisquel 9 and Trisquel 10 uses systemd-resolved where DNS works after first boot, so this appears to be a Trisquel 11 bug. You can work around it with rm -f /etc/resolv.conf && echo 'nameserver A.B.C.D' > /etc/resolv.conf or drink the systemd Kool-Aid. If you want to clean up and re-start the process, here is how you wipe out what you did. After this, you may run the sed, ./gen-preseed-iso and virt-install commands again. Remember, use virsh shutdown foo to gracefully shutdown a VM.
root@trana:~# virsh destroy fooDomain 'foo' destroyedroot@trana:~# virsh undefine foo --remove-all-storageDomain 'foo' has been undefinedVolume 'vda'(/root/vm-foo.img) removed.root@trana:~# rm vm-foo.*root@trana:~#
Happy hacking on your virtal machines!