It's a common scenario: you've been given the task of rolling out dozens of Linux boxes, but you'd rather not have to go through the pain of installing every one them manually. Automated installations with Redhat are well documented, but what about Ubuntu?
Ubuntu inherits Debian's ability to preseed the answers to its installation questions, but the instructions for this are rather haphazard and seems to quickly become out of date as newer versions are released.
In this article, we'll look at setting up automated installations for Ubuntu Jaunty, entirely from the network. We'll start out with one assumption however - that the workstation being used has the ability to perform network boots using PXE. Most modern workstations and servers have this feature, which is usually enabled via the BIOS. If your computer doesn't have this, then you will most likely need to initial your boots from a CDROM, floppy disk drive or USB key.
The installation process
The process used for performing a networked installation is as follows:
The workstation sends out a DHCP request for its IP address and boot location
The DHCP server provides the address and the hostname of the tftp server and the path to the boot code (pxelinux.0)
The workstation downloads pxelinux.0 via tftp and then boots this
pxelinux then retrieves its configuration file from the tftp server
pxelinux now retrieves a kernel, initrd and preseed file, and then boots the installer.
The installer reads the settings given in the preseed file and installs the system
Setting up a TFTP server
The TFTP server allows the workstations to download the pxelinux bootloader, and the installer Linux kernel and initrd file. I'm using tftpd-hpa, which has some specific requirements for PXE boots - the standard netkit tftpd will not work.
tftp-hpa serves up files from the /tftpboot directory on my server. Under this directory, I have the following files:
/tftpboot/pxelinux.0 - the pxelinux bootloader. This can be obtained from the Ubuntu archive, here.
/tftpboot/pxelinux.cfg/ - a directory that contains pxelinux configuration files
/tftpboot/ubuntu/jaunty/i386/linux - the installer kernel, available
/tftpboot/ubuntu/jaunty/i386/initrd.gz - the installer initrd, which can be retrieved from the link above.
This script will set up the /tftpboot directory for you. Run it as root - but read through it to make sure you know what it does, first.
Setting up a DHCP server
We're going to assume that the computer being installed can load a kernel via PXE - most modern computers now have this capability.
First, you will need a DHCP server. My network uses a Linksys WRT-54GS running OpenWRT, for DHCP I'm using dnsmasq. To configure dnsmasq so that it tells DHCP clients where to download the pxelinux bootloader, I added this line to my /etc/dnsmasq.conf file:
Once your workstation has been assigned an IP address by DHCP and told where to fetch the pxelinux.0 file from, it will download this file and then execute it. The first thing that pxelinux will do is attempt to fetch a configuration file from the tftpserver. It first attempts to download a file named with the workstation's ethernet card MAC address, from the /tftpboot/pxelinux.cfg/ directory. So if our workstation's ethernet MAC address is 00:11:22:33:44:55, then it will look for the file "/tftpboot/pxelinux.cfg/00-11-22-33-44-55". If it can't find that, it will look for a file named with the workstation's IP address in hexadecimal (eg, for 10.0.0.230, it will look for /tftpboot/pxelinux.cfg/0A0000D6), and then files with the most significant digits (eg, 0A0000D, 0A0000, 0A000, 0A00, 0A0, 0A, 0) ... and finally if it can't find any of those, it will look for a file named 'default'.
We'll just name the file 'default' for the moment. Create a file named /tftpboot/pxelinux.cfg/default with the following contents:
The above file creates two boot options for the pxelinux loader - the first one, named 'harddisk' will boot the workstation from its built-in disk drive. This is the default option and it will automatically run this if the user doesn't press any key within five minutes at boot time (this timeout is configured by the "timeout 300" line - ie, 300 seconds). The second option "install" is the auto-installation option.
The "kernel" directive tells the bootloader to load the kernel located at /tftpboot/ubuntu/jaunty/i386/linux, and within the append directive we've set a number of variables:
initrd - load the initrd from /tftpboot/ubuntu/jaunty/i386/initrd.gz
locale - set the locale to "en_AU" (Australian English) - this suppresses a question asked by the Ubuntu installer at a later stage
console-setup/layoutcode=us - sets the keyboard to US (again, suppresses a question later on)
preseed/url - fetch our preseed file from http://10.0.0.103/ubuntu/jaunty/preseed.txt
netcfg/get_hostname - we set this to blank, again to suppress a question asked by the installer. The system will learn its hostname from DHCP
Creating a preseed file
A preseed file contains all the answers to the questions that the Ubuntu installer will ask during a normal installation sequence. In the above pxelinux configuration file, we've told the installer to load the preseed file from a webserver on our locale network. So now, we'll create the following file, which you can download here.
Put the above text into a file called preseed.txt somewhere in the directory tree on a webserver on your local network, and make sure you adjust the preseed/url directive in the pxelinux configuration file to match the file's url.
At this point, we have everything in place for the automatic installation to proceed. If you now boot your workstation, force it to perform a PXE boot (you may need to adjust the bios settings to enable this), it will then obtain an IP address from your DHCP server, load the pxelinux bootloader and display a "boot:" prompt. At the prompt, type "install" and press Enter. Your system will then automatically install a minimal version of Ubuntu, from the Ubuntu archive, without any X or Gnome packages - just the bare essentials.
Preseed file description
To finish off, I'll give a run through of the above preseed configuration file, explaining each of the directives.
The above lines set the language of the installation (in this case, Australian English - amongst the many other options, there are also en_CA, en_IE, en_UK and en_US), tell the installer not to request automatic keyboard detection, force the keyboard to be a US variety and then set up the clock - the server will use UTC for its hardware clock, it will have a local timezone of Australia/Melbourne and the server will syncronise its clock with an ntp server.
d-i netcfg/choose_interface select auto tells the installer to automatically choose which ethernet interface to use.
The next three lines exist purely to suppress some annoying questions that the installer would otherwise ask, about the host and domain names (which will be assigned from DHCP) and the wireless wep key (which we're not using):
The first line tells the installer that we want to set the hostname manually, the second and third lines set the hostname and path respectively, and the fourth line we tell the installer that we don't wish to use a proxy (if you do want to use one, then give the url of the proxy here, for example http://proxy.server.name:3128/)
For simplicity, I've chosen an automatic partitioning scheme, using LVM - this will use the entire disk, allocate a small partition to /boot and then use LVM across the remainder of the disk, with one large root logical volume within it.
Now to set up the root account. I loathe Ubuntu's default setup that doesn't have a password assigned to the root account, so I've set it up with a password, here:
The encrypted password, in this case, is simply "test123".
There's two ways of choosing which packages should be installed - the first is to select groups of packages - "tasks", using the tasksel directive. The second is using pkgsel to select individual packages:
Here, I've chosen the "standard" task (which is very basic Ubuntu installation), and I've also opted to install the openssh-server package and build-essential (which will pull in gcc and libc6 header files).
The last thing we need to do is install a bootloader - we'll use grub:
You'll note that the configuration file has two xserver-xorg directives at the end; these are there simply to suppress two more questions from the installer that would halt the automated installation process.
That's all there is to it. You should now be able to take the above preseed configuration file and expand it to install an entire Ubuntu desktop, or perhaps even use it in a disaster recovery plan to quickly rebuild dead servers.