This is part 2 of the router series; you can read part 1 here
The second part on the router series will deal with setting up alpine linux which will form the basis of our router software stack. You do not necessarily need to use alpine for the operating system however its lightweight nature along with the run-from-RAM capability really sets it apart and I think it’s an ideal fit for this project. If you are not interested skip directly to part 3.
Alpine linux has the capability to load configuration on boot. When it boots from USB or other removable media it will load up any extra packages as well all the saved configuration that is stored on a hard disk, SD card, CF card, you name it! Previous configurations can be backed up which makes rolling back the system as easy as renaming a file. You can always do a traditional disk installation if you are so inclined but this is beyond the scope of this article. The installation guide is fairly detailed however there are some issues that you might need to address.
First of all the bootable medium does not forward console output to a serial
port. This is not a problem if you have a monitor that you can plug in but if
you are relying on serial port for interaction as is the case in PC Engines
boards you will need to modify the installation medium to output to serial
console. Then you can follow the installation guide in diskless mode as
usual. You can edit the iso image directly using an ISO editing tool however I
have hacked together a small
script that
does all the work for you. As this script uses systemd-nspawn
to setup a
minimal alpine environment you will need a systemd-based distribution to run
it. Running it is as easy as
# ./make-bootable-alpine.sh RELEASE [TARGET]
So if you want to burn version 3.6.2
on /dev/sdd
(your USB drive) just run
# ./make-bootable-alpine.sh 3.6.2 /dev/sdd
Please be extra careful when providing the device argument as it will delete
everything on your thumb drive. This script is also useful for upgrading
alpine to a different release. Just change the release version and you are
done! By default it will forward all output to /dev/ttyS0
but if you need
a different serial port edit line 136 to your desired value.
Either you edited the bootable medium or not pop it in your computer and the
alpine live environment should boot up. Before setting up alpine we need to
set up network and repositories. To do so run setup-alpine
and follow the
on-screen instructions up to the point of repository selection. Afterwards
just hit Ctrl-C
. We will do the rest of the setup in a minute. Just use
the dhcp
option for the interface that is connected to the internet. We
will not do any router specific configuration at the moment, since this
article is oriented into setting up alpine.
Now we need to setup our persistence medium. This is a device that will store
all packages and local configuration that will load up on every boot. For the
PC engines build I used an SD card which is presented to the operating system
under /dev/mmcblk0
but you can use any hard disk or USB flash you have
around. Then you need to format it. I think that ext4
usually works best
with alpine. You can probably use any filesystem but I found that alpine would
refuse to properly mount a device formatted in YAFS or JFFS for example. So
stick with what works. This is probably an initramfs issue as there is no
particular reason to refuse to mount any other filesystem as far as the kernel
is concerned but it I find it too much of a hassle to hack around the initrd
scripts.
You will probable need to install e2fsprogs
in order to have the mkfs.ext4
script available. To do so run
# apk add e2fsprogs
We can now format the persistence medium. I do not use a partition, formatting
instead the whole device, but if you need partitions feel free to do so. All
relevant tools such as fdisk
and parted
are available through apk
.
# mkfs.ext4 -O ^has_journal /dev/mmcblk0
The ^has_journal
bit is recommended for SD cards as it will minimise writes
to preserve the SD card lifetime. Since writes will be infrequent and the
filesystem will be mounted most of the time as read-only we can relax the
requirement for a journal. If you are using a regular disk or SSD you can
safely forgo this option.
You can now mount the newly created filesystem. I recommend that you use the
device name instead of a custom name. For example if the formatted device is
sda1
mount it under /media/sda1
. It seems that alpine’s initrd scripts
mount every available filesystem under /media
using the device name,
ignoring your fstab
. This kind of makes sense since fstab
is not available
in the pre-boot environment. So in order to avoid any further complications I
recommend that we stick to that convention.
Before running setup-alpine
for the last time we should take care of a few
config files. First add the persistence medium in your fstab
like so
/dev/mmcblk0 /media/mmcblk0 ext4 ro,noatime,data=writeback,acl 0 0
Since we only need to read from the persistence medium the ro
option is
recommended, especially for SD cards where journal is usually not available.
Remove data=writeback
if you have a journal on your device.
Next up is /etc/lbu/lbu.conf
. lbu
is alpine’s backup utility which is
also used for saving the current configuration. You might want to uncomment
the BACKUP_LIMIT
and setting up to a sensible number. Every time you save
your configuration a backup will be kept in a round robin fashion.
We should now remove the live media as a repository. This will allow us to only
fetch up-to-date packages from the remote repository. To do so edit
/etc/apk/repositories
and remove any local media.
Finally create a folder on your persistence medium to cache the downloaded packages. All installed packages will be first loaded from the cache and then from the remote repository. This is important as packages will be installed again EVERY time the computer boots. So we should not download them again.
# mkdir /media/mmcblk0/cache
You can now run the setup-alpine
script following the details on the wiki.
When you are asked where to save config files choose mmcblk0
or the device
we formatted earlier. Same thing for the cache directory.
Before rebooting we should upgrade the system packages to the latest version. To do so
# apk update && apk upgrade
You can now edit around whatever you want in the /etc
folder. When you are
done you would probably want to save your changes. To do so the lbu
utility
should be used. lbu
has a series of useful commands and I recommend that you
read its wiki page
carefully. In its simplest form lbu
will save your configuration with
# lbu commit
This command must be run EVERY time you change something to your system,
like installing a package or updating a configuration file. If you do not do so
all your changes will be LOST on the next boot. By default lbu
only saves
files and folders under /etc
. If you need to save other folders, for example
/usr/local
where your custom programs or scripts reside you should add them
to the list by using
# lbu add /usr/local && lbu commit
If you also have non-root users you should probably check their home folders
into lbu as well. Please note that you do not need to remount your persistence
medium as rw
every time you run lbu
. It will take care of that and
remount it back as ro
when it exits.
So that’s basically how to get started with alpine. If everything went well you can reboot the computer and all your changes should be loaded up on boot and all local packages from the cache folder will be reinstalled.
That’s the end of part 2. In part 3 we will start to look into router-specific configuration.