agile sysadmin

by Ferenc Erki

Unattended Ubuntu install in a VM

Edit: you may want to check out my updated post in this topic.

In one of my projects I needed to quickly install and/or reproduce virtual Ubuntu servers using QEMU+KVM. It’s nothing difficult but I decided to record the required steps here so I don’t have to remember it all the time. The overall process is the following:

  • download an installation image, mount it and make a writable copy
  • modify/replace isolinux.cfg and preseed files
  • recreate ISO and test by booting from it

Get an Ubuntu installation image

I’m using the latest 64-bit LTS server ISO which is marked 12.04.2 at the moment of writing this. I also recommend downloading it via torrent then keep it seeding.

Mount ISO and copy files

Mount the downloaded image then copy the contents to a directory where you can edit the files since the mounted filesystem will be read-only.

mount -o loop /path/to/image /mount/here
rsync -av /mount/here/ /copy/here
chmod -R u+w /copy/here/isolinux
chmod -R u+w /copy/here/preseed

Modify files

Adjust isolinux.cfg and preseed files to your needs. The options needed before the installer mounts the installation media should go into isolinux.cfg as part of the append statement. Every other preconfiguration for the installer could be set in the preseed file (list of preseed options). All path info in the below examples should be seen as if the root directory was the ISO image’s root.

isolinux.cfg

As I intend to use the new image for unattended installation I replaced the original file with the following:

/isolinux/isolinux.cfg

prompt 0
default install
label install
    menu label ^Install Ubuntu
    kernel /install/vmlinuz
    append file=/cdrom/preseed/ubuntu-server-minimalvm.seed locale=en_GB.UTF-8 console-setup/ask_detect=false keyboard-configuration/layoutcode=hu vga=788 initrd=/install/initrd.gz quiet --
  • prompt 0: this can spare time on boot by not waiting for any user input
  • append options:
    • file: which preseed file should be used during the installation
    • language, country and locale can be set separately but usually it’s enough to set the locale (language=en country=GB locale=en_GB.UTF-8 is equivalent to locale=en_GB.UTF-8 however language=en country=HU locale=en_GB.UTF-8 combination won’t work for some reason..)
    • console-setup/ask_detect=false: don’t try to autodetect keyboard settings
    • keyboard-configuration/layoutcode=hu: set the keyboard layout to Hungarian
    • everything else (vga, initrd, quiet) is kept from the default file

The installer mounts the installation media at this point so it could load the specified preseed file and use that from here on.

Preseed file

In order to don’t stop to wait for any user input I needed to specify the following minimal set of preconfiguration options: hostname, initial user’s full name, username and MD5 hashed password, home directory encryption, timezone, partition setup, mirror config, update policy, additional packages to be insalled, GRUB installation, and how to finish the installation.

I just prepended these lines to the existing ubuntu-server-minimalvm.seed file:

/preseed/ubuntu-server-minimalvm.seed

# 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/http/proxy string
# 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

Edit: install acpid by default as it is needed for proper VM shutdown. The initial username/password is ubuntu/ubuntu in this example.

recreate ISO

mkisofs -r -V "auto-ubuntu-minimalvm" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o /path/to/new/iso /copy/here

boot

  • createqemu image
qemu-img create -f qcow2 ubuntu-server-12.04.2-amd64-minimalvm.img 2G
  • boot from modified iso
qemu-kvm -cpu host -drive file=ubuntu-server-12.04.2-amd64-minimalvm.img,if=virtio -net nic -net user,hostname=ubuntu -m 256M -boot d -cdrom /path/to/new/iso