One script, set hard

The whole installer is one shell script. It asks its questions at the start, then works through the night, and writes down everything it did.

01Four acts

Only the first act happens on the machine you already trust, and only one step in it is typing.

1

Choose

What you are building and where it goes: an SD card, a USB stick, or an image file that touches no hardware at all. Alpine is downloaded and checked against its published checksum in front of you.

on your Mac · minutes

2

Say who you are

A username, a name and email for git, and the SSH public key already in the Mac's ~/.ssh. Only the .pub half ever travels.

on your Mac · one prompt

3

Pick a level

Log in as root, run copal-init.sh, choose server, medium or full, and walk away. Stage 3 moves the system onto the disk and reboots once; it comes back and carries on by itself.

on the new machine · hours, unattended

4

Log in as yourself

The desktop belongs to your account, never to root. On the full level, Copal Apps opens at the first login and installs the last sixteen programs while you watch them arrive.

on the new machine · done

# on your Mac
$ ./copal build vm            # or: ./copal card pi4, ./copal build pc
$ ./copal vm create --target aarch64 --image build/copal-vm.img

# on the new machine, as root, with no password yet
# sh /media/vda1/copal-init.sh   # answer yes: do the whole thing

02Eighteen stages

The levels are bundles of the same eighteen stages; nothing is a different code path, and every stage can be run again afterwards, alone and in any order. Roughly: 1–3 make it a computer, 4–6 make it usable, 7–15 make it yours, 16 makes it one of several, 17 gives it the Antiquity desktop, and 18 opens Copal Apps.

StageWhat it settles
1base configAlpine's own setup, from your answers; the admin account, doas, shells
2ext4 + apk cachepackages survive a reboot on a RAM-resident root
3full root/ moves onto the disk — reboots
4X.Org and i3the fallback desktop, its keys, and every Copal helper it needs
5zramcompressed swap in RAM
6SSH keyyour Mac's public key, authorised
7developmentcompilers, debuggers, Neovim, Claude Code, and your repositories cloned into ~/code
8grow rootthe root partition grows into the whole disk, while mounted
9emulatorsMini vMac and VICE, with disks and launchers
10peripheralswifi, Bluetooth, audio, capture, disk tools
11snapshotsrsync snapshots on a third partition — asked, never unattended
12applicationsthe catalogue: over 300 programs
13hand over rootroot locked; you log in as yourself — checks first
14the workshopCAD, KiCad, ngspice, lab instruments, LaTeX, trackers
15SD card carewhat wears a card, and a read-only root if you want one
16the fleetjoin a fleet of Copal machines — only when one is named
17Antiquity desktopHyprland on Wayland, the Linux Antiquity theme — aarch64 and x86_64
18Copal Appsthe programs, by what they do; the full monty's sixteen queued for the first login

03A playbook per program

Every program Copal installs from its shelf is a playbook: one file per project, named after it. The header is data — where it comes from, what it needs to build and to run, which programs it puts on the machine, and two sentences saying what each one is. The body is its steps: pre to prepare, install to put it there, and post to finish it — first-run settings, menu entries, whatever makes the program complete rather than merely present.

# playbooks/Creative/darktable.sh
# playbook: darktable
# source:   github darktable-org/darktable
# build:    build-base cmake samurai gtk+3.0-dev exiv2-dev lensfun-dev …
# runs:     iso-codes exiftool
# program:  darktable
# about:    A darkroom for camera raw files: exposure, colour, lens correction
#           and masks, applied without touching the original. …
darktable_install() { … pinned release, SHA-256, cmake … }
darktable_post()    { … the welcome dialog, turned off … }

Where to get a program is a policy, not a habit: Alpine's package when it is current and stable; the program's own release, compiled on the machine and pinned by checksum when upstream is ahead or Alpine does not carry it; and a git clone into ~/code for projects that are worked on there. Given several programs, Copal installs all their prerequisites in one step before the first compile, and takes the build-only ones away in one step after the last.

The playbooks are separate files in the repository, and make assembles them into the one script that ships — so a machine still updates itself by fetching a single file.

04Everything, written down

A long install you did not watch is only as good as its record. Copal keeps three:

The sources are kept too, so a rebuild or a reinstall downloads nothing, and every temporary file is cleaned away when each build ends.