Avoiding The Needless Multiplication Of Forms

System Deployment

Dr Andrew Moss


There is not much interesting to say about the debian installer any more: what used to be complex has become quite simple. Hit the appropriate buttons for localisation, choose a standard task selection and drive layout then wait around for the system to build.
The first thing that we want to do is to automate this process. The debian installer was written with scripting support in mind. Preseeding is a technique for supplying the answers to each installer prompt in a simple text format. If the installer can see the preseed file then it can execute the entire installation and reboot into the new system without any user input.
What do we need to make this work?
  1. A preseed file to configure the installer.
  2. A method of getting the preseed file into the installer image.
Let's see how to solve the second problem first.

Remastering the installer image to include a preseed file.

This is easy to do in a running linux system. It seems to be next to impossible in a modern OSX version (the newest debian installers use UDF rather than ISO and the specific UDF used does not mount under OSX).
remaster.iso: copy cp preseed.cfg copy/ cp ~/.ssh/id_dsa.pub copy/ genisoimage -b isolinux/isolinux.bin -c isolinux/boot.cat -o remaster.iso -J -R -no-emul-boot -boot-load-size 4 -boot-info-table copy/ copy: debian-8.2.0-amd64-netinst.iso mkdir copy 2>/dev/null || true mkdir loop 2>/dev/null || true mount debian-8.2.0-amd64-netinst.iso loop/ rsync -rav loop/ copy umount loop rm -rf loop debian-8.2.0-amd64-netinst.iso: curl -LO http://cdimage.debian.org/debian-cd/8.2.0/amd64/iso-cd/debian-8.2.0-amd64-netinst.iso
A makefile may not be the best way to do this, but it is fast and cheap. We don't want to grab the original installer each time - we want to cache it to save bandwidth. We don't want to unpack the image again unless we have to. A makefile is very natural way to express building from caches.
Unfortunately there is something funky here - it could be that using the directory copy as a target is causing problems with time-stamping for the make logic. Either way I've had to kill the copy directory a few times to get changes to propagate. This mostly works.
Using a file called preseed.cfg in the root directory of the installer image is supported directly by the debian installer. The ssh key file is not used directly by the installer but it is explained later in this post.

Writing a preseed file

Writing a preseed file is like any other configuration - start with a working example (in this case the jessie example file). Run it to check it works. Tweak it until it does the right thing. In this case the right thing is a desktop install targeted at a virtualbox VM for development work. There is an extra unused partition on the harddrive - this is for storing the .ISO on directly so we can do re-installs direct from the harddrive without needing access to the virtual cdrom.
d-i debian-installer/language string en d-i debian-installer/country string SE d-i debian-installer/locale string en_SE.UTF-8 d-i keyboard-configuration/xkb-keymap select sweden d-i netcfg/choose_interface select auto d-i netcfg/get_hostname string unassigned-hostname d-i netcfg/get_domain string unassigned-domain d-i netcfg/hostname string psuedo2 d-i netcfg/wireless_wep string d-i mirror/protocol string ftp d-i mirror/country string se d-i mirror/ftp/hostname string ftp.se.debian.org d-i mirror/ftp/directory string /debian d-i passwd/root-login boolean false d-i passwd/user-fullname string Amoss d-i passwd/username string amoss d-i passwd/user-password password abc d-i passwd/user-password-again password abc d-i clock-setup/utc boolean true d-i time/zone string Europe/Stockholm d-i clock-setup/ntp boolean true d-i partman-auto/disk string /dev/sda d-i partman-auto/method string regular d-i partman-auto/expert_recipe string \ remasterPart :: \ 1000 1000 1000 ext2 \ $primary{ } $bootable{ } \ method{ keep } \ . \ 1000 1000 1000 linux-swap \ $primary{ } \ method{ swap } format{ } \ . \ 15000 15000 150000 ext3 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext3 } \ mountpoint{ / } \ . d-i partman/choose_recipe select remasterPart d-i partman-partitioning/confirm_write_new_label boolean true d-i partman/choose_partition select finish d-i partman/confirm boolean true d-i partman/confirm_nooverwrite boolean true d-i partman-basicmethods/method_only boolean false tasksel tasksel/first multiselect minimal d-i pkgsel/include string openssh-server xorg e17 xdm terminology popularity-contest popularity-contest/participate boolean false d-i grub-installer/only_debian boolean true d-i grub-installer/with_other_os boolean true di finish-install/reboot_in_progress note d-i preseed/late_command string \ mkdir /target/home/amoss/.ssh ; \ in-target chown amoss:amoss /home/amoss/.ssh ; \ chmod 700 /target/home/amoss/.ssh ; \ cp /cdrom/id_dsa.pub /target/home/amoss/.ssh/authorized_keys ; \ in-target chown amoss:amoss /home/main/.ssh/authorized_keys ; \ chmod 600 /target/home/amoss/.ssh/authorized_keys

Some words about security

Don't really set your password to abc - even when you are just testing this in a machine sitting behind NAT. It just sets you up for fail when you change the network configuration in virtualbox and forget to update the password. The idea is to set a randomised password for the only user account and disable root access.
The late_command script at the end is very specific to my configuration, but it should be adaptable for anyone. I have one ssh key that I use to log into desktop machines. It has a strong passphrase on it as sometimes I store the private key in places that I do not entirely trust (and thus it needs to be strong enough to survive brute-force attacks for the expected lifetime of the key).
I place the public-half of this key into the disk image inside the makefile. The installer then creates a .ssh directory for the single user and sets the public key as an authorised key for login to the new desktop. I then have a single way into the newly installed image - ssh to the virtualbox bridge IP address using the key. Once I have securely logged in then I can set the password to something memorable - this avoids storing the password in the .ISO image that is being built. Even if we never release the .ISO into the wild storing a plaintext password in it of any value is simply a bad idea.