Creating a VMWare Player Appliance for Ubuntu Jeos

Ubuntu came out with a version optimized for use in virtual machines. It's called Jeos, for "Just Enough Operating System".

I had hoped to find a prebuilt basic Jeos appliance, but the few at vmware's appliance store were built by people or groups I've never heard of. Strangely, there isn't one to download from Here are the notes I gathered while figuring out exactly how to build one. At the bottom is a fairly explicit recipe that takes about two hours to follow, and yields a compact virtual machine with Jeos installed.

There's a lengthy article at Linux Magazine about how to create Jeos appliances with VMWare Server. It's intimidatingly long, but it is straight from the Jeos team, so read it and pay attention.

There's a script called ubuntu-jeos-builder that might be useful, too, but it won't be released until Hardy is out, so it wasn't mentioned in that article. It will probably make the document you're reading now obsolete when it's released next month, but I couldn't wait.

I noticed that some of the prebuilt Ubuntu appliances ran in vmware player on Linux, but not on Windows! Maybe that was operator error, but it led me to try creating a basic appliance using VMWare Player on Windows.

Here are the roadblocks I ran into, and how I got around them.

1. Jeos Hardy Alpha 3 dies during installation due to bug 183910: pre-pkgsel.d/I: No such file or directory"

Workaround: use Jeos Gutsy until Hardy is fixed

2. Jeos Gutsy and Hardy Alpha 3 die during installation due to bug 163195: E: Couldn't find package lvm2 if LVM selected

Workaround: don't select LVM during initial installation of Jeos

3. Jeos (any version) crashes on boot in VMWare Player with "PANIC: CPU too old for this kernel" due to bug 185205: server kernel requires PAE support not present in VMWare Player

Workaround: in installer, when done, manually install generic kernel before rebooting (see bug report above and recipe below).

4. After reboot, network doesn't work, symptoms match bug 145503: NIC 82545EM not recognized by Ubuntu

Symptom: ifconfig doesn't show eth0. "mii-tool eth0" says ENODEV. ifconfig -a shows no eth0, and an inactive eth1.

Cause: Somehow, eth0 no longer matches the MAC address in /etc/udev/rules.d/70-persistent-net.rules, see bug 145382.

Workaround: edit /etc/udev/rules.d/70-persistent-net.rules to contain the right mac address. (When it happened to me, I just had to remove the old eth0 device and rename eth1 to eth0, as udev seemed to have created an eth1 for the new mac.) To test, do sudo /etc/init.d/udev restart.

This happened to me when I was using the "generated" mac address type in the .vmx file; my example .vmx file now uses a static mac address.

5. The virtual image one gets from installing the Jeos iso is way larger than the iso

Solutions (do all):


So my recipe looks like this when all is said and done:

0. Install VMWare Player

1. Build a working Ubuntu Gutsy Jeos image

Download Gutsy Jeos iso from

Accept the fact that you're going to have to learn how to edit a .vmx file by hand (this is part of the price you pay for doing this with VMWare Player). If you haven't written one before, read any of the many tutorials on how to use VMWare Player to build virtual appliances, e.g.

Using your favorite text editor, create a .vmx file that uses the .iso you downloaded as its cd-rom. There's not much to it. Here's the one I use in the following examples:

Grab an empty disk image. (Use an IDE one, not a SCSI one, since VMWare Player doesn't support SCSI.) I wanted a big disk with room for later, so I used a 20GB image. (Don't worry - as long as you don't use the space, the image is small.)
mv 20GB.vmdk gutsy.vmdk

Boot the virtual machine (e.g. "start gutsy.vmx" or "vmplayer gutsy.vmx") and install Jeos. Don't choose LVM (see roadblock #2 above).

Choose manual partitioning, create a 4GB bootable primary partition #1 at the beginning for /, and a 1GB primary partition #2 at the end for swap. This leaves 15GB of empty space for later expansion.

Before quitting, install the generic kernel (see roadblock #3 above) and clean up unneeded files (see "Cleaning Before Shipping" in the Jeos tutorial). Also, remove the /lib/linux-restricted-modules directory, since none of those modules should be needed in the virtual machine environment. Finally, remove unneeded large files from /var/log and /var/cache. To wit:

Get a shell by pressing alt-F3
chroot /target /bin/bash
mount /dev/scd0 /media/cdrom
aptitude install linux-generic
aptitude remove linux-virtual linux-image-virtual linux-image-2.6.22-14-virtual linux-ubuntu-modules-2.6.22-14-virtual
umount /media/cdrom
apt-get clean
rm -rf /lib/linux-restricted-modules
rm /var/log/dpkg.log
rm /var/cache/apt/*pkgcache.bin
Finally, exit all shells inside the virtual machine and let the installer terminate normally. VMWare will reboot into the (original) virtual machine; go ahead and log in to see if it works. If it does, do 'sudo halt' and move on to the next step.

2. Create defragmented disk image

Now let's produce a pristine filesystem. This will save space and make the machine image compress better.

Start in a new directory, and copy over just the .vmx and .vmdk files you created in the previous step. Make sure you can still boot them in vmware player.

On the host, rename the disk image and create an empty one in its place:

mv gutsy.vmdk gutsy-2.vmdk
mv 20GB.vmdk gutsy.vmdk
Then edit gutsy.vmx and attach gutsy-2.vmdk to the 2nd IDE drive. (If you use my sample .vmx, you just need to uncomment five lines.)

Then reboot from the cd-rom image into rescue mode, telling the rescue environment to use /dev/sdb1 as the root. Then execute a shell in the installer environment, then partition the second disk identically to the first, copy the first partition from the first disk to the second disk, change grub's menu.lst to specify the boot device by device name rather than UUID (or fix the UUID which changed when we copied the root filesystem's contents to a new filesystem), then create a master boot record using grub-install:

fdisk /dev/sdb  (and type 'p' to print the partition table)
fdisk /dev/sda  (and use the n, t, and w commands to recreate the same table)
mkfs.ext3 /dev/sda1
mount /dev/sda1 /mnt
cd /target
ls | egrep -v 'proc|sys|lost.found' > /files.txt
cp -a `cat /files.txt` /mnt
mkdir /mnt/proc /mnt/sys
chroot /mnt /bin/bash
vi /boot/grub/menu.lst    (and replace UUID=alkdsjflskjfd with /dev/sda1)
grub-install /dev/sda
umount /mnt
tell rescue disk to reboot system
When the copy is done, df inside the virtual machine should show both /target and /mnt using about 400MB. Outside the virtual machine, du should show gutsy-2.vmdk using about 664MB, but gutsy.vmdk, the one that contains the clean copy, should be a relatively svelte 341MB. (It probably helps that the new swap partition has never been written to.)

Make sure you can still boot the virtual machine.

Verify that the network device exists. If 'ifconfig' only shows lo, but 'ifconfig -a' shows lo and eth1, you're probably suffering from roadblock #4 above. To fix, edit /etc/udev/rules.d/70-persistent-net.rules to remove the old eth0 device, and rename the eth1 to be eth0. Then do 'sudo /etc/init.d/udev restart' and verify that the network is happy.

3. Compress the disk image

Finally, remove the reference to the .iso and the second IDE drive from the .vmx file. Then use a good compression tool to compress the disk image, e.g.
sudo apt-get install p7zip
7zr a ubuntu-7.10-jeos-vmware.7z gutsy.vmx gutsy.vmdk
This produces the archive ubuntu-7.10-jeos-vmware.7z, size 87 megabytes. Sweet! (For the record, p7zip had about 15% better compression than rzip -9. lrzip had almost exactly the same compression as p7zip, but was slower.)

Finally, verify that you can decompress (with p7zip -d) and boot the image. If it works, celebrate!

Interesting links

Original URL:
Copyright 2008, Dan Kegel
Back to