Debian serial install

Citron, headless, in its final settingA lot has happened since I first installed Debian on an old P-166 laptop back in 2003. Up until this morning, it has been dutifully serving web pages, managing e-mails, sharing drive space and generally providing a slew of other moderately useful services. But even using a php accelerator and running the database server off a different machine, poor old Goyave was still struggling. As of today, Citron manages all the aspects of the site, from the backend MySQL 5 database to the HTTP/PHP server. Citron is a desktop machine, hence notably bulkier than Goyave, and the only way it was going to score a high enough WAF was by losing the screen. Now, I’m all for running a headless server anyway — I’d much rather fiddle with it via SSH from the comfort of my living room / local starbucks / occasional hotel room. But I could already sense that a headless installation procedure would be a challenge.

Why go serial

After a few hours spent googling headless Debian installations, it became clear to me that the best way to go was via a serial console. Luckily, Debian is probably one of the easiest environments to do this in. Before I describe the installation procedure, here are the reasons why I chose this solution over, say, a scripted install:

  • it is not overkill: I only have one machine to set up, so the benefit of reusability of the install settings is lost anyway
  • it is interactive: even though I’ve installed Debian a handful of times on a couple of machines, this was a new version I was about to install, so I figured it would be easiest to do it “live” rather than pre-script it
  • a serial console can always come in handy: if for some reason I can no longer access the box over SSH, I can always plug in my null-modem and get a root console to fix things up. A serial console also gives me access to the boot loader itself, making it super easy to switch kernels or perform rescue operations using a boot disk.

With all this in mind, I went online and purchased a null-modem cable and USB-to-serial adapter (my wintel laptop is of the post-serial era), for under $15 with shipping. I later realized that my picking low-end hardware meant I had no hardware handshaking, causing all kinds of display glitches during operation. It is my belief those can be blamed on some kind of buffer overrun, but the installation was mostly manageable anyway so I didn’t bother looking into it — as I said, the serial console is only useful until the SSH server is up and running, which comes pretty early in the Debian setup, or in case of an emergency.

I also removed the graphics adapter from the system entirely, in order to lower power consumption and heat generation / improve the air flow inside the case. Luckily, this particular machine is able to boot without a keyboard attached, but not all PC systems are.

And now, for my own records and possibly to the benefit of others, here’s a quick description of what I did. It is essentially a 3-step process:

  1. prepare bootable installation media enabling a serial console
  2. install the base system over said console
  3. modify the new system’s boot loader to enable a serial console every time it reboots

Preparing the installation media

Basically, Debian has all the serial drivers already included in the default installation, so it is only a matter of enabling them. Since I was installing from a CD, instead of tweaking the image to load the drivers at boot time I chose to boot from a set of floppies. The idea is to boot the install system from the floppies, which are modified to enable a serial console. Once the install system is started, the rest of the install happens from the CD, and then downloads additional packages directly from a mirror in typical Debian fashion.

The first step is creating the boot floppies. Boot floppy images can be found on any Debian mirror. To perform a minimal CD install, three floppies are needed:

  • boot.img will, as the name implies, initiate the system boot process by loading a small functional kernel
  • root.img will then be used to bring up a usable system
  • finally, cd-drivers.img is needed since the actual installation files will be accessed from the CD directly

The kernel boot floppy needs to be modified to enable a serial console. To do this, change the very first line and final section of the file syslinux.cfg to the following:

first line:
serial 0 9600

final section:
label linux
kernel linux
append vga=normal initrd=initrd.gz ramdisk_size=1842 root=/dev/rd/0 devfs=mount,dall rw console=ttyS0,9600n8 - -

label expert
kernel linux
append DEBCONF_PRIORITY=low vga=normal initrd=initrd.gz ramdisk_size=1842 root=/dev/rd/0 devfs=mount,dall rw console=ttyS0,9600n8 - -

(the part after each append is all on one line, and there is no space between the final two dashes.) The part in bold enables a 9600 bauds, 8-bit no-parity serial line. Thanks to the first line, the system will boot with a serial console enabled right from the start, making it possible to follow the whole boot process and get all the bootloader messages (syslinux is the minimal bootloader used for the install system.) The bottom section changes the default boot parameters for the installer itself so it also uses the serial line.

Modifying the contents of the floppy image from another linux machine can be done just by mounting it locally, e.g.
mount -o loop boot.img /mnt/floppy/
On a DOS/Windows system, a program such as rawwrite (included on the Debian install CD under /tools) can be used, as explained in the Debian Manual in Section 4.3, “Creating Floppies from Disk Images”.

If building the boot floppy on another Debian system, it is even possible to test it beforehand using QEMU, the processor emulator. Just launch it with the following command:
qemu -fda boot.img -nographic -m 32 -no-kqemu
The nographic option instructs qemu to emulate a system with no graphics adapter and a single serial line, effectively what we are trying to achieve. If the system starts booting and the bootloader messages are displayed correctly, the first step is a success (just for kicks, I tried the same qemu command with the original boot.img, and sure enough the emulated serial line was receiving no output.)

Booting the install system and setting up the base system

Now that the boot floppies are ready, the target system can be booted and monitored from a serial terminal. I used my Windows laptop attached via the null-modem cable and usb-to-serial adapter, together with the standard HyperTerminal program shipped with Windows (set to VT220 emulation, 9600 bauds, 8-bit no-parity).

Once the boot prompt is displayed, just pressing <enter> should launch the default, serial-enabled installer. Actually, Debian is supposed to automatically switch to a serial console if no graphics adapter (framebuffer device) can be found, but since some motherboards have display chips embedded anyway manually enabling the serial line in syslinux.cfg may still be needed.

The rest of the installation can be performed as usual. Before rebooting after the base install is finished, the bootloader has to be configured to use the serial line as well. I seem to recall that the install system did this automatically for me, but it’s still better to make sure. Switch to a new console (e.g. alt+f3) and edit /boot/grub/menu.lst to have the following two lines near the top (anywhere before the automagic kernel options and list of kernels):
serial --unit=0 --speed=9600 --word=8 --parity=no --stop=1
terminal serial

Also make sure /etc/inittab enables a serial console to wait for logins, in case accessing the system via a serial terminal is ever needed:
T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
(the first field T0 is an identifier and can be anything, as long as it’s not used already somewhere else in the file.) If a similar line is already included and uncommented, no need to add a second one.

Switch back to the installer (alt+f1) and proceed to reboot the system. At this point the additional packages will be downloaded from a (hopefully) local mirror, and SSH access should be enabled. Time to switch!

Leave a Comment

Verification Image

Please type the word you see in the picture.