Update (May 2014): I’ve since had the occasion to do this again on my Xperia U, and this time I used Linux Deploy to install Ubuntu 14.04 inside Android 4.0.x – it worked flawlessly, and besides having the source available, 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 and chroot
so often these days I decided to have a go at upgrading my Android phone (aka my pocket server) to Ubuntu 13.04.
(In case you missed that post, I’m using the Complete Linux Installer to run a server sandbox 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 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 and ARM binary support as well as debootstrap
:
sudo apt-get install debootstrap qemu-user-static qemu-system git \
gcc-arm-linux-gnueabihf binfmt-support
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:
dd if=/dev/zero of=ubuntu.img bs=1024 count=2097152
mkfs.ext2 ubuntu-armhf.ext2.img
sudo mount -o loop ubuntu-armhf.ext2.img /mnt
Next up, use debootstrap
to deploy the basics (note the arch
and raring
settings):
HOSTNAME=ubuntu-armhf sudo debootstrap --variant=minbase --foreign \
--arch armhf raring /mnt
Now deploy qemu-arm-static
inside the soon-to-be chroot
:
sudo cp /usr/bin/qemu-arm-static /mnt/usr/bin/
…and use it to finish the deployment:
LANG=C sudo chroot mnt /usr/bin/qemu-arm-static -cpu cortex-a9 /bin/bash
./debootstrap/debootstrap --second-stage
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):
echo "deb http://ports.ubuntu.com raring main restricted universe" > /etc/apt/sources.list apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 428D7C01
From then on, you can install stuff as required (this is my base setup):
apt-get update
apt-get install sudo apt-utils dialog less wget vim net-tools openssh-server \
htop tmux build-essential libevent-dev python-dev python-setuptools \
python-lxml sqlite3 nodejs npm golang git-core
If you have enough horsepower, you can also install a VNC server (and a minimal X11 setup) by doing:
apt-get install --no-install-recommends tightvncserver
Even though this is not really necessary for an Android chroot
, you should also set up a serial console in case you ever need to run this under QEMU again1:
cp /etc/init/tty1.conf /etc/init/ttyAMA0.conf
sed -i "s/tty1/ttyAMA0/" /etc/init/ttyAMA0.conf
To top everything off, you need to set up a user with sudo
access1:
adduser ubuntu
usermod -aG sudo ubuntu
Next up, exit the chroot
:
exit
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) to /root/init.sh
and making sure it’s executable3, 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 image on your SD card, and you’re golden.
I’ve since managed to get Postgres running on mine – just disable TCP and use UNIX sockets instead so that it doesn’t get confused with the network setup.
-
This is actually more common than you’d think - I used to run an emulated Intel
chroot
inside a PowerPC Mac mini, and forgot to do this every time I upgraded it. ↩︎↩︎ -
Note that the Complete Linux Installer script insists on adding the user to the
admin
group, which doesn’t actually exist on Ubuntu. ↩︎ -
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. ↩︎