Alpine Linux on PCEngines APU

I currently own 4 PCEngines APU boards (2x apu and 2x apu2) which I find perfect for use as low-power servers or routers. For this reason, I like to run a lightweight Linux distro called Alpine Linux. Besides being lightweight I also find this distro quite simple and easy to contribute to. In this post, I’ll be documenting my steps to getting Alpine Linux running on my boards.

These embedded boards don’t have any form of graphical output, simply a serial console port. This is actually kind of nice and minimal, but it requires a bit of tweaking to get it working.

What I do first is master my own custom Alpine Linux installer ISO, this may seem extreme but there is a good reason for this. Firstly I can specify the serial console settings for the installer so that I can proceed to install the operating system using a serial console cable and a laptop. And secondly, so that I can have additional tools pre-loaded in the ISO to update the system firmware. The generated ISO can also function as a helper to flash new firmware without actually installing Alpine Linux.

I frequently maintain Alpine Linux packages, so I have a special environment set up to do my work on the Alpine aports tree. It’s a docker environment so docker and docker-compose is a pre-requisite to the rest of this guide. The environment can be cloned from here. I won’t be going over setting it up in this post.

Clone the Alpine aports tree from here. And clone the docker-abuild repository linked above such that both sit alongside each other.

Navigate to aports/scripts and make a new file and mark it executable with chmod +x, in my case I’m calling it mkimg.apu.sh. In this file we create a new file profile, mine will be the following:

profile_apu() {
    profile_standard
    profile_abbrev="apu"
    title="APU"
    desc="Similar to standard.
        Made for PCEngines APU.
        Enabled serial console, includes flashrom."
    arch="x86_64"
    kernel_cmdline="unionfs_size=512M console=tty0 console=ttyS0,115200"
    syslinux_serial="0 115200"
    apks="$apks flashrom"
}

In this profile I’ve enabled serial console and included the flashrom package, which can be used for upgrading the firmware.

Switch to the docker-abuild directory and enter the abuild environment (explained in the README). Inside the abuild container environment, navigate to ~/aports/scripts (this is mounted from your host filesystem) and run the following command (replace any part of it that you may need in case of version changes):

./mkimage.sh \
  --profile apu \
  --tag v3.13 \
  --repository http://dl-cdn.alpinelinux.org/alpine/v3.13/main \
  --outdir ~/iso

After some time the command will complete and hopefully, a new custom ISO should be present in your host filesystem at docker-abuild/iso.

With this ISO you should be able to boot and install Alpine Linux using the serial console. Once you’ve installed it however, make sure to be able to regain access to the device over the network, I do this by mounting the installed root filesystem to /mnt and modifying etc/ssh/sshd_config to allow password root login over ssh. Then I reboot. The serial console will stop working, but then I can regain access over ssh.

Once I can access the device over ssh, I can modify /etc/update-extlinux.conf to set:

  • serial_baud=115200
  • serial_port=0

And add console=ttyS0,115200 to default_kernel_opts.

To apply these changes, run update-extlinux.

Reboot again to hopefully see serial console output returned.