Muster: Making Little Linux Services Less Haunted
A repo scaffold you hand to Codex, Claude Code, or any coding agent so the small Linux service you built this weekend is still installable, updateable, and rollback-safe in six months. Includes a worked reference — dvd-ingester — and a pattern library of reusable solution atoms.
- essays
- linux
- tools
- agents

Coding got faster. The civilizing of code did not.
Last winter I built a small Bluetooth audio gateway. Home Assistant pushed a stream into Snapcast, Snapcast pushed it to a Raspberry Pi running snapclient, snapclient handed the audio to PipeWire, and PipeWire walked it the last few feet to a Bluetooth speaker on the kitchen counter. Five components. Two protocols. One actual job, which was: play music when someone asks for music.
The architecture was simple enough to explain in a paragraph. The first prototype was a hand-rolled .service file, a few lines of shell, and a TODO list I lied to myself about. By the second weekend the Pi was rebooting at three in the morning and the speaker was offline by breakfast. The fix was a one-line config change. Finding the line took an hour, because the script was installed from a gist, the logs were going somewhere I did not remember, and there was no doctor to ask.
That kind of failure used to mean I had bitten off too much. Now it usually means something else.
The economics shifted
Coding got faster — not all coding, not the part where you decide what should exist, but the part where prose architectures turn into files. Anyone with a half-decent agent and a free afternoon can produce a working Pi service by dinner. That is genuinely new, and it is genuinely good.
The cleanup did not get faster. The cleanup is still the same ledger it always was: install paths, config preservation, service ownership, log destinations, idempotent setup, update behavior, rollback, uninstall behavior, tests, security notes, and documentation that survives your next enthusiasm cycle. None of that has got cheaper.
So the risk has moved. Before, a half-baked service cost enough effort to write that you sometimes did not. Now it costs almost nothing to write, and exactly the same as before to maintain. The bottleneck is not authorship anymore. It is everything that comes after authorship.
The reward function
This is not a discipline problem. It is a reward-shaping one. The brain likes the clever bridge — the move where Snapcast's network leg meets PipeWire's audio plumbing and a Bluetooth speaker becomes addressable from Home Assistant. The brain does not like writing the uninstall path. Lennart Poettering, in his original 2010 systemd announcement, named exactly this: the boring scaffolding around init scripts had not been rewritten in decades not because it was good, but because nobody who had the energy to invent things had the energy to invent that.
If the boring scaffold has to be hand-written by the same person who wrote the clever bit, the clever bit ships and the scaffold rots. That has been true since computers had operators. The only thing new is that the clever bit now ships much faster, so the rot starts sooner.
The agent does not have a reward function. The agent will write the uninstall path with the same patience it brought to the clever part, if you ask it to. You just have to ask for the right thing, and you have to constrain what it returns.
What Muster is
Muster is a repo scaffold for small Linux service appliances. More precisely: it is a contract you hand to a coding agent. Codex, Claude Code, whichever one you reach for. You give it a prose architecture and the Muster shape. The agent's job stops being “write the clever script” and starts being “produce a repo that passes the Muster shape.”
/etc/<project>/ config
/opt/<project>/releases/<version>/ installed code
/opt/<project>/current active release symlink
systemd/*.service lifecycle
systemd/*.timer scheduled checks and updates
bin/install.sh idempotent installer
bin/update.sh verified update and rollback
bin/doctor.sh health check
make test compliance checks
make package release artifacts
README.md self-certification
muster.yaml machine-readable contractThe point is not elegance. The point is repeatability. Every Muster repo has the same bones. Every install behaves the same. Every uninstall behaves the same. Every update verifies a healthy state before it cuts over the current symlink, and rolls back if the new release fails its doctor. The scheduled timer runs the doctor on its own schedule, so the box tells you when it is unhealthy instead of waiting for you to notice.
None of that is novel. SysVinit had service scripts. systemd has units. dpkg has install hooks. The Twelve-Factor App had configuration discipline in 2011. What is new — what is only new because of the agent — is that following all of it at once for a one-weekend project no longer requires the patience of a release engineer.
A reference: dvd-ingester
The first reference implementation is azide0x37/dvd-ingester, a Muster-built Linux appliance for lawful DVD ingest. The architecture fits on a napkin:
DVD inserted
-> udev marks the device for systemd
-> dvd-rip@.service runs one bounded job
-> dvd-rip-one fingerprints the disc
-> WORK_DIR receives rip output
-> dvd-publish-one publishes atomically to NAS
-> success record appended locally
-> tray ejectsThe interesting part is not that it can rip a disc. A one-off script can do that. The interesting part is that the repo answers the operational questions out loud: udev never runs the long work itself; systemd owns the job lifecycle through a templated unit; config lives in /etc/dvd-ingester/dvd-ingester.env; installed code lives under /opt/dvd-ingester/releases/<version>/; the current symlink moves only after doctor.sh passes; and the updater verifies SHA256 and rolls back if the new release fails on first boot.
make test checks shell syntax, unit-file shape, udev rules, installer idempotence, README compliance, and muster.yaml. make package produces release artifacts and a manifest. The README self-certifies the repo against the Muster contract — a literal table of acceptance rows the agent has to keep green.
That is the whole difference between “the script worked once” and this box is something I can maintain.
The pattern library
Muster the contract is one half of the bargain. Muster the pattern library is the other. The contract says what every repo must look like on disk. The pattern library names the reusable solution atoms a service appliance actually composes from — so the agent is not reinventing “wait for a NAS to be mounted” from scratch every time.
R2 · device-binding
udev hands the device to a templated systemd unit. udev never runs the long work itself.
R5 · capability-mount
Before the job moves a byte, prove the destination capability is actually mounted. findmnt, not faith.
T2C1 · hot-cold-nas-conveyor
Stage work locally, write to a .part on the cold side, atomic-rename when whole. Crashes leave junk only in the staging area.
C2 · persistent-tick
A timer that survives reboots and missed wakeups. The box checks itself on its own clock, not yours.
T2C3 · scheduled-herald
A periodic job that announces health to whoever should care. Failure escapes the box on its own.
C5 · failure-ratchet
Marker files and append-only success records. The box can answer 'what happened the last time?' without forensic equipment.
The dvd-ingester architecture is not its own snowflake. It is a composition of those atoms — a single composed pattern called T2R4.device-triggered-conveyor: a device event starts a bounded ingest job, the job proves its destination capability, stages work locally, and hands output to a hot/cold conveyor on a persistent tick. Once you see the appliance through that lens, the next service does not start at zero. It starts by asking which atoms already describe the shape, and only invents new ones where the existing ones do not fit.
The agent should ask which Muster atoms already describe this before inventing a new shape.
Who this is for
Muster is for the people building useful small services that are too important to leave as loose scripts and too small to justify heavyweight infrastructure. Concretely:
Homelab operators. Raspberry Pi appliance builders. Media-ingest boxes, office automations, local bridges between systems, one-machine data movers, the weird-but- valuable Linux helper that has been quietly running in a closet for two years. And — increasingly — the person who used a coding agent to scaffold a service in an afternoon and intends to actually keep running it.
The diagnostic is simple. If you have a small service running somewhere right now and you cannot immediately answer how do I update this safely, Muster is aimed at you.
What Muster is not
Muster is not Kubernetes for house goblins. It is not Ansible. It is not Nix. It is not a fleet manager, and it is not trying to make a weekend project look like a platform team designed it.
It assumes one box, one service repo, one human owner, systemd available, and a future-self with a fading memory. That is enough structure for a surprisingly large class of real projects, and not a milligram more.
The bargain
The bargain Muster makes with the agent does not look like a script request. It looks like an acceptance contract. Not write a script, but:
Implement this architecture as a Muster-compliant repo.
Use systemd for lifecycle. Preserve config under /etc/<project>/.
Install versioned releases under /opt/<project>/releases/<version>/.
Pass `make test`. Package it with `make package`.
Show me `bin/doctor.sh` output. Update the README certification table.Agentic coding should make small tools more productionizable, not more haunted.
Compound interest for competence
A scaffold is compound interest for competence. Each project gets the same bones. Each example improves the pattern. Each new repo starts less feral than the last, because the last one taught the scaffold something. The Bluetooth audio gateway taught Muster that doctor.sh needs to know about the speaker's MAC address, not just the network leg. dvd-ingester taught the library that capability checks belong before the conveyor, not after the rip. The next service will teach it something else.
I do not want to make tiny tools big. Enterprise-grading a kitchen audio gateway is its own disease — the kind of disease that gets a Helm chart written for a Pi. The goal is smaller and more honest. The obvious path should also be the maintainable path. The weekend project should be safe enough to keep.
Six months from now, the next service I deploy is going to be old code. I would like to recognize it then. I would like the future-me who walks back into that repo to find the installer where it should be, the doctor where it should be, the rollback where it should be, and a README that does not need archaeology.
That is a low bar. It is also exactly the bar most of my own old projects fail to clear. Muster is my attempt to bias my next project — and the one after that, and the one after that — toward the side of the line that does.
Try the scaffold
Muster lives at azide0x37/muster. Clone it, drop your architecture into the prompt, ask the agent to apply Muster, and require make test and make package before calling it done. For a worked example, browse azide0x37/dvd-ingester — what a small, agent-built Linux service looks like when the boring operational work is part of the prompt from the beginning.
