Archive

Posts Tagged ‘chroot’

Installing Debian wheezy on android (chroot method)

December 7, 2014 4 comments

This is a yet another guide on how to install Debian GNU/Linux on your android phone. While there are huge number of resources available on the Internet dedicated on how to install GNU/Linux to your android phone, this guide aims to show how to do it step by step manually without the use of any additional android applications and tools.

Before we begin, there are some prerequisites that should be met to install GNU/Linux on your android device,

  • Root access to your android device and busybox installed.
  • Your android’s Linux kernel should support loop devices and one of etx2/3/4 filesystems
  • A system running Debian GNU/Linux

If these prerequisites are met, then let’s get down to our first step, which is creating a chroot image.

Note: commands which required to be run as root are prefixed with sudo.

Debian has a tool called debootstrap which automates the process of creating a base debian system which can be chrooted into. Install debootstrap if you don’t have it installed already.

sudo apt-get install debootstrap

Now run debootstrap in terminal with the following arguments,

sudo debootstrap –arch armel –foreign wheezy ./wheezy ftp://ftp.uk.debian.org/debian

Note: Issue with WordPress fonts makes double dashes appear as single dash. single dash which appears before arch and foreign needs to be replaced with double dash

As we are creating a Debian system for a different architecture than an x86 system in which debootstrap is run, –arch armel argument is used to instruct debootstrap to create debian base system for arm architecture. –foreign instructs it to do initial unpack only, a second stage install is done on the actual hardware. wheezy instructs it to create a wheezy system. Replace with any other name like squeeze or jessie or testing or stable to create an appropriate system image. ./wheezy tells it to download the packages to directory named wheezy in the current directory from where debootstrap is run. And finally a repository url to fetch the packages from. You can use your local repository here, but make sure it has packages for the architecture armel. See man page of debootstrap if you need more information.

While this process runs let’s create an image file to hold the Debian system. I prefer to use an image file instead of creating an dedicated partition on the sdcard, as this way its portable and can be resized later easily when you need more space. To create an image file with size 1GB run the following command,

dd if=/dev/zero of=./linux.img bs=1M count=1024

If you need any other size replace count with appropriate value. Any size can be used according to the free space on your android’s sdcard, but a minimun of 1GB is recommended.Once it completes a file named linux.img with specified size is in the current directory.

Before creating a file system on this file, check what ext filesystem your android’s Linux kernel supports by running the following command in your android terminal.

grep ext /proc/filesystems

My phone’s kernel supports only ext2, so I’m creating an ext2 filesystem on this image file.

sudo mkfs.ext2 linux.img

Once filesystem is created, this image file can be mounted anywhere on the system, like an ordinary disk drive. I’m creating a directory named tmpmntpnt under tmp and for mounting this image file,

mkdir /tmp/tmpmntpnt

sudo mount -o loop linux.img /tmp/tmpmntpnt/

After this is done, check whether the debootstrap has completed successfully. If it is complete, copy the files under wheezy directory created by debootstrap to this linux.img mounted under /tmp/tmpmntpnt/ using,

cp -rp ./wheezy/* /tmp/tmpmntpnt/

-rp is used to recursively copy the files and preserving the files ownership and permissions. Once the files are copied, unmount the image using the command,

sudo umount /tmp/tmpmntpnt

Now the first step which is creating a chroot image is complete.

Before moving on to the second step, copy the linux.img just created to your android’s sdcard.

Moving on to second step, preparing your android device and mounting the image.

There is a lot of typing that needs to be done on the android device, so its preferable you use adb shell to type commands from your workstation to android device instead typing it directly in the device. Install android-tools-adb in debian which enables us to connect to android device over usb.

sudo apt-get install android-tools-adb

While installation is going on, enable android usb debugging in your android device settings under developer tools menu and connect the device to your workstation using usb cable and after adb-tools is installed,run

adb shell

to connect to your android shell. Once it connects and shows the $ prompt issue su command to get root. All the commands below needs to be run as root in your android shell.

Sdcards in android are mounted with nodev,noexec and nosuid. As we’ll be bind mounting device files and executing binaries with suid root, we’ll need to remount sdcard as,

busybox mount -o remount,exec,dev,suid /sdcard

Then, create a loop device to mount our linux.img,

loopno=254

mknod /dev/block/loop$loopno b 7 $loopno

This creates a block device with major number 7, minor number 254. These numbers are chosen by looking at the existing loop devices created by android os in my phone by running,

ls -l /dev/block/loop*

brw——- root     root       7,   0 2014-12-06 16:50 loop0
brw——- root     root       7,   1 2014-12-06 16:50 loop1
brw——- root     root       7,   2 2014-12-06 16:50 loop2

My android creates loop devices with major number 7 with incrementing minor numbers. You just have to choose the same major number and a minor number thats not yet used. As you install more apps to sdcard, it’ll create loop device for each of them, to prevent conflict I used 254, which is unlikely to be used any time soon. You can just use the same numbers I used without looking for all this stuff if you are not interested.

Once the loop device is created, associate our linux.img to this loop device using,

losetup /dev/block/loop$loopno /sdcard/linux.img

Now to mount it, create a directory under /data/local

mntpt=/data/local/linux

mkdir $mntpt

Then mount the loop device to this directory,

busybox mount -t ext2 -o relatime /dev/block/loop$loopno $mntpt

Take care to replace ext2 with the filesystem you used for the linux.img.

This completes the second step.

Moving on to the third step, which is completing second-stage installation and setting up debian system.

Once the image has been mounted, bind the kernel directories from your android to debian using,

for f in dev dev/pts proc sys ; do mount -o bind /$f $mntpt/$f ; done

This above step bind mount /dev /dev/pts/ /proc/ /sys to debian image, which means that it will be available to both android and debian and changes made from debian to any of the files in these directories will reflect in android and vice versa. These directories are required for the proper functioning of debian.

You can also optionally bind mount your sdcard to make it accessible under debian by using,

sdcard=$(readlink -f /sdcard)

mkdir $mntpt/media/sdcard

mount -o bind $sdcard $mntpt/media/sdcard

This will make files in sdcard available to both debian and android.

Now our debian system is ready to be chrooted into. Before doing that we’ll need to set some environment variables, so that the binaries in debian work properly. If this not set up correctly, debootstrap will fail to run.

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
export HOME=/root

Then setup /etc/resolv.conf file to enable dns resolution so that external addresses can be connected to,

echo “nameserver 8.8.8.8” > $mntpt/etc/resolv.conf
echo “nameserver 8.8.4.4” >> $mntpt/etc/resolv.conf

Now chroot into debian and complete the second stage installation,

chroot $mntpt /bin/bash -l
debootstrap/debootstrap --second-stage

This will take a while to complete. Once it completes, your debian system is ready 🙂

You can now use apt-get to install additional binaries. Let’s take a look at how to install openssh-server to remotely connect to our debian system.

Before using apt-get, repository needs to configured in /etc/apt/sources.list, just as you would do on a normal debian system. To do this run,

echo “deb http://ftp.uk.debian.org/debian/ wheezy main contrib non-free” > /etc/apt/sources.list

Now refresh repository information and install openssh-server

apt-get update

apt-get install openssh-server

After this is complete don’t forget to set password for root using passwd command to remotely log in to. Then try connecting to your device by using ssh from your workstation.

ssh root@<ip address of your android device>

If you are able to connect successfully, then congrats, you have installed yourself a debian system on your android from scratch. To unmount the debian system logout from the debian environment and unmount the directories mounted above using umount command.

Automate this mount and unmount process by putting the commands inside a script and installing it under /system/bin, so that it’ll save you from typing the commands over and over.

A quick hacked up script to mount and log in to the debian system and unmount it.

#!/system/bin/sh

arg=$1

loopno=254
loopdev=/dev/block/loop$loopno
mntpt=/data/local/linux
sdcard=$(readlink -f /sdcard)

if [ “$arg” == “unmount” ] ; then
umount $mntpt/media/sdcard
for f in dev/pts dev proc sys ; do umount $mntpt/$f ; done
umount $mntpt
losetup -d $loopdev
rm $loopdev
exit 0;
fi

mknod $loopdev b 7 $loopno
losetup $loopdev /sdcard/linux.img
busybox mount -t ext2 -o relatime $loopdev $mntpt
for f in dev dev/pts proc sys ; do mount -o bind /$f $mntpt/$f ; done
mount -o bind $sdcard $mntpt/media/sdcard
export HOME=/root
export USER=root
export TERM=screen
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH

chroot $mntpt /bin/bash -l

Save this script under /system/bin by mounting /system partition as rw and assign executable permissions to the script by

mount -o remount,rw $(mount | grep system | cut -d " " -f 1,2)
cp /sdcard/linux /system/bin/linux
chmod 755 /system/bin/linux
mount -o remount,ro $(mount | grep system | cut -d " " -f 1,2)

From now on, you’ll be able to login to debian by just using linux and unmount it by issuing linux umount from android shell.
Reference: https://wiki.debian.org/ChrootOnAndroid#Manual_installation_in_a_chroot
Update: to free memory used by android and make it available to Debian see https://blulin.wordpress.com/2014/12/07/freeing-up-resources-for-use-by-gnulinux-on-your-android-device/