I build systems software — embedded Linux, wireless firmware, edge infrastructure, OTA pipelines, and whatever else the project demands. This is where I write about what actually happened.
Systems Software Engineer · Cologne, Germany
Systems Software Engineer · Cologne, Germany
I build systems software — embedded Linux, wireless firmware, edge infrastructure, OTA pipelines, and whatever else the project demands. This is where I write about what actually happened.
A debug-info kernel overshoots U-Boot’s decompression buffer by 1.85 MiB. The bundle verifies at every layer, RAUC reports success, and the board silently falls back to the old slot, because the one property that mattered is only observable at bootm time on the device.
Migrating RAUC’s mTLS client key from a file on disk to a TPM2-backed PKCS#11 URI. The recipe wiring was straightforward; the URI was not. module-path is a p11-kit URI extension that libp11 — the parser RAUC’s streaming path actually uses — rejects outright.
Switching RAUC’s streaming mTLS client key from a file path to a PKCS#11 URI produced a one-line error with no obvious cause. The real problem was not the module path, not the engine, and not a missing PIN — it was the sandbox user’s group membership and what tpm2-pkcs11 needs to initialise.
No OE recipe for Telegraf exists upstream. What looked like a straightforward packaging task turned into a Go linker collision, a PIE/CGO conflict, and a credential problem that ruled out the obvious solution entirely.
Part 1 got OTBR running as a non-root user with three capabilities. Part 2 covers the hardening block in the service file — what each directive does, why one had to be an exception, and how to use systemd-analyze security as a decision tool rather than a score to chase. Part 2 of 2.
OpenThread Border Router assumes it runs as root. Getting it down to a least-privilege non-root user means figuring out exactly what it needs — which turned out to be a source code problem, not a trial-and-error problem. Part 1 of 2.