This tutorial is using a custom ISO of Ubuntu downloaded from here.

The Challenges

We have Apple XServe 3.1 servers here. They are equipped with a JBOD, Promise VTrek E610F. It connected via Fibre Channel. We have configured them for RAID6 28 TB.

The best part of the challenge is that XServe 3.1 use EFI. Some people would suggested us to use rEFIt and chainload it to GRUB2. We could use “bless” command from OSX.

The problem is, we have stripped the original 150 GB harddrive. The reason was because it was only had one drive without RAID. Data integrity was in question so we have to use only the JBOD.

Another problem is because PC BIOS couldn’t handle more than 2 TB. We just have to use GPT. Besides, GPT is the part of EFI.

So, I took the challenge to not use the OSX but to install directly from GNU/Linux installer from EFI to a GPT partition.

The Preparation

I got this challenge from my friend because he gave up on installing the XServe. From his previous attempt, I got 64 Bit Mac (AMD64) alternate install CD downloaded from Ubuntu. I don’t know where he got the ISO. Please download here. Not bad, I can use it to debootstrap the partitions.

To start, boot the CD and choose Expert Install. The Expert Install mode would let us select few things manually. Here’s the things that I’ve selected:

  1. Language: Indonesia – Bahasa Indonesia
  2. Keyboard: USA :: Macintosh :: No Compose Key
  3. Installer component from CD: [*] choose-mirror: To select mirror [*] network-console: To enable SSH server, I can configure from remote. [*] parted-udeb: To manually create partition.
  4. Configure the network.

If you don’t want to have remote install, you could disable network-console. In my case, I don’t like to be in the server room and to move XServe with its JBOD is daunting. I would like to configure everything from my nice warm room office.

After configuring the network jump to the run shell option. Or, after we have configure SSH credential, we could SSH to the machine with username “installer”. And choose to start a shell. Either way, we would be presented with a little console program: BusyBox. It isn’t feature-rich like BASH, but it serves right with compact size.

On The Shell

First, we partition our drive. We are using parted instead of fdisk because the later doesn’t support GPT partition type. The Apple’s EFI specification needs a FAT32 partition to load the EFI binary. That partition should be at the range of the first 2 TB disk. It doesn’t have to big, just few megs actually would do. So, here’s my partition:

  1. 20 MB FAT32 partition at the beginning with BOOT flag on.
  2. 20 GB partition for our GNU/Linux partition.

We have lots of RAMs, so we disable swap partition. But, yours might differ. From my research, the semantic web/4th paradigm world, it seems people prefer XFS because it is optimized for big data. So, from the beginning I choose XFS. Again, yours might differ. So, here’s the two commands:

# parted -s /dev/sda mklabel gpt mkpart EFI fat32 0% 20MB toggle 1 boot
# parted -s /dev/sda mkpart primary reiserfs 20MB 20GB
# mkfs.xfs /dev/sda2
# mount /dev/sda2 /mnt -t xfs

I have difficulty to format the FAT32 partition, I think the Installer CD is dying. So, I decided to format it later. Now, let’s install it via bootstrap it and copy the files that were configured earlier from the installer:

# debootstrap squeeze /mnt
# cp /etc/{fstab,hostname,hosts,resolv.conf} /mnt/etc
# cp /etc/network/interfaces /mnt/etc/network/interfaces

BusyBox can’t do the array like the above. You have to parse it one by one (copy fstab, then hostname, and so on). I just put that way for convenience. Next, we mount the important filesystems and chroot to our new system. I explicitly use BASH instead of DASH, the default shell in Ubuntu.

# mount /dev /mnt/dev -o bind
# mount none /mnt/proc -t proc
# mount none /mnt/sys -t sysfs
# chroot /mnt /bin/bash

On Chrooted Shell: The Basic Packages

First thing to do is to add other repositories to “/etc/apt/sources.list”.

# cat > /etc/apt/sources.list << EOF
deb squeeze main contrib non-free
deb-src squeeze main contrib non-free 

deb squeeze/updates main contrib non-free
deb-src squeeze/updates main contrib non-free 

deb squeeze-backports main contrib non-free
deb-src squeeze-backports main contrib non-free

I put away the “>”  so you could just copy and paste above. Use a mirror near you. KAMBING is the nearest for me. Then, update and upgrade:

# apt-get update
# apt-get upgrade

Install essential applications. I’m using XFS, that’s why I install xfsprogs. Adjust it with your own filesystem tools. The dosfstools are for FAT32 and so on. I too put SSH server there.

# apt-get install xfsprogs dosfstools parted bash-completion less eject ssh

I’m use ViM. So, optionally, I do this:

# apt-get install vim
# update-alternatives --config editor
There are 3 choices for the alternative editor (providing /usr/bin/editor).

  Selection    Path                Priority   Status
* 0            /bin/nano            40        auto mode
  1            /bin/nano            40        manual mode
  2            /usr/bin/vim.basic   30        manual mode
  3            /usr/bin/vim.tiny    10        manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in manual mode.

Next, we are going to change the preferences of our system.

On Chrooted Shell: Personalizing System

Let’s add a user with admin privileges. The default system, sudo is not installed. So, we must get it first

# apt-get install sudo
# adduser user
# adduser user sudo

Install and configure our language. Mine is “id_ID.UTF-8”. Also, configure clock (Timezone). Mine is “Asia/Jakarta”.

# apt-get install locales && dpkg-reconfigure locales
# dpkg-reconfigure tzdata

Time is crucial for server. Install NTP server to have our server clock right. Don’t forget to edit the editor to get our nearest NTP server.

# apt-get install ntp
# $EDITOR /etc/ntp.conf
# /etc/init.d/ntp restart

We can check the avaibility of the NTP servers.

# ntpq -p

Last thing, let’s install our Linux kernel.

# apt-get install linux-image-2.6-amd64 firmware-linux-nonfree

The next one is the most challenging one: making our server boot from EFI on GPT partition.

Building GRUB2 from Unstable

I have many failed attempts using the default grub-efi 1.98 from Squeeze. As I realize, the Natty installer is using 1.99 version of GRUB2. I decided to go to that route.

GRUB2 1.99 is available at unstable and must get backported to Squeeze. We must compile it ourselves. So, here’s how to.

Get all the requirements for GRUB2 in Squeeze. There is another optional package we need: libfuse-dev for building grub-mount. It can be skipped, but it’s not that bad to add few bytes on that functionality. We need also autogen because the GRUB2 source is taken from Bazaar.

# apt-get build-dep grub2
# apt-get install autogen libfuse-dev

Next, add Debian source repository for unstable/SID. Don’t add the binary, it will upgrade your system to unstable/SID.

# echo "deb-src unstable main contrib non-free" > /etc/apt/sources.list.d/unstable.list
# apt-get update

Get the source.

# apt-get source grub2
# cd grub2-1.99/

We could build the package manually, but I prefer the Debian way. Fortunately, the showstopper of doing the Debian way is only the GCC requirement. Unstable/SID  is using gcc-4.5 while Squeeze using gcc-4.4. The solution is simple, find all the occurrences and change all of them.

# grep -ri "gcc-4.5" debian/*
debian/changelog:    - Build with gcc-4.5 on ppc64.
debian/control: gcc-4.5-multilib [i386 kopensolaris-i386 any-amd64 any-ppc64 any-sparc],
debian/control: gcc-4.5,
debian/rules:CC := gcc-4.5

There are three files that affected. You could use sed/awk, or using your favorite editor to change all of the gcc-4.5 to gcc-4.4. I’m using ViM with regex. Of course, it is advised that we change the version also. I’m not doing it because we are not trying to publish it. This build has bug, yet sufficient for our need. 😛

Okay, the next thing is to build all of the packages.

# dpkg-buildpackage -b -uc -d

All of the Debian packages are built on the top of our source directory. Let’s install all of the EFI versions. But wait, before you could install, the package needs to install efibootmgr, an application for setting the default drive to boot on UEFI (Universal EFI) compatible board. Unfortunately, XServe is using Apple’s own EFI implementation, so the application is useless. We must use bless, an application on OSX for that purpose. Oh, btw, install the ucf and os-probes.

# apt-get install efibootmgr ucf os-probes
# cd ..  && dpkg -i grub-common_1.99-11_amd64.deb \
    grub2-common_1.99-11_amd64.deb grub-efi-amd64*  \

Now, we are ready to get into the show.

Installing GRUB2 EFI

Before we take further, I want to say something. I am gratefully to the developer of the grub-install for making an undocumented parameter  –debug. That parameter saves me and made me to see what’s going on.

Okay, now we need to prepare our partition for EFI. It should be FAT32 and mounted at “/boot/efi”. Let’s create one.

# mkfs.vfat /dev/sda1
# mkdir -p /boot/efi && mount /dev/sda1 /boot/efi

Next, we run the GRUB installer.

# grub-install --bootloader-id=BOOT --removable --debug

The parameter “–bootloader-id=BOOT –removable” is what I found out after I analyze “/usr/sbin/grub-install” script. Basically, I want  GRUB2 installs its EFI file at “(hd0,gpt1)/EFI/BOOT/BOOTX64.EFI” (in its FAT32 partition). Some UEFI board may have other vendor such as Ubuntu, GRUB, etc. But, XServe doesn’t understand other vendor, yet. We could only use the default prefix where XServe’s EFI would search for EFI binary.

Don’t restart yet, because next is the most important one.


You know why I used the “–debug”? It was because I kept on going to the GRUB Rescue mode with error message telling that GRUB could not found the proper disk. In the GRUB Rescue, I’ve found out that the prefix was wrong. The prefix was pointing to ” ((null),gpt2)/boot/grub”. Wew, that was wrong.

After I’ve found the problem, it seems that the “/usr/sbin/grub-install” didn’t generate the right prefix. From the debug, I’ve found the culprit:

... (OMITTED by me)
+ /usr/bin/grub-mkimage -d /usr/lib/grub/x86_64-efi -O x86_64-efi --output=/boot/grub/core.efi --prefix=(,gpt2)/boot/grub xfs part_gpt
... (OMITTED by me)

I couldn’t found out what went wrong. The solution is to generate the EFI binary manually.

# /usr/bin/grub-mkimage -d /usr/lib/grub/x86_64-efi -O x86_64-efi --output=/boot/grub/core.efi --prefix="(hd0,gpt2)"/boot/grub xfs part_gpt
# cp /boot/grub/core.efi /boot/efi/EFI/BOOT/BOOTX64.EFI

These two lines were the thing that the “/usr/sbin/grub-install” used incorrectly.

Configuring GRUB2 Settings

We need to add lines so that the screen won’t messed up. We disable the modeset and keep the screen resolution. Use:

# dpkg-reconfigure grub-efi-amd64

and add  “nomodeset  gfxpayload=keep” to the “Linux command line:” option. Or edit “/etc/default/grub and put the string to GRUB_CMDLINE_LINUX.


After we install, we can do two things. First, we call update-grub to detect all of available kernels. And, we could add “/boot/efi” to “/etc/fstab”.

# update-grub
# echo "/dev/sda1       /boot/efi       vfat    defaults        0       0" >> /etc/fstab

Last step is reboot and having your new system shines.



As Isaac Alcocer pointed out on his comment, using the LTS Ubuntu 12.04 might be the easiest way. With it, you would only have to edit the GRUB.