# How to install Ubuntu on your Android phone

Update (May 2014): I’ve since had the occasion to do this again on my [Xperia U][xu], and this time I used [Linux Deploy][ld] to install [Ubuntu][ub] 14.04 inside [Android][an] 4.0.x – it worked flawlessly, and besides having [the source available][ghld], it has up-to-date presets to download and install the required bootstrap files directly on the phone (no computer required).

To make a long story short, we took a mini-break out in the countryside, and I got bored.

I was supposed to relax and read up on a whole bunch of stuff related to natural language processing, but since I’ve been fiddling around with [LXC][lxc] and chroot so often these days I decided to have a go at upgrading my [Android][an] phone (aka my pocket server) to [Ubuntu][ub] 13.04.

(In case you missed that post, I’m using the [Complete Linux Installer][cli] to [run a server sandbox][b1] off an old Xperia Arc S, and it works well enough for me to run an instance of this site there – and much more besides.)

do-release-upgrade worked fine to step up to 12.10 from 12.04, but the Complete Linux Installer’s supplied images are built with armel binaries whereas 13.04 has moved on to armhf exclusively – so after confirming that my Xperia could run armhf binaries via multiarch (which, incidentally, made things a tad snappier), I decided to build a new image from scratch.

Regretfully there’s very little info out there on how to go about doing that other than a few scattered forum posts, so I decided to document the process. It’s all fairly straightforward provided you’re using the Complete Linux Installer app already and have a [Ubuntu][ub] box handy (I daresay it can be done on the phone itself on simpler cases).

First off, and for the more general case where you’ll be using an Intel machine to get this going, you need to set up [QEMU][q] and [ARM][a] binary support as well as debootstrap:

sudo cp init.sh /mnt/root/init.sh
sudo chmod +x /mnt/root/init.sh
sudo rm /mnt/usr/bin/qemu-arm-static
sudo mkdir /mnt/sdcard
sudo mkdir /dev/shm
sudo umount /mnt


Now create the filesystem itself (this is for a 2GB image) and mount it under /mnt. Since we don’t need all the bells and whistles of ext3/ext4 (after all, the end result will be running inside a file), we’ll be building everything inside an ext2 filesystem:

Next up, use debootstrap to deploy the basics (note the arch and raring settings):

Now deploy qemu-arm-static inside the soon-to-be chroot:

…and use it to finish the deployment:

Once that’s done, we need to set up apt sources (you can optionally set up deb-src as well, but I have yet to need it):

From then on, you can install stuff as required (this is my base setup):

If you have enough horsepower, you can also install a [VNC][vnc] server (and a minimal [X11][x11] setup) by doing:

Even though this is not really necessary for an [Android][a] chroot, you should also set up a serial console in case you ever need to run this under [QEMU][q] again[^1]:

To top everything off, you need to set up a user with sudo access[^1]:

Next up, exit the chroot:

Now for the Complete Linux Installer tweak, which boils down to copying across their init.sh script (of which I’ve made a [local copy][init]) to /root/init.sh and making sure it’s executable[^3], as well as adding a couple of extra mount points:

sudo cp init.sh /mnt/root/init.sh
sudo chmod +x /mnt/root/init.sh
sudo rm /mnt/usr/bin/qemu-arm-static
sudo mkdir /mnt/sdcard
sudo mkdir /dev/shm
sudo umount /mnt


Now copy the image across (it should clock in at about 400MB compressed, in case you want to keep a copy around), replace the original [Ubuntu][ub] image on your SD card, and you’re golden.

I’ve since managed to get [Postgres][pg] running on mine – just disable TCP and use UNIX sockets instead so that it doesn’t get confused with the network setup.

1. This is actually more common than you’d think - I used to run an emulated Intel chroot inside a PowerPC [Mac mini][mm], and forgot to do this every time I upgraded it. ↩︎

2. Note that the Complete Linux Installer script insists on adding the user to the admin group, which doesn’t actually exist on [Ubuntu][ub]. ↩︎

3. I’ve tweaked the one I’m actually using a bit further, since I need /dev/shm to work. Also, I wish they’d document the configuration files somewhere – I’d also like to have custom mounts working without hacking them into the script. ↩︎