USB Linux Part I

Introduction

I find it useful to carry a LiveCD Linux distribution on an usb flash drive with me. It means I can boot into a Linux system with my preconfigured software, its useful for system recovery and adds an extra layer of privacy. Previously I used Slax Linux which worked; however, I found myself wanting more customisability into the installed software and appearance. So I set out to build my own LiveCD Linux.

One of the main features I want is ‘run from ram’. In this mode the operating system is loaded into ram at boot and then runs completely from ram. This has a range of benefits:

  • improved performance as ram read/ writes are faster then writing onto the usb flash disk
  • increased lifespan of the usb flash drive by reducing write cycles
  • increased privacy as when the ram is cleared no trace will be left of the Linux system (theoretically would still be retrievable by a cold boot attack)
  • allows for the usb flash disk to be removed after the system has booted (avoids leaving it behind!)

Most Linux distributions are able to run from ram; however, for a portable Linux I need to create a small sized image to avoid exceeding the computer’s maximum ram size.

Alpine Linux

Alpine Linux is a good option for this; it offers a small base image size (121 mb) and runs from ram by default (known as diskless mode). As diskless mode copies the Linux image to ram any writes to the system will be stored in ram and lost at system reboot. To provide configuration persistence between reboots the local backup command can be used. This writes system modifications to an overlay file (.apkovl) which is loaded into the ram alongside the image at boot.

One feature I want is WireGuard, which provides a vpn connection to my home server. Although standard packages can be installed easily through the package manager adding kernel modules whilst in diskless mode is a bit trickier. At boot Alpine uses modloop to mount a squashfs filesystem of the kernel onto /.modloop. /lib/modules then symlinks these files; therefore, when booted will be read only access. This means kernel modules will fail to be installed. One option to solve this it to create a custom iso with WireGuard already installed into the kernel; this is explained below in Part 1. In Part 2 I will use this iso to install Alpine Linux to the usb flash disk and add in the software to create a usable environment.

Setting up the build environment

To build a custom iso an Alpine Linux development machine is required. To set this up Alpine Linux can be installed into a virtual machine; in my case a VM with 2gb ram, 2 cpu cores, 10gb hard disk.

Once the VM is initialized download the extended iso to the host machine and add it the cd-rom slot of the newly created VM. When run the VM will boot Alpine Linux into diskless mode. After logging into the root terminal (entering root as username) the install script script can be run with:

# setup-alpine

This script will guide the install process. Select sys mode for the install method which gives a ‘traditional’ hard disk install.

After a reboot the VM is all set up and ready to become a development machine.

Adding the required packages

Currently there are no other users apart from root so logging in will enter a root terminal. Install the required build tools with:

# apk add alpine-sdk build-base apk-tools alpine-conf busybox fakeroot syslinux xorriso squashfs-tools mtools dosfstools grub-efi git sudo

User management

Create a new user build and add to the abuild group:

# adduser build
# adduser build -G abuild

Now grant the build user sudo privileges:

# visudo

And enter:

# visudo

... ## ## User privilege specification ## build ALL=(ALL:ALL) ALL ...

Create signing keys

Uncomment and add your details to /etc/abuild.conf

/etc/abuild.conf

... PACKAGER="Your Name <[email protected]>" MAINTAINER="$PACKAGER" ...

At this point, exit the root terminal and log back in with the build user.

Create the signing keys with:

$ abuild-keygen -a -i

Note: -i copies the keys to /etc/apk/keys/ which is required to successfully build the iso

Cloning aports

Clone the aports repository.

$ git clone git://git.alpinelinux.org/aports ~/aports

Note: The aports repository holds the APKBUILD files for every package. APKBUILD file is the script that is used to build / compile a package.

Now we are ready to start building.

Adding Broadcom Wi-Fi Chipset support

The Broadcom Wi-Fi Chipset is used in older computers and without this firmware Linux will be unable to use those computer’s Wi-Fi. I have a couple of machines that use this chipset so I need to add support for this. The firmware package is not available in the Alpine Linux repositories but can be built from aports:

$ cd ~/aports/non-free/b43-firmware
$ abuild -r

This will compile the package and create a local repository in ~/packages/non-free/. The package could then be copied and installed to the usb flash disk after the system has been set up. It is easier; however, to add the package into the iso we are going to create.

Making the ISO

Creating the iso makes use of the mkimage.sh script. This uses a profile script to build the iso; examples of these can be found in ~/aports/scripts/ and have the name format mkimg.PROFILENAME.sh.

Create a new file ~/aports/scripts/mkimg.portable.sh with the following contents:

~/aports/scripts/mkimg.portable.sh

profile_portable() { profile_standard kernel_addons="wireguard" apks="$apks b43-fwcutter b43-firmware" local _k _a for _k in $kernel_flavors; do apks="$apks linux-$_k" for _a in $kernel_addons; do apks="$apks $_a-$_k" done done

This profile tells mkimage.sh to build on top of profile_standard which is the profile for the standard Alpine Linux iso. Then it uses two lists to tell it which packages to install:

  • kernel_addons will have the kernel version appended to the name, e.g. wireguard-lts
  • apks will be installed as is

To build using the our newly created profile mkimage.sh is called with the following parameters:

$ sh ~/aports/scripts/mkimage.sh --tag v3.11 \
    --outdir ~/iso \
    --arch x86_64 \
    --hostkeys \
    --repository http://dl-cdn.alpinelinux.org/alpine/v3.11/main \
    --extra-repository http://dl-cdn.alpinelinux.org/alpine/v3.11/community \
    --extra-repository ~/packages/non-free \
    --profile portable

This builds mkimg.portable.sh using the v3.11 repository and our local repository containing the Broadcom firmware we built above. It signs it with the keys we created and outputs to ~/iso/.

This iso now provides both WireGuard and Broadcom support and is ready to be used to create the portable Linux in Part 2.


May 2020