Alpine Linux Notes

This series is to explore the feasibility of using Alpine Linux in embedded systems.


Testing Alpine Linux a bit using quickemu:

quickget alpine 3.15`
quickemu --vm alpine-3.15.conf

The install iso was only 50MB! The installed size was about 95MB.

After the system booted, I ran setup-alpine and went with mostly defaults. The one confusing part was the keyboard to use – I ended up with us-alt-intl. After rebooting, I was able to log in.

ssh access

With quickemu, I could not get a bridged network to work, so ended up port forwarding the ssh port:


From there I could add a user, install sudo, add a user to wheel group, and enable the wheel group in /etc/sudoers – then I could ssh as the new user and run sudo.

Updating to the latest release

Updating to the latest release was pretty simple:

  1. edit /etc/apk/repositories
  2. replace version with 3.18
  3. enable commuinity repo
  4. apk upgrade

Update was very fast and now /etc/os-release shows 3.18.3 and kernel is 6.1.55

Init system

Alpine uses OpenRC for an initsystem – most of the rest of the world uses systems. I must admit I have mixed feelings about this – systems does provide some nice features, but it is also becoming quite a hog.

I then installed the Caddy webserver to get a feel for init.

sudo apk add caddy
sudo rc-update add caddy

I like that OpenRC uses run levels like default, manual, etc instead of numbers. After rebooting, it does appear that Caddy is running:

localhost:~$ service caddy status
 * status: started
localhost:~$ ps -A | grep caddy
 2461 root      0:00 supervise-daemon caddy --start --respawn-delay 2 --respawn-max 5 --respawn-period 1800 --user caddy caddy /usr/sbin/caddy -- run --config /etc/caddy/Caddyfile --adapter caddyfile
 2462 caddy     0:00 /usr/sbin/caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
 2594 cbrake    0:00 grep caddy

Man Pages

apk add man-db man-pages

Building alpine packages in archlinux or any other linux distro using chroot

NOTE: that these process will involve some sudo permissions which does not work in chroot environemt on all kind of file systems e.g. if the host has f2fs file system then it will not work. However it works all well with ext4.

chroot will user users as group so add yourself to that group on host ( archlinux)

sudo usermod -a -G users kraj

clone your fork of aports repository

cd ~/work

git clone

clone the chroot script

cd ~/work
git clone

cd alpine-chroot-install

sudo ./alpine-chroot-install -a x86_64 -b edge -d /mnt/a/alpine-x86_64 -i /home/kraj/work/aports -p build-base -p alpine-sdk

cd $HOME

Run /mnt/a/alpine-x86_64/enter-chroot [-u <user>] [command] to enter the chroot
and /mnt/a/alpine-x86_64/destroy [--remove] to destroy it.

Configure chroot for development ( once )

adduser kraj abuild
# setup the abuild configuration
echo 'PACKAGER="Khem Raj <>"' >> /etc/abuild.conf
echo 'MAINTAINER="$PACKAGER"' >> /etc/abuild.conf
echo "%abuild ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/abuild

# Now login using normal user ( kraj )
/mnt/a/alpine-x86_64/enter-chroot -u $USER
abuild-keygen -a -i -n

# Add git commit hook for alpine
cd aports
cat <<-'_EOF_' >".git/hooks/prepare-commit-msg"
  case "$2,$3" in
      if git diff-index --diff-filter=A --name-only --cached HEAD \
          | grep -q '/APKBUILD$'; then
        meta() { git diff --staged | grep "^+$1" | sed 's/.*="\?//;s/"$//';}
        printf 'testing/%s: new aport\n\n%s\n%s\n' "$(meta pkgname)" \
          "$(meta url)" "$(meta pkgdesc)" "$(cat $1)" > "$1"
        printf '%s\n\n%s' `git diff-index --name-only --cached HEAD \
          | sed -n 's/\/APKBUILD$//p;q'` "$(cat $1)" > "$1"
chmod +x ".git/hooks/prepare-commit-msg"

exit chroot and restart with normal user.

/mnt/a/alpine-x86_64/enter-chroot -u $USER

cd ~/work/aports

1 Like

Adding a new package to alpine - Lets try adding simpleiot and see how it goes

~/work/aports $ newapkbuild -h
newapkbuild 3.12.0-r0 - generate a new APKBUILD
Usage: newapkbuild [-n PKGNAME] [-d PKGDESC] [-l LICENSE] [-u URL]
       [-a | -C | -m | -p | -y | -r] [-s] [-c] [-f] [-h]
  -n  Set package name to PKGNAME (only use with SRCURL)
  -d  Set package description to PKGDESC
  -l  Set package license to LICENSE, use identifiers from:
  -u  Set package URL
  -a  Create autotools package (use ./configure ...)
  -C  Create CMake package (Assume cmake/ is there)
  -m  Create meson package (Assume is there)
  -p  Create perl package (Assume Makefile.PL is there)
  -y  Create python setuptools package (Assume is there)
  -e  Create python gpep517 package (Assume pyproject.toml is there)
  -r  Create rust package (Assume Cargo.toml is there)
  -s  Use sourceforge source URL
  -c  Copy a sample init.d, conf.d, and install script
  -f  Force even if directory already exists
  -h  Show this help

OK time to try adding simpleiot

~/work/aports $ newapkbuild \
-u "" \
-d "Simple IoT cloud/edge application/framework" \
-l "Apache-2.0" \

And it generated the template

~/work/aports/testing $ cat simpleiot/APKBUILD
# Contributor:
# Maintainer:
pkgdesc="Simple IoT cloud/edge application/framework"
subpackages="$pkgname-dev $pkgname-doc"

build() {
        # Replace with proper build command(s)

check() {
        # Replace with proper check command(s)

package() {
        # Replace with proper package command(s)

And in less than two hours I have a new aports done from 0 to a pull requets with all tests passing etc. and few bugs to address in simpleiot

Alpine dev experience could ne solid !! I am just starting

1 Like

simpleiot is now in alpine/testing - testing/simpleiot: new aport - aports - Alpine packages build scripts

1 Like

yoe-kiosk-browser is in official alpine ports now - testing/yoe-kiosk-browser: new aport (cf1ea6ff) · Commits · alpine / aports · GitLab

1 Like

That is a nice concise recipe!

We need to write openRC scripts to launch otherwise updating flow is well set.
Next would be to start thinking about image builder.