I have about fourteen years worth of electronic mail stored on my laptop. Browsing through the archives is like looking straight into the soul of a person I'm not sure ever actually existed.
Like that cute girl that smiled to you while crossing paths at the airport, the character that's only in the book for a couple of pages, or a friend of a friend somebody once mentioned in passing.
I started writing a blog post, the first one in a year.
Then I realized the technical stuff I wanted to talk about, a workaround for an annoying software issue, is no longer relevant because upstream has changed his mind and decided to fix it for good.
It's taken me a long time, but I think I get it now.
The day you are pushed into a fire and it hurts so much you feel like you're going to die, you tell yourself that the pain will go away because that's the only way you can cope with it. And, eventually, it really does.
But your body, your hands, your face, they're all covered in scar tissue now, and those marks will remain until your last day. You survived, but every time you look in the mirror you're reminded of the price you had to pay. How can your life ever be like it was before, knowing that?
Looking at the build status for Cattle on Debian, I noticed that the test suite fails on some of the more exotic architectures. Here’s the error message:
ERROR:tape.c:282:test_tape_decrease_current_value: assertion failed: (cattle_tape_get_current_value (tape) == 127)
Not exactly helpful. It would be much easier to debug the issue if I had interactive access to a computer running Debian on one of those architectures… Luckily, turns out that I do!
$ egrep '^Processor|^Hardware' /proc/cpuinfo
Processor : ARMv7 Processor rev 0 (v7l)
Hardware : SMDK4x12
The computer in question is my Samsung Galaxy SIII smartphone which, with a bit of work, can be used as a Debian development host, and a pretty good one at that.
The procedure I’m about to describe will work on most Android
smartphones and tablets, provided that root access is available and
busybox has the right commands compiled in.
If, like me, you’re running CyanogenMod on your device, you already have everything you need. Note that I’ve only tested this on CM 11, though.
First of all, you’re going to need a computer running Debian. Other
Unix–like operating systems will work as well, but obtaining and
debootstrap on them is probably going to be a little
convoluted, so it’s left as an exercise to the reader.
$ dd if=/dev/zero of=debian.img bs=1M count=1024
$ sudo mkfs.ext4 -F debian.img
This will create a
debian.img file, 1GB in size, which will
contain your Debian system. 1GB is enough for the base system,
build-essential and a bunch of other libraries with 250MB to
spare. Mount the image with
$ sudo mount -o loop debian.img /mnt
and complete the first stage of the bootstrap process with
$ sudo debootstrap --arch=armhf --variant=minbase --foreign unstable /mnt http://ftp.debian.org/debian
$ sudo umount /mnt
debian.img to your Android device and launch a
terminal emulator. Become root by running
and navigate to the directory you’ve saved your image to. Now for the interesting bits:
# mount -o rw,remount rootfs /
# mknod /dev/block/loop99 b 7 99
# mount -o ro,remount rootfs /
This creates the loopback device you’re going to use to mount the image on Android. It will be automatically deleted on reboot, so don’t bother removing it when you’re done.
# mkdir debian
# losetup /dev/block/loop99 debian.img
# mount -t ext4 /dev/block/loop99 debian
Your image is now mounted on
debian/. A few filesystems are
needed on top of that for the system to work properly:
# mount -o bind /dev debian/dev
# mount -t devpts none debian/dev/pts
# mount -t proc none debian/proc
# mount -t sysfs none debian/sys
Now you can finally complete the installation!
# chroot debian /bin/bash
# export PATH=/usr/sbin:/usr/bin:/sbin:/bin
# /debootstrap/debootstrap --second-stage
Once the bootstrap is complete, you can perform any customization you might want. I immediately created an unprivileged user; then, after setting up DNS with
# echo "nameserver 184.108.40.206" >/etc/resolv.conf
# echo "nameserver 220.127.116.11" >>/etc/resolv.conf
and configuring software repositories with
# echo "deb http://ftp.debian.org/debian unstable main" >/etc/apt/sources.list
I was able to install
openssh-server, which is crucial because,
by this point, I could no longer bear to type Unix commands on a tiny virtual
Once the OpenSSH daemon is running, you can either login from a computer connected to the same wireless network or directly from the Android device by using something like
$ ssh firstname.lastname@example.org
I prefer the second approach: I just connect the phone to my laptop with the USB cable, start a shell on the device with
$ adb shell
and login to the Debian system using the command above.
Once you’re done with your Debian work, you need to stop any daemon you’ve started inside the chroot and umount all the filesystem in reverse order from a privileged Android shell, like
# umount debian/sys
# umount debian/proc
# umount debian/dev/pts
# umount debian/dev
# umount debian
Doing this every time would become tedious, of course, so I've created a couple of shell scripts that do everything for me; they even support multiple Debian chroots running concurrently, because why not :)
You can grab the scripts, along with some documentation, from the Git repository.
Once you’re inside the chroot, it’s actually easy to forget you’re working on a phone: everything behaves exactly like it would on an Intel computer, if only a little slower. This is not a watered–down version of Debian, it’s the real deal. Kudos to all the developers who have have made such an impressive thing possible!
Now on to hunt the actual bug :)
«I still think it’s weird», she said. «All these years living in the same town — not even a big one — and we’ve bumped into each other, like, two times?»
«That might be related to the fact that I never leave my house unless I’m forced to», I replied in a guilty whisper.