feat(umbrel): add headless seeder daemon, Axum web server, and Umbrel packaging - #2
feat(umbrel): add headless seeder daemon, Axum web server, and Umbrel packaging#2borocode wants to merge 23 commits into
Conversation
… app packaging - Add napstr-daemon headless entrypoint running 24/7 on port 30421 - Add Axum REST and WebSocket API router mirroring all Tauri commands - Add HTML5 WebAudio in-browser audio streaming with HTTP Range seek support - Add universal frontend API client bridge supporting desktop and web - Decouple EventEmitter abstraction for Tauri and Tokio broadcast channels - Add umbrel-app.yml, docker-compose.yml, and multi-stage Dockerfile.umbrel
…libdbus runtime dependency
Daemon is built from src-tauri and links against webkit2gtk/gtk3/soup3/ javascriptcore/wayland even in headless mode. Runtime stage only had libasound2+libdbus -> 13 'not found' libs on arm64 (libwayland-client first). Verified via QEMU arm64 ldd against the exact GHCR image: 0 missing after adding libwebkit2gtk-4.1-0, libgtk-3-0, libsoup-3.0-0, libjavascriptcoregtk-4.1-0.
setup-buildx-action has no 'builder' input - the previous config silently fell back to whichever builder was last selected on the runner host (docker driver), which cannot do linux/amd64+linux/arm64 multi-platform. Now: ensure mybuilder exists (docker-container driver), bootstrap it, and set it as the default for the job. No more ambient host-state dependency.
setup-buildx-action create hit 'existing instance but no append mode' and did not switch the active builder; build still ran on docker driver. build-push-action accepts a per-invocation 'builder' input - targeting mybuilder directly, no global-state switching required.
Self-hosted Windows runner is a minefield for docker builds: PowerShell run-steps mangle /dev/null into C:\dev\null, builder selection depends on fragile host state, and the docker driver cannot multi-platform build. ubuntu-latest gives a clean linux environment with working containerd store + native buildx multi-platform support. GHA layer caching added to offset slower hosted hardware.
- Merge upstream/main (0.1.4): daemon core rewrite (scan_lock/scan_cancel, progress events), player + network fixes, 3000-track indexing fix. - Add headless wrappers (index_path_headless, start_folder_watcher_headless) so the Umbrel seeder daemon runs without a Tauri AppHandle. - Re-point server/daemon to queue_catalogue_publish + re-expose IndexReport as pub for the web layer. - Bump umbrel-app.yml version 0.1.0 -> 0.1.4. - Verified: cargo check passes for both napstr-daemon and tauri desktop.
|
Nice work — the headless mode is the piece that makes Napstr an always-on thing rather than a desktop session, and the Axum server with range requests is doing more heavy lifting than the PR description lets on. Context for why I'm commenting: I built an independent Napstr client from Two things I ran into that may matter for this PR specifically: Two of the six default relays are unreachable. The session onion is the weak point for an always-on seeder. The reference flow creates a fresh Which brings me to a question rather than a proposal. This daemon already serves HTTP with 206 range requests from an indexed, hash-addressed library — which is most of a Blossom BUD-01 endpoint ( The route I've been testing for that second path is FIPS, which gives each node an authenticated Being explicit about what I have and haven't proven, because it matters: interoperation with the public swarm is verified in both directions, including serving my own file over a real v3 onion and fetching it back. The extension field is verified additive. I have not yet moved a single byte over the mesh transport itself — that leg is blocked on a firewall rule on my side, not on anything in the design — and I have not run Blossom over it either. So this is a direction with partial evidence, not a finished thing. Would a second transport be interesting to you at all, or is Tor-only a deliberate boundary for Napstr? Happy to keep it to myself if so — I'd rather ask before building toward something you don't want. If it is interesting, the smallest useful proof is probably one seeder, one downloader, one encrypted file, verified over both routes from the same offer. |
Summary
This PR adds support for running Napstr as a 24/7 headless sovereign audio seeder and web player for Umbrel / UmbrelOS (and any headless server/docker environment).
Key Additions
Headless Daemon (
napstr-daemon):30421./music) without needing a desktop window open.Universal Dual-Mode Client:
$lib/api.tsbridge that automatically detects whether Napstr is running in desktop Tauri or inside a web browser.$lib/webAudio.ts) with HTTP Range request (206 Partial Content) support.Decoupled Event Layer:
EventEmittertrait implemented for both Tauri IPC (TauriEmitter) and Tokio broadcast channels (BroadcasterEmitter).Umbrel App Store Packaging:
umbrel-app.ymlmanifest,docker-compose.yml, and multi-stageDockerfile.umbrel.Verification
npm run buildpasses with 0 errors (static Svelte 5 SPA).cargo build --bin napstr-daemoncompiles and links cleanly.