# apk: Alpine's packages on SchOS Alpine is musl with a different init, and SchOS is musl with a different kernel. Alpine's binaries run on SchOS unmodified: its dynamic linker, its busybox, and apk itself, fetching over TLS through SchOS's network stack. So instead of porting programs one at a time, SchOS can install them. ## The model The root filesystem is an apk-managed root: | Part | Where it comes from | |---|---| | musl, busybox, apk-tools, alpine-keys, CA certificates | Alpine's minirootfs (`ports/alpine`) | | what `ports/alpine/world` lists (zsh, terminfo, ...) | Alpine's packages, pinned in `world.lock` | | schinit, its jobs, SchOS's tools, toybox, mksh, configuration | **schos-base**, an apk package the build makes from `sysroot/` | `apk add` installs anything from Alpine's main and community repositories. `apk upgrade` updates Alpine's packages, and schos-base from the SchOS repository at `/var/lib/schos/repo`. PID 1 is still schinit. Alpine's OpenRC is not installed, and packages that ship OpenRC services install them where nothing reads them. ## Who owns what Where Alpine and SchOS both have a program, Alpine's wins, and SchOS keeps only what is its own (see `tools/posix/mkaroot.sh`): - `/bin/sh`, `cat`, `sed`, `find` and the rest are busybox. Alpine's package scripts are written against busybox. - zsh is Alpine's. SchOS keeps its `zshrc` and `zshenv` (`replaces=zsh`). - `/etc/os-release` and `/etc/motd` are SchOS's (`replaces=`). - `passwd`, `group` and `profile` are Alpine's. schos-base's post-install sets root's shell to zsh, and SchOS's profile is `/etc/profile.d/schos.sh`. - mksh is `/bin/mksh`. schinit's recovery shell looks for it first because it is static: a broken musl cannot take recovery down with it. ## Building make aroot build/aroot.img: the root, as a SchFS volume make qemu-aroot boot it make alpine-lock re-resolve world against Alpine (needs the network) Only `alpine-lock` asks Alpine what is current. A normal build installs exactly what `world.lock` names: files in `dist/alpine/`, fetched once and checked against the lock's sha256, and against Alpine's signatures by apk. schos-base and its repository index are signed with a key made on the first build (`build/apk-keys/`, never committed). The root trusts it beside Alpine's keys. ## Kernel work this needed All of it found by running apk: - **TCP receive window:** it reopened before the reader drained, so lwIP refused data and the sender waited on retransmission timers (5 KB/s). It now reopens on read, with a 32-segment window. - **mmap address reuse:** freed ranges were never reused, so musl's malloc used up the 256 mapping records with 780 MB of RAM free. - **unlinkat / renameat:** bare `-1`, read as EPERM, where apk expects ENOENT; renameat could not replace its target, and wrote v1 dirents into SchFS. - **`#!` scripts in execve**, and ENOEXEC: apk runs triggers directly. - **chroot**, and mounting devtmpfs and proc more than once. ## Next - The live ISO and USB stick are still the ramdisk root. They need the apk root on the stick itself, or an installer that writes it to a disk. - Xorg from apk (`xorg-server xf86-video-fbdev xf86-input-evdev`) instead of the hand port in [xorg.md](xorg.md). The packages install; running them is the next test.