agile sysadmin

by Ferenc Erki

Simple unattended Ubuntu install in a VM

I wrote the previous post about this topic almost 6 months ago. Recently I had to review the process for a different project and I was curious if I could find an easier way to seed the installer options – preferably without modifying the original ISO file. Although there is more than one way to do it, I hope others would also find this method helpful.

Ingredients:

  • preseed file
  • libvirt
  • virtinst or virt-manager
  • virt-viewer (optional)

Virtinst recently got merged with virt-manager but your distribution may still provide it separately. And that’s right, you don’t even need to download the ISO as virtinst can use an online kernel/initrd pair as install media.

Basically the process is to download an install media from the internet, inject our custom preseed file into initrd, then boot a VM with these.

Let’s see the full command first then some details:

virt-install \
--connect qemu:///system \
--name ubuntu \
--ram 256 \
--disk pool=default,size=5,bus=virtio,sparse=false \
--network network=default,model=virtio \
--location http://hu.archive.ubuntu.com/dists/precise-updates/main/installer-amd64 \
--initrd-inject=/var/lib/libvirt/images/preseed.cfg \
--extra-args="locale=en_GB.UTF-8 console-setup/ask_detect=false keyboard-configuration/layoutcode=hu file=file:/preseed.cfg vga=788 quiet" \
--os-type=linux \
--os-variant=ubuntuprecise \
--virt-type kvm \
--video=vga \
--noreboot

This creates a VM named ubuntu with 256 Mb of RAM and an 5Gb disk in the default storage pool. The virtual disk uses the virtio bus and non-sparse allocation for performance reasons. The VM will also have a virtio network card in the default network. Here comes the interesting part:

  • –location: it tells virtinst to use an online kernel/initrd from the official Ubuntu repos; you may want to adjust the mirror, release name and architecture parts of the link to your needs
  • –initrd-inject: the custom preseed config to be injected into initrd before booting the VM; only preseed.cfg worked for me as the name for this file, and it will be placed under the root directory (an example preseed.cfg is included below)
  • –extra-args: these will be passed to the downladed kernel as command line parameters on boot; it’s generally the answers for the first few installer steps (locale, console, keyboard), the path to the seed file to use, and some convenience options (graphics mode and boot verbosity)

The remaining options are telling virtinst that it will be a Linux VM, specifically an Ubuntu Precise OS using KVM virtualization, simple VGA video card and no reboot is needed after the installer finished. Virt-installer also tries to display the console of the new VM during installation, but virt-viewer is needed for it – if you don’t want to install it you can also open the console via virt-manager or a VNC/SPICE client (depending on what graphics settings your new VM is using).

UPDATE: adamstokes2013 kindly pointed out that --connect qemu:///system is needed for virt-install if you would like to use anything else than usermode networking. You can find out more about this in libvirt FAQ and documentation, along with info on how to set your default hypervisor.

Currently I’m using the following preseed file:

preseed.cfg

# Set hostname
d-i netcfg/get_hostname string ubuntu
# Create new user
d-i passwd/user-fullname string Ubuntu User
d-i passwd/username string ubuntu
d-i passwd/user-password-crypted password $1$1AniiGAw$ZsUcBK840ZrkmoVIvTneP1
# Don't encrypt the home directory
d-i user-setup/encrypt-home boolean false
# Set timezone
d-i time/zone string Europe/Budapest
# Partitioning
d-i partman-auto/disk string /dev/vda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
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
# Mirror
d-i mirror/country string manual
d-i mirror/http/hostname string hu.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string
# Upgrade packages after debootstrap
d-i pkgsel/upgrade select full-upgrade
# Unattended security upgrades
d-i pkgsel/update-policy select unattended-upgrades
# Install OpenSSH server
tasksel tasksel/first multiselect openssh-server
# Install acpid
d-i pkgsel/include string acpid
# Install GRUB2
d-i grub-installer/only_debian boolean true
# Avoid that last message about the install being complete
d-i finish-install/reboot_in_progress note
d-i debian-installer/exit/poweroff boolean true

# Don't install kernel headers.
d-i base-installer/kernel/headers boolean false
# Don't even install the standard task.
tasksel tasksel/skip-tasks string standard
# Only install basic language packs. Let tasksel ask about tasks.
d-i pkgsel/language-pack-patterns string
# No language support packages.
d-i pkgsel/install-language-support boolean false
# Only ask the UTC question if there are other operating systems installed.
d-i clock-setup/utc-auto boolean true
# Verbose output and no boot splash screen.
d-i debian-installer/quiet boolean false
d-i debian-installer/splash boolean false
# Install the debconf oem-config frontend (if in OEM mode).
#d-i oem-config-udeb/frontend string debconf
# Wait for two seconds in grub
d-i grub-installer/timeout string 2
# Add the network and tasks oem-config steps by default.
#oem-config oem-config/steps multiselect language, timezone, keyboard, user, network, tasks
d-i base-installer/kernel/altmeta string lts-raring

The second part of the file is basically the original preseed file from the Ubuntu 12.04.3 ISO and the custom options are placed before them. The initial username/password is ubuntu/ubuntu in this example and acpid is needed for proper VM shutdown.