Headless Rust gRPC daemon to drive Bluetooth, HLS/DASH playback, and snapcast/shairport-sync/squeezelite on Raspberry Pi audio rigs.
0

Configure Feed

Select the types of activity you want to include in your feed.

Default server bind to 0.0.0.0:50151

127.0.0.1 default left the daemon unreachable from the LAN, which is
the common deployment shape (Pi audio appliance + remote CLI). Flip the
default to all-interfaces and lean on the bearer token (random fallback)
for the no-zerod.toml case. Document the security trade-off in the
Security section and tell users to set bearer_token explicitly when
exposing on a network they don't fully trust.

+27 -14
+15 -9
README.md
··· 87 87 88 88 ```toml 89 89 [server] 90 - bind = "127.0.0.1:50151" 91 - bearer_token = "" # empty → ZEROD_BEARER_TOKEN env → random 90 + bind = "0.0.0.0:50151" # all interfaces; use "127.0.0.1:50151" for loopback only 91 + bearer_token = "" # empty → ZEROD_BEARER_TOKEN env → random 92 92 93 93 [systemd] 94 94 units = ["snapserver.service", "shairport-sync.service"] 95 95 96 96 [[configs]] 97 - key = "snapserver" 97 + key = "snapserver" 98 98 path = "/etc/snapserver.conf" 99 99 unit = "snapserver.service" 100 100 ``` 101 101 102 - If no `zerod.toml` is found, `zerod` runs with defaults (loopback, no 103 - systemd allowlist, no managed configs) and emits a warning. 102 + If no `zerod.toml` is found, `zerod` runs with defaults (bind 103 + `0.0.0.0:50151`, no systemd allowlist, no managed configs) and emits a 104 + warning. 104 105 105 106 ## Usage 106 107 ··· 172 173 173 174 ## Security 174 175 175 - There is intentionally no TLS in v1. The default bind is `127.0.0.1`. If you 176 - need to drive `zerod` across a network, put it behind WireGuard / Tailscale / 177 - SSH; do not expose `:50151` directly. The bearer token is the only line of 178 - defence against requests that reach the listening socket. 176 + There is intentionally no TLS in v1. The default bind is `0.0.0.0:50151` 177 + (all interfaces) so the daemon is reachable from your LAN out of the box — 178 + which means the bearer token is the only line of defence against any host on 179 + that network. Always set `bearer_token` in `zerod.toml` (or 180 + `ZEROD_BEARER_TOKEN`) instead of relying on the random one logged at 181 + startup, especially when running unattended. For cross-internet access put 182 + `zerod` behind WireGuard / Tailscale / an SSH tunnel rather than punching 183 + the port through your router. If you only ever drive `zerod` locally, flip 184 + the bind back to `127.0.0.1:50151`. 179 185 180 186 Systemd actions and config writes are gated by the allowlist in `zerod.toml` 181 187 — `zerod` cannot be turned into a generic remote `systemctl`.
+6 -3
crates/server/src/settings.rs
··· 2 2 //! 3 3 //! Example: 4 4 //! [server] 5 - //! bind = "127.0.0.1:50151" 5 + //! bind = "0.0.0.0:50151" 6 6 //! bearer_token = "" 7 7 //! 8 8 //! [systemd] ··· 44 44 } 45 45 46 46 fn default_bind() -> String { 47 - "127.0.0.1:50151".to_string() 47 + // Bind on all interfaces by default so the daemon is reachable from the 48 + // LAN out of the box — bearer-token auth (random fallback) covers the 49 + // "no zerod.toml" case. Override to "127.0.0.1:50151" for loopback only. 50 + "0.0.0.0:50151".to_string() 48 51 } 49 52 50 53 impl Default for ServerSettings { ··· 87 90 None => default_search_paths().into_iter().find(|p| p.exists()), 88 91 }; 89 92 let Some(p) = resolved else { 90 - tracing::warn!("zerod.toml not found; using defaults (loopback, no allowlist, no configs)"); 93 + tracing::warn!("zerod.toml not found; using defaults (bind 0.0.0.0:50151, no allowlist, no configs)"); 91 94 return Ok(Settings::default()); 92 95 }; 93 96 let body = std::fs::read_to_string(&p)
+6 -2
zerod.toml.example
··· 1 1 # zerod.toml — copy to ./zerod.toml, $XDG_CONFIG_HOME/zerod/zerod.toml, or /etc/zerod.toml 2 2 3 3 [server] 4 - bind = "127.0.0.1:50151" 4 + # All-interfaces by default so the daemon is reachable from the LAN. 5 + # Set to "127.0.0.1:50151" if you only want loopback (and plan to drive 6 + # zerod over SSH / WireGuard / Tailscale). 7 + bind = "0.0.0.0:50151" 5 8 # Leave empty to fall back to the ZEROD_BEARER_TOKEN env var, otherwise a 6 - # random token is generated and logged at startup. 9 + # random token is generated and logged at startup. Strongly recommended to 10 + # set this explicitly when bind is non-loopback. 7 11 bearer_token = "" 8 12 9 13 [systemd]