Overview

  • What is a Linux distribution
  • How popular package managers work
  • Introducing our package manager
  • Internals

What is a Linux distribution

.
├── boot
├── dev
├── etc
│   ├── group
│   └── ...
├── home
├── proc
├── root
├── run
├── sys
├── tmp
├── usr
│   ├── bin
│   │   ├── awk
│   │   ├── ls
│   │   ├── sh
│   │   └── ...
│   ├── include
│   │   ├── stdio.h
│   │   ├── stdlib.h
│   │   └── ...
│   ├── lib
│   │   ├── crti.o
│   │   ├── libc.so
│   │   ├── libz.so
│   │   └── ...
│   ├── lib64 -> lib
│   └── share
│       └── ...
└── var
    ├── cache
    └── ...

Filesystem Hierarchy

Building Packages

$ tar xf zlib-1.3.1.tar.gz 
$ cd zlib-1.3.1; ls
CMakeLists.txt   README           crc32.h          gzlib.c          inflate.c        old              uncompr.c        zlib.3.pdf
ChangeLog        adler32.c        deflate.c        gzread.c         inflate.h        os400            watcom           zlib.h
FAQ              amiga            deflate.h        gzwrite.c        inftrees.c       qnx              win32            zlib.map
INDEX            compress.c       doc              infback.c        inftrees.h       test             zconf.h          zlib.pc.cmakein
LICENSE          configure        examples         inffast.c        make_vms.com     treebuild.xml    zconf.h.cmakein  zlib.pc.in
Makefile         contrib          gzclose.c        inffast.h        msdos            trees.c          zconf.h.in       zutil.c
Makefile.in      crc32.c          gzguts.h         inffixed.h       nintendods       trees.h          zlib.3           zutil.h
$ ./configure --prefix=/usr
Checking for gcc...
Checking for shared library support...
Building shared library libz.so.1.3.1 with gcc.
Checking for size_t... Yes.
...
Checking for attribute(visibility) support... Yes.
$ make
gcc -O2 -pipe -march=x86-64-v2 -mtune=generic -fno-math-errno -fstack-protector-strong --param ssp-buffer-size=4 -D_FORTIFY_SOURCE=3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
...
$ make DESTDIR="/path/to/sysroot" install
  • Downloading source tarballs
  • Configuring the build via autotools, meson, cmake, etc.
  • Building & Installing

How popular package managers work

Pacman (Arch Linux)

  • Uses bash-based PKGBUILD scripts for building packages
  • Supports installing binary packages from repositories in addition to source-based builds (AUR)

PKGBUILD example

pkgname=make
pkgver=4.4.1
pkgrel=2
pkgdesc="GNU make utility to maintain groups of programs"
arch=('x86_64')
url="https://www.gnu.org/software/make"
license=('GPL3')
depends=('glibc' 'guile')
source=("https://ftp.gnu.org/gnu/${pkgname}/${pkgname}-${pkgver}.tar.lz"{,.sig})
sha256sums=('8814ba072182b605d156d7589c19a43b89fc58ea479b9355146160946f8cf6e9'
            'SKIP')
validpgpkeys=('6D4EEB02AD834703510B117680CB727A20C79BB2')   # Paul Smith

build() {
	cd "${pkgname}-${pkgver}"
	./configure --prefix=/usr
	make
}

check() {
	cd "${pkgname}-${pkgver}"
	make -k check
}

package() {
	cd "${pkgname}-${pkgver}"
	make DESTDIR="${pkgdir}" install
}
$ makepkg
==> Making package: make 4.4.1-2 (Fri 14 Nov 2025 09:00:09 AM UTC)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Downloading make-4.4.1.tar.lz...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1275k 100  1275k   0     0 491547     0   0:00:02  0:00:02 --:--:-- 491584
==> Validating source files with sha256sums...
    make-4.4.1.tar.lz ... Passed
==> Extracting sources...
  -> Extracting make-4.4.1.tar.lz with bsdtar
==> Starting build()...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
gcc -I/usr/include/guile/3.0 -I/usr -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions         -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security         -fstack-clash-protection -fcf-protection         -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -g -ffile-prefix-map=/home/testuser/make/src=/usr/src/debug/make -flto=auto -Wl,--export-dynamic -Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now          -Wl,-z,pack-relative-relocs -flto=auto -o make src/ar.o src/arscan.o src/commands.o src/default.o src/dir.o src/expand.o src/file.o src/function.o src/getopt.o src/getopt1.o src/guile.o src/hash.o src/implicit.o src/job.o src/load.o src/loadapi.o src/main.o src/misc.o src/output.o src/read.o src/remake.o src/rule.o src/shuffle.o src/signame.o src/strcache.o src/variable.o src/version.o src/vpath.o  src/posixos.o  src/remote-stub.o  -lguile-3.0 -lgc -lpthread -ldl lib/libgnu.a   
make[1]: Leaving directory '/home/testuser/make/src/make-4.4.1'
==> Entering fakeroot environment...
==> Starting package()...
Making install in lib
...
make[2]: Entering directory '/home/testuser/make/src/make-4.4.1'
 /usr/bin/mkdir -p '/home/testuser/make/pkg/make/usr/include'
 /usr/bin/mkdir -p '/home/testuser/make/pkg/make/usr/share/man/man1'
 /usr/bin/mkdir -p '/home/testuser/make/pkg/make/usr/bin'
 /usr/bin/install -c -m 644 src/gnumake.h '/home/testuser/make/pkg/make/usr/include'
 /usr/bin/install -c -m 644 doc/make.1 '/home/testuser/make/pkg/make/usr/share/man/man1'
  /usr/bin/install -c make '/home/testuser/make/pkg/make/usr/bin'
make[2]: Leaving directory '/home/testuser/make/src/make-4.4.1'
make[1]: Leaving directory '/home/testuser/make/src/make-4.4.1'
==> Tidying install...
  -> Removing libtool files...
  -> Purging unwanted files...
  -> Removing static library files...
  -> Stripping unneeded symbols from binaries and libraries...
  -> Compressing man and info pages...
==> Checking for packaging issues...
==> Creating package "make"...
  -> Generating .PKGINFO file...
  -> Generating .BUILDINFO file...
  -> Generating .MTREE file...
  -> Compressing package...
==> Creating package "make-debug"...
  -> Generating .PKGINFO file...
  -> Generating .BUILDINFO file...
  -> Generating .MTREE file...
  -> Compressing package...
==> Leaving fakeroot environment.
==> Finished making: make 4.4.1-2 (Fri 14 Nov 2025 09:02:05 AM UTC)
$ pushd extracted; tar xf ../make-4.4.1-2-x86_64.pkg.tar.zst; tree -a -L 3
.
├── .BUILDINFO
├── .MTREE
├── .PKGINFO
└── usr
    ├── bin
    │   └── make
    ├── include
    │   └── gnumake.h
    └── share
        ├── info
        ├── locale
        └── man
$ cd /var/lib/pacman/local/make-4.4.1-2; ls
desc  files  mtree
$ cat files
%FILES%
usr/
usr/bin/
usr/bin/make
usr/include/
usr/include/gnumake.h
usr/share/
usr/share/info/
usr/share/info/make.info-1.gz
usr/share/info/make.info-2.gz
usr/share/info/make.info-3.gz
usr/share/info/make.info.gz
usr/share/locale/
usr/share/locale/be/
usr/share/locale/be/LC_MESSAGES/
usr/share/locale/be/LC_MESSAGES/make.mo
usr/share/locale/bg/
usr/share/locale/bg/LC_MESSAGES/
usr/share/locale/bg/LC_MESSAGES/make.mo
usr/share/locale/cs/
usr/share/locale/cs/LC_MESSAGES/
usr/share/locale/cs/LC_MESSAGES/make.mo
usr/share/locale/da/
usr/share/locale/da/LC_MESSAGES/
usr/share/locale/da/LC_MESSAGES/make.mo
usr/share/locale/de/
usr/share/locale/de/LC_MESSAGES/
usr/share/locale/de/LC_MESSAGES/make.mo
usr/share/locale/es/
usr/share/locale/es/LC_MESSAGES/
usr/share/locale/es/LC_MESSAGES/make.mo
usr/share/locale/fi/
usr/share/locale/fi/LC_MESSAGES/
usr/share/locale/fi/LC_MESSAGES/make.mo
usr/share/locale/fr/
usr/share/locale/fr/LC_MESSAGES/
usr/share/locale/fr/LC_MESSAGES/make.mo
usr/share/locale/ga/
usr/share/locale/ga/LC_MESSAGES/
usr/share/locale/ga/LC_MESSAGES/make.mo
usr/share/locale/gl/
usr/share/locale/gl/LC_MESSAGES/
usr/share/locale/gl/LC_MESSAGES/make.mo
usr/share/locale/he/
usr/share/locale/he/LC_MESSAGES/
usr/share/locale/he/LC_MESSAGES/make.mo
usr/share/locale/hr/
usr/share/locale/hr/LC_MESSAGES/
usr/share/locale/hr/LC_MESSAGES/make.mo
usr/share/locale/id/
usr/share/locale/id/LC_MESSAGES/
usr/share/locale/id/LC_MESSAGES/make.mo
usr/share/locale/it/
usr/share/locale/it/LC_MESSAGES/
usr/share/locale/it/LC_MESSAGES/make.mo
usr/share/locale/ja/
usr/share/locale/ja/LC_MESSAGES/
usr/share/locale/ja/LC_MESSAGES/make.mo
usr/share/locale/ko/
usr/share/locale/ko/LC_MESSAGES/
usr/share/locale/ko/LC_MESSAGES/make.mo
usr/share/locale/lt/
usr/share/locale/lt/LC_MESSAGES/
usr/share/locale/lt/LC_MESSAGES/make.mo
usr/share/locale/nl/
usr/share/locale/nl/LC_MESSAGES/
usr/share/locale/nl/LC_MESSAGES/make.mo
usr/share/locale/pl/
usr/share/locale/pl/LC_MESSAGES/
usr/share/locale/pl/LC_MESSAGES/make.mo
usr/share/locale/pt/
usr/share/locale/pt/LC_MESSAGES/
usr/share/locale/pt/LC_MESSAGES/make.mo
usr/share/locale/pt_BR/
usr/share/locale/pt_BR/LC_MESSAGES/
usr/share/locale/pt_BR/LC_MESSAGES/make.mo
usr/share/locale/ro/
usr/share/locale/ro/LC_MESSAGES/
usr/share/locale/ro/LC_MESSAGES/make.mo
usr/share/locale/ru/
usr/share/locale/ru/LC_MESSAGES/
usr/share/locale/ru/LC_MESSAGES/make.mo
usr/share/locale/sr/
usr/share/locale/sr/LC_MESSAGES/
usr/share/locale/sr/LC_MESSAGES/make.mo
usr/share/locale/sv/
usr/share/locale/sv/LC_MESSAGES/
usr/share/locale/sv/LC_MESSAGES/make.mo
usr/share/locale/tr/
usr/share/locale/tr/LC_MESSAGES/
usr/share/locale/tr/LC_MESSAGES/make.mo
usr/share/locale/uk/
usr/share/locale/uk/LC_MESSAGES/
usr/share/locale/uk/LC_MESSAGES/make.mo
usr/share/locale/vi/
usr/share/locale/vi/LC_MESSAGES/
usr/share/locale/vi/LC_MESSAGES/make.mo
usr/share/locale/zh_CN/
usr/share/locale/zh_CN/LC_MESSAGES/
usr/share/locale/zh_CN/LC_MESSAGES/make.mo
usr/share/locale/zh_TW/
usr/share/locale/zh_TW/LC_MESSAGES/
usr/share/locale/zh_TW/LC_MESSAGES/make.mo
usr/share/man/
usr/share/man/man1/
usr/share/man/man1/make.1.gz

Introducing our package manager

  • Entirely source-based
  • Repositories are just directories on the local filesystem - synced via git (or any other mechanism)
  • Packages are described by multiple files under a directory
repo/
├── core
│   ├── ...
│   ├── pigz
│   │   ├── build
│   │   ├── checksums
│   │   ├── depends
│   │   ├── post-install
│   │   ├── sources
│   │   └── version
│   └── zlib
│       ├── build
│       ├── checksums
│       ├── sources
│       └── version
├── extra
│   ├── ...
│   └── zstd
│       ├── build
│       ├── checksums
│       ├── sources
│       └── version
└── ...
$ ls
build         checksums     depends       post-install  sources       version
$ cat build                                                                                                                            git
#!/bin/sh -ef
#
# Intentional, globbing disabled.
# shellcheck disable=2086

for f in pigz.o yarn.o try.o; do
    echo "$CC" -c -o "$f" "${f%%.o}.c" $CPPFLAGS -DNOZOPFLI $CFLAGS
    "$CC" -c -o "$f" "${f%%.o}.c" $CPPFLAGS -DNOZOPFLI $CFLAGS
done
echo "$CC" -static -o pigz pigz.o yarn.o try.o $CPPFLAGS $CFLAGS -lz $LDFLAGS
"$CC" -static -o pigz pigz.o yarn.o try.o $CPPFLAGS $CFLAGS -lz $LDFLAGS

mkdir -p \
    "$1/usr/bin" \
    "$1/usr/share/man/man1"

cp  -f pigz   "$1/usr/bin"
ln -sf pigz   "$1/usr/bin/gzip"
cp  -f pigz.1 "$1/usr/share/man/man1"
ln -sf pigz.1 "$1/usr/share/man/man1/gzip.1"
$ cat checksums                                                                                                                        git
fa165f414a12851806d9d54920879dd989917b9aa410aec671c602b18773b23638
$ cat sources                                                                                                                          git
https://zlib.net/pigz/pigz-2.8.tar.gz
$ cat depends                                                                                                                          git
zlib make
$ cat version                                                                                                                          git
2.8 1

Metadata Overview

Build & Installation

# kiss_ng build
[DEBUG] looking up dependency zlib of pigz
[INFO] fetching remote file https://zlib.net/pigz/pigz-2.8.tar.gz
0 MB  0.07 MB/s  00:01  [####################################################################################################################################################################################] 100%
[INFO] found remote file pigz-2.8.tar.gz
[INFO] checksum matched fa165f414a12851806d9d54920879dd989917b9aa410aec671c602b18773b23638 pigz-2.8.tar.gz
[INFO] found remote file zlib-1.3.1.tar.gz
[INFO] checksum matched 207c3b0862cb4e3686f8405f76a98c38dbad9c94bcf4be4b9efca0716aba51ecbb zlib-1.3.1.tar.gz
[INFO] (1/1) will build package (explicit) pigz
[INFO] (1/1) building package pigz
[INFO] handling remote source pigz-2.8.tar.gz
cc -c -o pigz.o pigz.c -DNOZOPFLI
cc -c -o yarn.o yarn.c -DNOZOPFLI
cc -c -o try.o try.c -DNOZOPFLI
cc -static -o pigz pigz.o yarn.o try.o -lz
[INFO] inspecting ELF /var/cache/kiss/proc/1311/pkg/usr/bin/pigz of type elf.ET.EXEC
[INFO] successfully built pigz
# kiss_ng install                                                                                                                                     git@main
[INFO] acquiring lock file at /var/cache/kiss/lock...
[INFO] acquired lock file
[INFO] extracting pigz@2.8-1.tar.zst
[INFO] checking for conflicts
[INFO] removing system package
[INFO] successfully executed hook at /var/db/kiss/installed/pigz/post-install in /
$ ls /var/db/kiss/installed/pigz
build         checksums     depends       manifest      post-install  sources       version
$ cat /var/db/kiss/installed/pigz/manifest
/var/db/kiss/installed/pigz/version
/var/db/kiss/installed/pigz/sources
/var/db/kiss/installed/pigz/post-install
/var/db/kiss/installed/pigz/manifest
/var/db/kiss/installed/pigz/depends
/var/db/kiss/installed/pigz/checksums
/var/db/kiss/installed/pigz/build
/var/db/kiss/installed/pigz/README
/var/db/kiss/installed/pigz/
/var/db/kiss/installed/
/var/db/kiss/
/var/db/
/var/
/usr/share/man/man1/pigz.1
/usr/share/man/man1/gzip.1
/usr/share/man/man1/
/usr/share/man/
/usr/share/
/usr/bin/pigz
/usr/bin/gzip
/usr/bin/
/usr/

Internals

Building Packages

  • Compute build order of packages
  • Download & cache source tarballs
  • Verify source checksums
  • Extract the sources in a temp. directory and execute the build scripts
  • Compress the installed files into a package (tar file)

Build Order Computation

$ cat rust/depends 
cmake   make
curl    make
llvm
openssl
pkgconf make
python  make
xz
zlib
$ cat cmake/depends 
bzip2
curl
expat
linux-headers make
zlib
$ cat llvm/depends 
cmake  make
python make
zlib
zstd
$ cat python/depends 
bzip2
expat
libffi
ncurses
openssl
sqlite
zlib
$ cat curl/depends 
openssl
zlib
$ cat sqlite/depends 
zlib
[INFO] (1/16) will build package (implicit) bzip2
[INFO] (2/16) will build package (implicit) certs
[INFO] (3/16) will build package (implicit) openssl
[INFO] (4/16) will build package (implicit) zlib
[INFO] (5/16) will build package (implicit) curl
[INFO] (6/16) will build package (implicit) expat
[INFO] (7/16) will build package (implicit) linux-headers
[INFO] (8/16) will build package (implicit) cmake
[INFO] (9/16) will build package (implicit) libffi
[INFO] (10/16) will build package (implicit) ncurses
[INFO] (11/16) will build package (implicit) sqlite
[INFO] (12/16) will build package (implicit) python
[INFO] (13/16) will build package (implicit) llvm
[INFO] (14/16) will build package (implicit) pkgconf
[INFO] (15/16) will build package (implicit) xz
[INFO] (16/16) will build package (explicit) rust

Build Environment

$ pwd
/var/cache/kiss/proc/1789
$ ls
build    pkg      script   sysroot
$ ls build
CMakeLists.txt   adler32.o        crc32.lo         example64.o      gzread.c         inffast.h        inftrees.lo      minigzip64.o     trees.h          zconf.h.in       zutil.lo
ChangeLog        amiga            crc32.o          examples         gzread.lo        inffast.lo       inftrees.o       minigzipsh       trees.lo         zlib.3           zutil.o
...
$ tree -L 3 pkg
pkg
├── usr
│   ├── include
│   │   ├── zconf.h
│   │   └── zlib.h
│   ├── lib
│   │   ├── libz.a
│   │   ├── libz.so -> libz.so.1.3.1
│   │   ├── libz.so.1 -> libz.so.1.3.1
│   │   ├── libz.so.1.3.1
│   │   └── pkgconfig
│   └── share
│       └── man
└── var
    └── db
        └── kiss
  • Source files extracted & built in build
  • Built artifacts installed to pkg
  • Enumerate all installed files and write to a manifest file

Sandboxing

  • All builds are run as root
  • Process is only granted read-only permissions to the filesystem using the Landlock API
  • A temporary rootfs (sysroot) is created that only contains relevant files for the build which is executed under chroot
$ ls sysroot
bin    boot   dev    etc    home   lib    lib64  mnt    opt    proc   root   run    sbin   sys    tmp    usr    var
$ ls sysroot/var/db/kiss/installed
baselayout     bzip2          gcc            gnugrep        linux-headers  musl           xz
binutils       file           git            libmpc         make           ncurses        zlib
busybox        flex           gmp            libseccomp     mpfr           util-linux     zstd
$ ls -i sysroot/usr/bin/gcc
 891411 sysroot/usr/bin/gcc
$ ls -i /usr/bin/gcc
 891411 /usr/bin/gcc
+---------------------------------------+
| landlock_create_ruleset()             |
+---------------------------------------+
                |
                v
+---------------------------------------+
| landlock_add_rule("/", READ_ONLY);    | // Read-only access to the whole filesystem
+---------------------------------------+
                |
                v
+---------------------------------------------------+
| landlock_add_rule("/var/cache/kiss", READ_WRITE); | // Read-write access for the build & packaging directory
+---------------------------------------------------+
                |
                v
+---------------------------------------+
| unshare(CLONE_NEWNS);                 | // Unshare a new mount namespace for the sysroot
+---------------------------------------+
                |
                v
+-----------------------------------------------------------+
| mount("/var/cache/kiss/proc/<PID>",                       | // Bind mount relevant directories like the build directory
|       "sysroot/var/cache/kiss/proc/<PID>", MS_BIND);      | // and /dev, /proc, etc.
+-----------------------------------------------------------+
                |
                v
+------------------------------------------------+
| linkat("/usr/bin/gcc", "sysroot/usr/bin/gcc"); | // Enumerate all files provided by symlinks and hardlink them into the sysroot
+------------------------------------------------+
                |
                v
+---------------------------------------+
| chroot("sysroot");                    | // Chroot into the sysroot directory
+---------------------------------------+
                |
                v
+-----------------------------------------------------------+
| execve("/var/cache/kiss/proc/<PID>/script");              | // Execute the build step
+-----------------------------------------------------------+

deck

By git-bruh

deck

  • 11