So, this is a blog :3

Let’s see whether I publish blog posts regularly. You may know me as the girl dropping systemd into postmarketOS initially, making the team with @Casey excited about it which then turned into a huge distro-wide effort resulting in the first stable release with systemd(!!) and then Alpine Linux shipping systemd units via a subpackage and sooo much more. Posts will be mainly about the progress of various projects and I would appreciate feedback (especially of my style of writing these blog-posts) to @jane@smolhaj.social.

Well, planning and executing are two different beasts but I’ll try to give a quick overview over my projects:

Projects

Project Protostar

A nice name where basically lump in everything Alpine Linux and postmarketOS related. I technically gave me a break in direct postmarketOS involvement for a year, but that doesn’t work out in practice (hehe). Now I have more time reinventing the wheel!

systemd’s DynamicUsers on musl

Still in the prototyping stage, but the nearest to completion. There are various ways this can be done, but all ways involve patching musl-libc in postmarketOS:

NSS on musl

Implementing a full-blown NSS in musl, which wouldn’t need any code-changes in systemd. While it would enable cool stuff like resolved integration, glibc’s module system is still an ugly hack to workaround limitations to extend libc functionality. We can do better.

musl-nscd

Using musl-nscd or a similar daemon in systemd itself would work, we would have to be careful around synchronization and early boot. This probably results in forking musl-libc too to add required tooling. Early prototypes by me during the first Boiling the Ocean (example toot) in late 2024 resulted in lockups.

Stabilizing internal systemd interfaces for a musl-libc to use them. This is something that would have to be maintained indefinitely and would require co-operation or worst-case forks of both musl-libc and systemd.

The nss-systemd module currently does two things:

  • provide root and nobody user/group combo if they don’t exist yet (e.g. if /etc/passwd is missing entirely or missing those entries)
  • lookup entries in UserDB (setting EXCLUDE_NSS and optionally EXCLUDE_DYNAMIC_USER to prevent recursion)
  • exposes a _nss_systemd_block function to disable/enable itself at runtime. This functionality needs more documentation upstream, this is only described as public API in the commit introducing it.

We would still not support other NSS modules, but for passwd, shadow entries and groups one could make a daemon translating NSS modules to a UserDB service. (I’m thinking of authd.)

This is currently the solution I’m working on and off since October 2025. I’m using Rust, the core crate and the simd-json crate. After figuring out that _nss_systemd_block is indeed a public API I figured I could make musl expose that function and “hijack” the usual redirect of dlopen to itself for other bundled libraries like libm, libpthread by just including libnss_systemd in that list. Now I just need to change the fallback calls to __nscd_query (the entire giant if block here) to call my beautiful little rust code. I currently have a UserDB CLI client which worked on a single socket while using bindgen to libc, I’m currently implementing an epoll based helper for multiplexing as I’m not allowed to call io.systemd.Multiplexer in any scenario. I also tried to keep the code ready for the eventual static lib for inclusion into the musl build system, while also keeping an eye on memory management as we need to deal with “four” different allocation types. We have the usual C pains like static thread-local memory passed in via an pointer to a function, usual C malloc, rust-based “heap” allocation via core::alloc calling the C malloc and the usual stack-based allocation in Rust. This together with &str, &ffi::CStr, the read-only pointer guarantees by core::CString also meant I needed to introduce a LibCString calling malloc directly for use in the usual C environment.

The drawbacks will be a constant maintenance load as this will never be accepted by upstream, I feel don’t even need to ask. This will also need attention from systemd, as this project is probably the first using UserDB such intensly outside of the monorepo. I expect this to be only introduced in postmarketOS at first, as I assume Alpine Linux doesn’t want to include it. So we we’ll need a bunch of monitoring, testing, version-constraints and fast upkeep to not break ABI between aports' libc and pmaports' libc.

UserDB goes POSIX

IMO UserDB is a great good enough protocol, we should just propose the inclusion into the POSIX spec. I also dislike having the standard library as both dynamic linker and standard C library anyway, dlopen as part of standard user/group lookup incentivizes that.

multitool

Building a Rust based abuild/pmbootstrap re-implementation. The project is currently quite early in development and therefore in a prototyping stage. I’m announcing this now as I reached the first goal of my initial road-map. multitool currently uses brush and one of the more notable novel ideas I try with this is replacing abuild functions by shell builtins by crafting a custom bash environment. APKBUILD would be more easily introspectable. pmbootstrap made quite some progress creating dependency graphs by “simple” regex on shell scripts but I want to eventually go one step further: multitool should be able to do this correctly, fast and secure.

Reached:

Soon reached:

  • metadata of an APKBUILD in a stable json format
    • already parsed, a minimal set of abuild functions/variables/builtins are implemented.
    • schema files are not written yet and hence mapping from shell variables isn’t implemented yet

Far far away:

  • sandboxed worker-threads giving data to the frontend (CLI, potentially pmbootstrap?)
  • parsing APKINDEX files
  • “chroot” package building (in modern: overlayfs, containers, syscall filters and more)
  • cross-compiling made easy: meson integration
  • reproducible build (and finally using that fancy ~hash suffix :3)

config-preset

Still at an concept stage, no start of a prototype yet. A home-manager style vendor/admin/user configuration for Alpine Linux based on Lix, with aports packages providing derivations for Lix. With some sort of ACL in mind: the default should be “soft” settings modifiable by users but admins can set policies enforced/read-only. This may even extend into an MDM-style management of devices.

paranoidOS

Still at an concept stage, no start of an prototype yet.

  • signed u-boot with fastboot locked to those u-boot keys.
  • HSM based verified boot and credential management (reusing both Android and Windows components available on the device, e.g. mssecapp.mbn for a Trust-Zone based TPM)
  • File based or Home based encryption with things like gnome-clocks, calls working without credentials.
  • using pKVM/QHEE to isolate waydroid and/or linux apps
  • niceties like DNS-over-TLS by default
  • a networking daemon providing a NetworkManager D-BUS API which works in tandem with sandboxing (e.g. connecting to a WiFi with a captive portal. The WebView for the captive portal is only seeing the WLAN interface, the rest of the device would still use Mobile Networking.)
  • verityfs? only signed code is run? the sky is endless. But Project Duranium from @craftyguy seems to beat me in that regard.
  • basically anything good from GrapheneOS