Installing Debian GNU/Linux in a chroot on a Samsung Galaxy S II

(Last updated 2011-11-25)

There are numerous how-tos on the web for installing a Debian chroot onto a smartphone running Android, but most of them either give you an image to install on your phone (which doesn't teach you anything) or have you set up the Debian system on your desktop and copy it to the phone. Neither of these options appeal to me, so I've done it my own way and written this document to light the way for others, too.

Assumptions made:

If not all of these assumptions are true, please don't contact me if something doesn't go right for you when following this how-to.

Preparation

The first thing you need to do is install cdebootstrap on your phone. cdebootstrap is a tool for bootstrapping a Debian system, usually from another Debian system, but in this case we'll be doing it from Android.

So, to install cdebootstrap:

Bootstrapping the Debian system

Now that you have a working cdebootstrap on your phone, you can use it to bootstrap Debian. First, however, you will need to create a file system for Debian to live on. It may be possible to create such a file system directly on the SD card, but as I don't really understand Android partitioning, I decided not to try this and risk losing data. (If someone knows of a way to do this, please contact me and let me know!) The reason you need a separate file system for Debian is that Android mounts its own file systems with options like noexec, which would disallow executing all binaries placed on them (thus defeating the purpose of an operating system).

The easiest way to set up a file system is to simply create a file in /mnt/sdcard and format that -- but beware, if you make this file larger than 2 GiB, the FAT file system it lives on will complain and you will lose the image next time you reboot. This happened to me the first time I tried it, and I hadn't made a backup, so I had to do it all over again. :(

So, ssh to your phone, and run the following commands:

# dd if=/dev/zero of=/mnt/sdcard/debian.img bs=1024 count=2000000
# mke2fs -Fj /mnt/sdcard/debian.img
# mkdir /debian
# mount -t ext3 -o noatime,errors=remount-ro /mnt/sdcard/debian.img /debian

One last thing you need to do before setting up Debian: cdebootstrap expects the system shell to be at /bin/sh and fails without telling you why if it isn't. Since Android's system shell is /system/bin/sh, you have to appease cdebootstrap like so:

# mkdir /bin && ln -s /system/bin/sh /bin/sh

Now comes the fun bit, where we actually set up a Debian system. Still on your phone, run cdebootstrap to set up a file system tree in /debian. You may want to tweak the options below; I'm using ftp.debian-ports.org as my mirror because (at the time of writing) the armhf architecture is not yet fully integrated into the official archive. If you're using armel, or if you happen to live in the future, you can use your normal Debian mirror for this. Obviously, feel free to replace unstable with whichever suite you want to install.

# cdebootstrap --allow-unauthenticated -c/data/local/bin/cdebootstrap-support/ unstable /debian http://ftp.debian-ports.org/debian/

We have to use --allow-unauthenticated because gpgv isn't available to authenticate signatures on Android. This command can take a while to complete, so go and have a coffee or something while you wait for Debian to download and install.

Fixing broken packages

It was the case for me that some packages failed to install from cdebootstrap. Fortunately, it had at least progressed to the point where a shell and dpkg were installed and usable in the chroot, so now we can leave cdebootstrap behind and work in Debian:

# chroot /debian /bin/bash
# cd /var/cache/bootstrap
# dpkg -i *.deb

At this point, dpkg may run into some problems. As the package archive changes over time and different people install different suites, your problems will very likely not be the same as mine, so here's where your familiarity with the Debian package tools comes in. ;)

The main issue I ran into here was circular dependencies. These can be fixed by the use of the --force-depends option to dpkg, to allow it to install and configure one of the packages in the dependency loop, so that you can then install the others normally. For example, I found that libc6 depends on libgcc1, which pre-depends on multiarch-support, which depends on libc6. After running:

# dpkg --force-depends --configure multiarch-support

this circular dependency was no longer a problem, although there were other remaining circular dependencies that could be fixed in a similar way.

Once you have resolved a few circular dependencies and want to try again, it is a good idea to run:

# dpkg --configure -a

before telling dpkg to try installing packages again, as the shell glob *.deb will simply present the packages in alphabetical order, which is usually not a sensible order in terms of satisyfing dependencies. dpkg --configure -a will make sure that packages which are already installed (and thus don't depend on any which aren't installed yet) get configured before those which aren't already installed (and might depend on installed packages being configured).

Installing a standard Debian package set

cdebootstrap will only install packages with a priority of required or important. While this will give you a powerful Unix-like base system, it doesn't include many utilities that you would get with a standard Debian system. Once all of your package dependency issues have been resolved, and everything in /var/cache/bootstrap/ is installed, you can use aptitude to install a standard Debian system:

# aptitude install '~prequired|~pimportant|~pstandard'

What you choose to install beyond this depends on your wants and needs, and how you like your Debian. ;)