Update: Curated Ubuntu Images now available on Google Cloud Platform

Ubuntu is a popular choice of Linux distribution among developers and DevOps people, especially due to long-term-support (LTS) and package availability.

At the present, Google Compute Engine doesn't have any of Ubuntu images, which gives us the joy of cooking the image by ourselves - thanks to Custom Kernels functionality of GCE. Please note this post represents just the general idea of how to make your own Ubuntu image on GCE, your actual deployment may vary.

If this is too technical for you, please feel free to contact cloud@doit-intl.com and we’ll share the ready-to-go image of basic Ubuntu 14.04 LTS with you.

To build the image,  I’ve used the following:

  • Ubuntu 14.04 Desktop (will host our virtual machine then-to-become GCE image)

  • Qemu emulator/virtualizer

  • Google Cloud SDK

We will begin with the infrastructure set-up. Start the Ubuntu Desktop (of course you can use any other dist).

Step 1 - Install Qemu and Ubuntu Virtual Machine

There are several options to get it done, I’ll just pull it from the repository:

$ sudo apt-get install qemu -y

For the sake of order, create a folder which will contain the virtual machine and other stuff:

$ mkdir VM
$ mkdir VM/Disks/SourceISO
$ mkdir VM/BackupImage

Get your Ubuntu 14.04 LTS ISO from here, and download it to the SourceISO folder

$ wget -P VM/SourceISO http://releases.ubuntu.com/14.04/ubuntu-14.04-server-amd64.iso

Create a disk for the virtual machine:

$ qemu-img create VM/Disks/ubuntu.raw 10g

Let’s start the virtual machine and boot it from the ISO:

$ qemu-system-x86_64 --enable-kvm -smp 1 -m 512m -net nic,model=virtio -net user,hostfwd=tcp::2222-:22 -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd,physical_block_size=4096 -drive if=none,id=hd,file=VM/Disks/ubuntu.raw,cache=none -cdrom VM/SourceISO/ubuntu-14.04-server-amd64.iso

This will invoke an x64 instance with the required hardware and boot into the setup. Go ahead and install the machine, customize it any way you want, as long as you do these:

  • There should be only one partition (manual setup)

  • Don’t encrypt home dir

  • Select UTC time zone

  • Install OpenSSH server

Your qemu instance of Ubuntu will finish installation and reboot. You’re half-way there! :)

Step 2 - Update the Image & Install Packaging tools

Now, let’s go ahead and set-up the Ubuntu image itself. You can work on the qemu console window if you wish, the drawback is the lack of copy/paste, therefore I would recommend the SSH session.

Connect to the instance with the user you’d created during the installation:

$ ssh -p 2222 user@

Let’s make sure the virtual machine is up to date:

$ sudo su -l
$ apt-get update
$ apt-get upgrade -u -y

At this point, I would recommend to take a backup copy of your image (it will also be useful for future images creation, you’ll have a clean up to date installation to manipulate at the future).

Shutdown the machine and just make a copy of the ubuntu.raw file to a different location, for example:

$ cp VM/Disks/ubuntu.raw mkdir VM/BackupImage/ubuntu_clean.raw

Once done, turn-on the instance again.

To package the virtual machine as GCE’s image, we will need to install the latest Google packages from git (you’ll need to have root privileges for this)

$ apt-get install kpartx ethtool

$ wget https://github.com/GoogleCloudPlatform/compute-image-packages/releases/download/1.1.2/python-gcimagebundle_1.1.2-1_all.deb https://github.com/GoogleCloudPlatform/compute-image-packages/releases/download/1.1.2/google-compute-daemon_1.1.2-1_all.deb https://github.com/GoogleCloudPlatform/compute-image-packages/releases/download/1.1.2/google-startup-scripts_1.1.2-1_all.deb

$ dpkg -i google-compute-daemon_1.1.2-1_all.deb google-startup-scripts_1.1.2-1_all.deb python-gcimagebundle_1.1.2-1_all.deb

Step 3 - Image Configuration & Upload to GCE

If you didn’t set the instance as UTC at setup, do it now:

$ ln -sf /usr/share/zoneinfo/UTC /etc/localtime
$ apt-get install ntp -y

You’ll need to comment-out Ubuntu NTP server and add GCEs - server metadata.google.internal

$ sed -i 's/^server ntp.ubuntu.com/# server ntp.ubuntu.com\nserver metadata.google.internal/' /etc/ntp.conf

Then, remove the /etc/hosts file and add the Google’s metadata server IP address

$ rm /etc/hostname
$ echo " metadata.google.internal metadata" >> /etc/hosts

$ ln -s /usr/share/google/set-hostname /etc/dhcp/dhclient-exit-hooks.d/

Create /etc/init/ttyS0 file with the following content:

$ vim /etc/init/ttyS0.conf
# ttyS0 - getty
start on stopped rc or RUNLEVEL=[2345]
stop on runlevel [!2345]
exec /sbin/getty -L 115200 ttyS0 vt102

Edit the /etc/default/grub file to include these settings:

GRUB_CMDLINE_LINUX="console=ttyS0,115200n8 ignore_loglevel"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

$ sed -i 's/^GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="console=ttyS0,115200n8 ignore_loglevel"\nGRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"/' /etc/default/grub

$ sed -i 's/^#GRUB_TERMINAL=console/GRUB_TERMINAL=console/' /etc/default/grub

And update grub:

$ update-grub2

For FIPS mode (optional) execute:

$ mkdir /etc/gcrypt && echo "1" >> /etc/gcrypt/fips_enabled

As with all security and installation preferences, it comes down to what you need and how you like to get it. I would recommend going over Google’s recommendations and see what fits your need. In this manual,  I’ve kept it very basic.

Recommended that those will be Disabled - root ssh login, password authentication, host based authentication - at /etc/ssh/sshd_config

Add GOOGLE to the sshd_not_to_be_run

$ echo "GOOGLE" > /etc/ssh/sshd_not_to_be_run

Remove old host SSH keys.

Important - by doing this you won't be able to SSH to the machine, only console access until you’ll upload the image to GCE, so please be careful :)

$ rm /etc/ssh/ssh_host_*

Create /etc/sysctl.conf.d/12-gce-recommended.conf with the following content:

$ vim/etc/sysctl.d/12-gce-recommended.conf

# provides protection from ToCToU races
# provides protection from ToCToU races
# makes locating kernel addresses more difficult
# set ptrace protections
# set perf only available to root
# disable ipv6

Great! Now, we just need to prepare the bundle of image and upload it to GCE. First check if /usr/lib/python2.7/dist-packages/gcimagebundlelib/manifest.py require patching by this link.

You'll need gsutil and gcutil in the instance. To install the GCE SDK:

$ curl https://sdk.cloud.google.com | bash

To prepare the image bundle:

$ gcimagebundle -d /dev/sda -r / -o /tmp --loglevel=DEBUG --log_file=/tmp/image_bundle.log

Now the last steps will be upload the bundle and serve it.

You'll need to authenticate yourself with your GCE’s project (follow on-screen directions):

$ gcloud auth login

Create a storage bucket for your image (the name has to be unique across Google Cloud Storage globally). Mine is “my-gce-images”.  Let’s upload our bundle and instruct the GCE to build image out of it:

$ gsutil cp /tmp/<whatEverNameCreatedByBundelTool> gs://<your-gce-images-bucket>/<name-of-image>.tar.gz

$ gcutil addimage <image-name-to-be> gs://<your-gce-images-bucket>/<name-of-image>.tar.gz -project <project-ID>

That would be it and you should be able to see your new and shining Ubuntu image under “Images” in your GCE project. Enjoy!


AuthorDoron Offir