A session of iteratively simplifying until it hurts
YAGNI — You Ain’t Gonna Need It.
💬 Rambling
Welp, if you haven’t been living under a rock, AI now cost money yo… WTF is a token… well it’s a magical thing that makes Sam Altman ALOT of money… in theory?
That being said… There are a lot of things I’d rather do with my Saturday than sit and fuck around with Linux services.
I dunno, I think I have a pretty weird idea with what I consider fun. I should probably be cleaning or doing some chores, but I digress… AND… to be honest, I’m pretty far behind with working on my German. I really need to catch up. Das ist nicht gut.
I also spent a good chunk of yesterday trying to fix my Hermes install. That poor thing really got messed up. I mean it doesn’t know how to UN-fuck itself sometimes and you gotta go in and then use a different agent to go fix it, which is really annoying. Like literally I’ve used Crush and Goose to fix OpenCode before… and half the time Crush won’t make system level changes, becuase it’s too careful… normally good. Then I just break out Goose, which is HONKING MAD… 🪿🔪💻 That … thing… will do whatever bat shit instructions you tell it, more or less. IIRC only Ante or Pi might be more pants on head…?
I’m also using handy to write some of this because I think it’s easier for me to try to say what I’m thinking and ramble on versus trying to type it out.
… ANYWAY…
📏 What you came here for
I needed to run an LLM proxy stack on my home server: Bifrost (AI gateway), Headroom (caching proxy), and optionally copilot-api. I wanted proper systemd services — restart on failure, logging, the works.
So threw OpenCode at it. What followed was a masterclass in over-engineering, followed by a Ponytail beatdown.
🏅 Round 1: The “Enterprise” Edition (545 lines)
The AI’s first pass was impressive. Three services, dependency chains, readiness checks with curl loops, PATH detection, wrapper scripts, environment file generation, pre-install dependency caching… it looked like something a cloud provider would ship.
# (545 lines of... this)
wait_for_port() {
local host="$1" port="$2" timeout="${3:-30}"
for i in $(seq 1 "$timeout"); do
if curl -sf "http://${host}:${port}" > /dev/null 2>&1; then
return 0
fi
sleep 1
done
return 1
}
It was correct. It was thorough. It was also fucking overkill for three services on a laptop. Not even on my home server…
🫠 Round 2: The Middle Ground
I pushed back. The AI collapsed it to a single service running llm_proxy.sh with trap + wait so bash stayed alive. Cleaner, but still had a wrapper script.
#!/bin/bash
trap 'exit 0' SIGINT SIGTERM
...
wait
Better, but I asked myself: wait, why do I need a wrapper at all?
💯 Round 3: Three Lines of ExecStart
The final version (189 lines for the installer, and the service definitions themselves are practically nothing):
[Service]
Type=simple
ExecStart=bunx @maximhq/bifrost -port 11434 -host 0.0.0.0
Restart=on-failure
That’s it. No wrapper. No PATH detection. No readiness checks. No env file for the first pass. Each service is just:
| Service | Command |
|---|---|
llm-proxy-bifrost |
bunx @maximhq/bifrost -port 11434 -host 0.0.0.0 |
llm-proxy-headroom |
uvx --from "headroom-ai[all]" headroom proxy ... |
llm-proxy-copilot |
npx copilot-api@latest start (disabled by default) |
Type=simple. Raw ExecStart. Restart=on-failure. DONE.
📖 The Headroom Standalone (the real lesson)
After all that, I realized I wanted Headroom minus Bifrost. So we made a standalone Headroom service with a swappable upstream via .env:
[Service]
Environment=HEADROOM_UPSTREAM_URL=http://127.0.0.1:11434
EnvironmentFile=-/opt/llm-proxy/.env
ExecStart=/bin/sh -c 'exec uvx --from "headroom-ai[all]" headroom proxy --no-telemetry --code-aware --openai-api-url "$HEADROOM_UPSTREAM_URL"'
The one shell wrapper I have, and it’s just to expand $HEADROOM_UPSTREAM_URL from the env file. Switching between local and OpenRouter:
echo 'HEADROOM_UPSTREAM_URL=https://openrouter.ai/api/v1' | sudo tee /opt/llm-proxy/.env
sudo systemctl restart llm-proxy-headroom
🧠 What I learned
Everything I cut had a reason:
- Readiness checks?
Restart=on-failurehandles that. If the port isn’t up, the service errors and retries. systemd already has a loop. - Wrapper scripts? If your command fits in
ExecStart, put it there. One fewer file to maintain. - PATH detection? Systemd has
Environment=PATH=.... Explicit beats magic. - Hard dependencies?
Wants=(soft) overRequires=(hard). If Headroom starts before Bifrost, it’ll fail once and restart fine. - Env file for the first version? Nope. Default baked into
Environment=. Only add the file when you need to override.
The AI kept adding things “just in case.” I kept deleting them. What remained was what I actually needed.
⚖️ Verdict
Less code is better code. The best systemd service is the one you can read in one screen.
4/5 deletions 🪓
… 5/5 w/ rice 🥡
💾 TL;DR
/etc/systemd/system/headroom.service
[Unit]
Description=Headroom Caching Proxy
After=network-online.target
[Service]
Type=simple
User=USENAME_HERE
Environment=PATH=/home/USENAME_HERE/.bun/bin:/home/USENAME_HERE/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=HOME=/home/USENAME_HERE
Environment=HEADROOM_OUTPUT_SHAPER=0
Environment=HEADROOM_UPSTREAM_URL=https://openrouter.ai/api/v1
EnvironmentFile=-/etc/headroom.env
ExecStart=/bin/sh -c 'exec uvx --from "headroom-ai[all]" headroom proxy --no-telemetry --no-code-aware --openai-api-url "$HEADROOM_UPSTREAM_URL"'
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/headroom/headroom.log
StandardError=append:/var/log/headroom/headroom.log
[Install]
WantedBy=multi-user.target
Other posts like this
Reply:
Mastodon Bluesky Email
