Built on Alpine

Small, simple and secure — Alpine's own three words, and the reason a desktop this complete can start from a Pi Zero.

01What Alpine is

Alpine Linux is an independent Linux distribution built around a few deliberate choices, each smaller than the usual one:

musl libc

A compact, standards-minded C library in place of glibc. Programs are smaller and start faster; software written only for glibc sometimes needs a hand.

the C library

BusyBox

The everyday commands — shell, file tools, networking — as one small program, instead of a separate package for each.

the userland

OpenRC

A dependency-based init system of plain shell scripts, which a person can read end to end.

the init system

apk

A fast package manager with a stable main repository, a community one, and edge/testing for newer software.

packages

By Alpine's own count, a container needs no more than 8 MB and a minimal install to disk about 130 MB. Stable releases come twice a year, and each is supported for years. It is the base of a great many container images for the same reasons it suits a Raspberry Pi: little is running, and what is running can be read.

02Diskless, then set hard

Alpine can run diskless: it boots from read-only media into RAM, and nothing is written anywhere unless you save it. That is how it first comes up on a Copal card, and it is where the name comes from — resin before it hardens. Stage 3 moves the running system onto the disk in Alpine's ordinary sys mode, keeping the small system and giving it a disk to remember with. Everything Copal does is done with Alpine's own tools: setup-alpine for the base, apk for packages, OpenRC for services.

03What building for musl takes

Copal compiles programs Alpine does not carry, or carries in an older release, and most of them were written on glibc. The differences are small, specific, and worth writing down. From the programs built for Copal Apps:

The differenceWhat it brokeWhat Copal does
a thread gets 128 KB of stack, not 8 MBNaev crashed loading textures on a worker thread; DDNet's renderer overflowedlinks every build for glibc-sized thread stacks
no execinfo.hcrash handlers that print a stack tracestubs that report no frames; the crash is still logged
glibc's own extensionsArdour's bundled GTK used nftw flags musl lackstakes the portable path the code already had
build probes that test glibc's macrosdarktable's image library could not learn the page sizegives it the machine's page and cache-line sizes
large-file names are opt-incode calling stat64 and friendsasks for them in every build

Each fix sits in the playbook of the program that needed it, with a comment saying why — so the next version of the program can be built without rediscovering it.

04Aggregated, not forked

Copal downloads stock Alpine from Alpine's mirrors and checks it against Alpine's published checksum before anything is written. It replaces no package. What it installs comes from Alpine's own repositories — edge/testing only for the packages named for it, tagged so nothing else follows — or is compiled on the machine from a pinned release whose checksum is written in its playbook. The exceptions are named: the Brave browser, from Flathub, and Claude Code, from npm. Copal is not affiliated with or endorsed by the Alpine project — it is built on its work, with thanks.