This howto is an update of Howto install a Debian/GNU Linux system onto a USB flash thumbdrive with the root partition encrypted (using Yaird & DM-Crypt).
So open your favorite root login shell and follow these steps!
Notes:Load any/all needed kernel modules (this is a partial list, actual list depends on your configuration):
root@hostname# modprobe ehci_hcd root@hostname# modprobe ohci_hcd root@hostname# modprobe usbhid root@hostname# modprobe usb_storage root@hostname# modprobe dm-crypt root@hostname# modprobe aes (or aes_686 or aes_x86_64 as appropriate for your system)
Install the necessary applications on the build system:
root@hostname# apt-get install cryptsetup dmsetup parted debootstrap grub
Determine what device our system identifies our flash media as. To do this, simply stick the usb thumbdrive into one of the usb ports and then run the tail command:
root@hostname# tail -n 14 /var/log/messages
Jan 1 12:00:00 hostname kernel: ohci_hcd 0000:00:02.1: wakeup
Jan 1 12:00:00 hostname kernel: usb 2-3: new full speed USB device using ohci_hcd
and address 2
Jan 1 12:00:00 hostname kernel: Initializing USB Mass Storage driver...
Jan 1 12:00:00 hostname kernel: scsi2 : SCSI emulation for USB Mass Storage devices
Jan 1 12:00:00 hostname kernel: usbcore: registered new driver usb-storage
Jan 1 12:00:00 hostname kernel: USB Mass Storage support registered.
Jan 1 12:00:00 hostname kernel: Vendor: Model: TS256MJFLASHA Rev: 1.00
Jan 1 12:00:00 hostname kernel: Type: Direct-Access ANSI SCSI
revision: 02
Jan 1 12:00:00 hostname kernel: SCSI device sda: 506400 512-byte hdwr sectors (259 MB)
Jan 1 12:00:00 hostname kernel: sda: Write Protect is off
Jan 1 12:00:00 hostname kernel: SCSI device sda: 506400 512-byte hdwr sectors (259 MB)
Jan 1 12:00:00 hostname kernel: sda: Write Protect is off
Jan 1 12:00:00 hostname kernel: sda: sda1 sda2
Jan 1 12:00:00 hostname kernel: sd 2:0:0:0: Attached scsi removable disk sda
root@hostname#
As we can see from this output, the device was detected and assigned to /dev/sda.
Next we need to partition the media. For a flash media installation, we will have a boot & a root partition. There will be no swap as this could prematurely age the drive.
For formating, we'll need a small unencrypted boot partition and then assign the rest to / (root).
root@hostname# parted /dev/sda "mklabel msdos mkpart primary 0.0 25.0 mkpart primary 25.0 -0 set 1 boot on" root@hostname#
root@hostname# cryptsetup luksFormat /dev/sda2 WARNING! ======== This will overwrite data on /dev/sda2 irrevocably. Are you sure? (Type uppercase yes): YES Enter LUKS passphrase: Verify passphrase: Command successful. root@hostname#
root@hostname# cryptsetup luksOpen /dev/sda2 rootfs Enter LUKS passphrase: key slot 0 unlocked. Command successful. root@hostname#
root@hostname# mkfs.ext2 /dev/mapper/rootfs
mke2fs 1.39-WIP (29-Mar-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
123392 inodes, 246383 blocks
12319 blocks (5.00%) reserved for the super user
First data block=0
8 block groups
32768 blocks per group, 32768 fragments per group
15424 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 35 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
root@hostname# mkfs.ext2 /dev/sda1
mke2fs 1.39-WIP (29-Mar-2006)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
5208 inodes, 20800 blocks
1040 blocks (5.00%) reserved for the super user
First data block=1
3 block groups
8192 blocks per group, 8192 fragments per group
1736 inodes per group
Superblock backups stored on blocks:
8193
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 35 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
root@hostname#
Ok, this stage we can lookup the UUIDs for the /boot and encrypted partitions for use later in /etc/crypttab and /etc/fstab.
root@hostname# /lib/udev/vol_id -u /dev/sda1 72ea8e0a-256e-47bd-bfc6-6ba33c2ecd48 root@hostname# /lib/udev/vol_id -u /dev/sda2 or cryptsetup luksUUID /dev/sda2 6278aae2-cad0-437d-affa-02277a0cca52 root@hostname#
Note: /sbin/blkid will give the wrong UUID for LUKS partitions.
Now that we have our partition, we need to create a temporary mount point and mount our partition to it so we can perform our install.
root@hostname# mkdir /mnt/buildroot root@hostname# mount -t ext2 /dev/mapper/rootfs /mnt/buildroot root@hostname# mkdir /mnt/buildroot/boot root@hostname# mount /dev/sda1 /mnt/buildroot/boot root@hostname#
Now that we have our partition mounted, we can install the base Debian system onto it.
root@hostname# debootstrap --arch i386 sid /mnt/buildroot I: Retrieving Release I: Retrieving Packages I: Validating Packages I: Resolving dependencies of required packages... I: Resolving dependencies of base packages... I: Found additional base dependencies: libdb4.2 libgnutls12 libreadline5 libsigc++-2.0-0c2a openbsd-inetd readline-common I: Checking component main on http://ftp.debian.org/debian... I: Retrieving adduser <SNIP> I: Configuring gnupg... I: Configuring sysklogd... I: Configuring klogd... I: Configuring netbase... I: Configuring openbsd-inetd... I: Base system installed successfully. root@hostname#
Some applications that we will install while need access to the system devices and files. To allow that we need to bind certain directories.
root@hostname# mount -o bind /dev/ /mnt/buildroot/dev root@hostname# mount -o bind /sys /mnt/buildroot/sys root@hostname#
root@hostname# chroot /mnt/buildroot /bin/su -l hostname:~#
Use vi to create the /etc/fstab file and add these contents to it:
#/etc/fstab: static file system information. # /dev/mapper/rootfs / ext2 defaults,errors=remount-ro,noatime 0 1 UUID=72ea8e0a-256e-47bd-bfc6-6ba33c2ecd48 /boot ext2 defaults,noatime,ro 0 1 none /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults,noatime 0 0 tmpfs /var/lock tmpfs defaults,noatime 0 0 tmpfs /var/log tmpfs defaults,noatime 0 0 tmpfs /var/run tmpfs defaults,noatime 0 0
Note: /var/tmp should not be mounted as tmpfs as the files stored here are often expected to survive a reboot.
Since we're mounting /boot as read-only, we need to add a hook for apt to remount it as read-write for updates. Create /etc/apt/apt.conf.d/30remount_readwrite like so:
DPkg
{
Pre-Invoke {
"mount -o remount,rw /boot;" }
Post-Invoke {
"mount -o remount,ro /boot;" }
}
Then mount all the filesystems:
hostname:~# mount -a (may need to be run twice) hostname:~#Set Hostname
Set the hostname by editing /etc/hostname, and then add the base configuration to /etc/hosts:
127.0.0.1 localhost.localdoman localhost <hostname>FILE: /etc/apt/sources.list
Next we have to add some sources to the Apt configuration.
deb http://ftp.debian.org/debian sid main non-free contrib deb-src http://ftp.debian.org/debian sid main non-free contrib deb http://mirrors.kernel.org/debian/ sid main non-free contrib deb-src http://mirrors.kernel.org/debian/ sid main non-free contrib
Using Tmpfs to save space has one side effect, and that is since it deletes everything when you unmount it, it causes some applications to lose their log directories. So we need to recreate them when the system boots. The easiest way to do that is to create a initialization file in /etc/rcS.d/S37feraga-init.sh.
#!/bin/sh
case "$1" in
start)
echo
echo "Feraga"
echo "-Recreating required subdirectories on /var/log (tmpfs)"
# /var/log subdirectories.
mkdir -p /var/log/fsck
mkdir -p /var/log/ksymoops
mkdir -p /var/log/news
# Example for the mixmaster anonymous remailer
if [ -f /usr/bin/mixmaster ] ; then
mkdir -p /var/log/mixmaster
fi
# Example for the Tor proxy
if [ -f /usr/sbin/tor ] ; then
mkdir -p /var/log/tor
fi
# Example for Privoxy
if [ -f /usr/sbin/privoxy ] ; then
mkdir -p /var/log/privoxy
fi
# Apt archive subdirectories.
mkdir -p /var/cache/apt/archives/partial
echo "-done."
echo
;;
stop)
echo "Feraga shutting down."
# Add anything that needs to happen at shutdown here.
echo
;;
*)
echo "Usage: cryptdisks {start|stop}"
exit 1
;;
esac
Start by updating the apt databases.
hostname# apt-get update Get:1 http://mirrors.kernel.org sid Release.gpg [189B] Get:2 http://mirrors.kernel.org sid Release [38.3kB] Get:3 http://mirrors.kernel.org sid/main Packages [4079kB] Get:4 http://ftp.debian.org sid Release.gpg [189B] Hit http://ftp.debian.org sid Release Hit http://ftp.debian.org sid/main Packages Get:5 http://ftp.debian.org sid/non-free Packages [74.6kB] Get:6 http://ftp.debian.org sid/contrib Packages [57.1kB] Get:7 http://ftp.debian.org sid/main Sources [1559kB] Get:8 http://ftp.debian.org sid/non-free Sources [30.3kB] Get:9 http://ftp.debian.org sid/contrib Sources [24.3kB] Get:10 http://mirrors.kernel.org sid/non-free Packages [74.6kB] Get:11 http://mirrors.kernel.org sid/contrib Packages [57.1kB] Get:12 http://mirrors.kernel.org sid/main Sources [1559kB] Get:13 http://mirrors.kernel.org sid/non-free Sources [30.3kB] Get:14 http://mirrors.kernel.org sid/contrib Sources [24.3kB] Fetched 7608kB in 48s (158kB/s) Reading package lists... Done hostname#
As space is limited, get in the habit of removing apt's cached files frequently.
hostname# apt-get clean
hostname# apt-get install initramfs-tools Reading package lists... Done Building dependency tree... Done The following extra packages will be installed: busybox klibc-utils libklibc libvolume-id0 udev The following NEW packages will be installed: busybox initramfs-tools klibc-utils libklibc libvolume-id0 udev 0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded. Need to get 873kB of archives. After unpacking 2564kB of additional disk space will be used. Do you want to continue [Y/n]? y <SNIP> Fetched 873kB in 1s (711kB/s) Preconfiguring packages ... Selecting previously deselected package libvolume-id0. (Reading database ... 9071 files and directories currently installed.) Unpacking libvolume-id0 (from .../libvolume-id0_0.103-2_i386.deb) ... Selecting previously deselected package udev. Unpacking udev (from .../archives/udev_0.103-2_i386.deb) ... Selecting previously deselected package busybox. Unpacking busybox (from .../busybox_1%3a1.1.3-4_i386.deb) ... Selecting previously deselected package libklibc. Unpacking libklibc (from .../libklibc_1.4.31-1_i386.deb) ... Selecting previously deselected package klibc-utils. Unpacking klibc-utils (from .../klibc-utils_1.4.31-1_i386.deb) ... Selecting previously deselected package initramfs-tools. Unpacking initramfs-tools (from .../initramfs-tools_0.85e_all.deb) ... Setting up libvolume-id0 (0.103-2) ... Setting up udev (0.103-2) ... A chroot environment has been detected, udev not started. Setting up busybox (1.1.3-4) ... Setting up libklibc (1.4.31-1) ... Setting up klibc-utils (1.4.31-1) ... Setting up initramfs-tools (0.85e) ... hostname#
Configure /etc/initramfs-tools/modules:
usbcore ehci-hcd ohci-hcd uhci-hcd usbhid ide-core scsi_mod usb-storage mbcache ext2 ide-cd ide-disk ide-generic sd_mod
Configure /etc/initramfs-tools/initramfs.conf
# initramfs.conf # Configuration file for mkinitramfs(8). See initramfs.conf(5). MODULES=most BUSYBOX=y BOOT=local DEVICE=eth0 NFSROOT=autoInstall Cryptsetup
hostname# apt-get install cryptsetup dmsetup hashalot Reading package lists... Done Building dependency tree... Done Suggested packages: dosfstools The following NEW packages will be installed: cryptsetup dmsetup hashalot 0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. Need to get 318kB of archives. After unpacking 942kB of additional disk space will be used. Do you want to continue [Y/n]? y <SNIP> Fetched 318kB in 0s (1400kB/s) Selecting previously deselected package dmsetup. (Reading database ... 9299 files and directories currently installed.) Unpacking dmsetup (from .../dmsetup_2%3a1.02.12-1_i386.deb) ... Selecting previously deselected package cryptsetup. Unpacking cryptsetup (from .../cryptsetup_2%3a1.0.4+svn26-1_i386.deb) ... Selecting previously deselected package hashalot. Unpacking hashalot (from .../hashalot_0.3-4_i386.deb) ... Setting up dmsetup (1.02.12-1) ... Setting up cryptsetup (1.0.4+svn26-1) ... Setting up hashalot (0.3-4) ... localepurge: Disk space freed in /usr/share/locale: 4K hostname#
Now that cryptsetup is installed, add the required mounting information to /etc/crypttab:
# <target name> <source device> <key file> <options> rootfs /dev/disk/by-uuid/6278aae2-cad0-437d-affa-02277a0cca52 none luks
Install cryptroot scripts for initramfs.
hostname# cp /usr/share/initramfs-tools/hooks/cryptroot /etc/initramfs-tools/hooks/ hostname:~# cp /usr/share/initramfs-tools/scripts/local-top/cryptroot /etc/initramfs-tools/scripts/local-top/ hostname:~#
Now we need to add a small delay in /etc/initramfs-tools/scripts/local-top/cryptroot to allow for USB detection.
<SNIP>
modprobe -q dm_crypt ## After this line add the following.
# Add delay
echo "Sleeping for 5 seconds to allow USB detection."
sleep 5
echo "Awake, attempting to mount encrypted partitions."
<SNIP>
We want to install Grub before the kernel. We do this to take advantage of the kernels automagic configuration of the required Grub boot stanzas.
First from within the chroot jail, we need to remount /boot as read-write.
hostname# mount -o remount,rw /boot hostname# apt-get install grub hostname#
Next from outside the chroot jail:
root@hostname# grub-install --recheck --root-directory=/mnt/buildroot /dev/sda Probing devices to guess BIOS drives. This may take a long time. Installation finished. No error reported. This is the contents of the device map /mnt/buildroot//boot/grub/device.map. Check if this is correct or not. If any of the lines is incorrect, fix it and re-run the script `grub-install'. (fd0) /dev/fd0 (hd0) /dev/hda (hd1) /dev/sda root@hostname#
Now back inside the chroot jail, we need to open /boot/grub/menu.lst and add this simplified configuration.:
# default num default 0 # timeout sec timeout 5 # pretty colours color green/black black/green ### BEGIN AUTOMAGIC KERNELS LIST ## ## Start Default Options ## # kopt=root=/dev/mapper/rootfs ro\n") # groot=(hd0,0) # alternative=true # lockalternative=false # defoptions= # lockold=false # howmany=all # memtest86=true # updatedefaultentry=false ## ## End Default Options ## ### END DEBIAN AUTOMAGIC KERNELS LIST
Then we need to run grub (again from outside the chroot jail) to link it all together
root@hostname# grub
Probing devices to guess BIOS drives. This may take a long time.
GNU GRUB version 0.97 (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported. For
the first word, TAB lists possible command
completions. Anywhere else TAB lists the possible
completions of a device/filename. ]
grub> root (hd1,0)
root (hd1,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd1)
setup (hd1)
Checking if "/boot/grub/stage1" exists... yes
Checking if "/boot/grub/stage2" exists... yes
Checking if "/boot/grub/e2fs_stage1_5" exists... yes
Running "embed /boot/grub/e2fs_stage1_5 (hd1)"...
failed (this is not fatal)
Running "embed /boot/grub/e2fs_stage1_5 (hd1,0)"...
failed (this is not fatal)
Running "install /boot/grub/stage1 (hd1) /boot/grub/stage2
p /boot/grub/menu.lst "... succeeded
Done.
grub> quit
Remove the Grub device map to force rescanning during boot.
hostname:~# rm -f /boot/grub/device.map hostname:~#
Before we can install the kernel, we need to set its configuration. Edit /etc/kernel-img.conf so that it looks like this:
do_symlinks = yes relative_links = yes do_bootloader = no do_bootfloppy = no do_initrd = yes ## <--- Verify this line link_in_boot = yes postinst_hook = /sbin/update-grub postrm_hook = /sbin/update-grubNext we install the kernel. The package linux-image-686 is a dummy package that requires the current kernel image as a dependency. Remove the linux-image-686 dummy package immediately afterwards or it will force you to update kernels every time a new one is published.
hostname:~# apt-get install linux-image-686 <SNIP> hostname:~# apt-get remove linux-image-686 <SNIP> hostname:~# apt-get clean hostname:~#
After the kernel is installed, remount /boot as read-only.
hostname:~# mount -o remount,ro /boot hostname:~#
Copy an existing /etc/group, /etc/passwd, and /etc/shadow file over from another system (this has to be done from outside the chroot directory).
root@hostname# cp /etc/passwd /etc/group /etc/shadow /mnt/buildroot/etc/ root@hostname#
Then chroot in and create their homedirectories
root@hostname# chroot /mnt/buildroot /bin/su - hostname:~# mkdir /home/<username> hostname:~# chown <username>.<username> /home/<username> <Repeat as necessary> hostname:~# exit root@hostname#Or:
Set root password and add users in the chroot
hostname# chroot /mnt/buildroot /bin/su -
hostname:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
hostname:~# adduser test
Adding user `test'...
Adding new group `test' (1001).
Adding new user `test' (1001) with group `test'.
Creating home directory `/home/test'.
Copying files from `/etc/skel'
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for test
Enter the new value, or press ENTER for the default
Full Name []: test
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [y/N] y
hostname:~#
<Repeat as necessary for more users>
hostname:~# umount -a hostname:~# umount /proc hostname:~# exit root@hostname:~#
Time to unmount everything we've mounted and prepare for reboot.
root@hostname# umount /mnt/buildroot/dev/mapper root@hostname# umount /mnt/buildroot/sys root@hostname# umount /mnt/buildroot root@hostname# cryptsetup luksClose rootfs root@hostname#
And thats it. time to reboot and test.