docs(qbzd): document the LAN-first bind and the token in the standalone README; posture line stops nagging gated setups
The public README never mentioned that the control API binds 0.0.0.0 by default nor how to restrict it; the boot line also told users who had set [server] token that anyone could control playback. cc
This commit is contained in:
3 files changed
+61
-10
No files matched your search
@@ -136,11 +136,18 @@ pub fn foreign_qbzd(addr: &str) -> String {
|
||||
/// `warning:` — an open LAN renderer (Sonos/Chromecast posture) is the
|
||||
/// intended default, the Origin shield already guards browsers, and this line
|
||||
/// just orients the operator toward the two ways to restrict it further.
|
||||
/// `addr` is the bound `ip:port`.
|
||||
pub fn lan_posture_note(addr: &str) -> String {
|
||||
format!(
|
||||
"control plane listening on {addr} — anyone on your network can control playback (set [server] bind = \"127.0.0.1\" or [server] token in qbzd.toml to restrict)"
|
||||
)
|
||||
/// With `[server] token` set the API is already gated, so the line says that
|
||||
/// instead of nagging. `addr` is the bound `ip:port`.
|
||||
pub fn lan_posture_note(addr: &str, token_set: bool) -> String {
|
||||
if token_set {
|
||||
format!(
|
||||
"control plane listening on {addr} — LAN clients must send the [server] token (Authorization: Bearer)"
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"control plane listening on {addr} — anyone on your network can control playback (set [server] bind = \"127.0.0.1\" or [server] token in qbzd.toml to restrict)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Version skew — daemon and CLI run different bin semvers (02 §1.6). A warning:
|
||||
@@ -234,11 +241,12 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lan_posture_note_renders_the_verbatim_copy() {
|
||||
fn lan_posture_note_renders_the_verbatim_copy_when_the_api_is_open() {
|
||||
// FB6 (successor to the old LAN-exposure warning) — one INFO line logged
|
||||
// by the daemon at boot when the control API is NOT loopback-only. This
|
||||
// test pins the exact wording so it cannot drift from the spec.
|
||||
let rendered = lan_posture_note("0.0.0.0:6789");
|
||||
// by the daemon at boot when the control API is NOT loopback-only and
|
||||
// no token gates it. This test pins the exact wording so it cannot
|
||||
// drift from the spec.
|
||||
let rendered = lan_posture_note("0.0.0.0:6789", false);
|
||||
assert!(
|
||||
rendered.contains("control plane listening on 0.0.0.0:6789"),
|
||||
"{rendered}"
|
||||
@@ -253,4 +261,18 @@ mod tests {
|
||||
"{rendered}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lan_posture_note_with_a_token_does_not_nag() {
|
||||
let rendered = lan_posture_note("0.0.0.0:6789", true);
|
||||
assert!(
|
||||
rendered.contains("control plane listening on 0.0.0.0:6789"),
|
||||
"{rendered}"
|
||||
);
|
||||
assert!(rendered.contains("[server] token"), "{rendered}");
|
||||
assert!(
|
||||
!rendered.contains("anyone on your network"),
|
||||
"a gated API must not be described as open: {rendered}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,15 @@ pub async fn run(roots: ProfileRoots, cfg: QbzdConfig, warns: Vec<String>, orbit
|
||||
// FB6: the default bind is now 0.0.0.0 — LAN-first posture (Sonos/
|
||||
// Chromecast parity), not a misconfiguration. One INFO line, not a
|
||||
// stderr warning; loopback binds stay silent.
|
||||
log::info!("{}", crate::cli::copy::lan_posture_note(&bind_addr.to_string()));
|
||||
let token_set = cfg
|
||||
.server
|
||||
.token
|
||||
.as_deref()
|
||||
.is_some_and(|t| !t.trim().is_empty());
|
||||
log::info!(
|
||||
"{}",
|
||||
crate::cli::copy::lan_posture_note(&bind_addr.to_string(), token_set)
|
||||
);
|
||||
}
|
||||
|
||||
// 6.-9. compose stores + runtime + restore credentials + restore session.
|
||||
|
||||
@@ -82,6 +82,27 @@ budgets exclude active streaming buffers, decoders and offline downloads. The
|
||||
policy applies live without reopening the output device.
|
||||
|
||||
|
||||
## Network access
|
||||
|
||||
By default `qbzd run` listens on `0.0.0.0:8182`: any device on your network
|
||||
can control playback, the queue and your playlists, the same way a Sonos or
|
||||
Chromecast renderer is open on the LAN. Browsers are blocked by an Origin
|
||||
check; other programs are not. The daemon logs one line about this at boot.
|
||||
|
||||
To restrict it, edit `~/.config/qbzd/qbzd.toml`:
|
||||
|
||||
```toml
|
||||
[server]
|
||||
bind = "127.0.0.1" # local clients only
|
||||
# or keep the LAN bind and require a token on every request:
|
||||
token = "choose-a-long-random-string"
|
||||
```
|
||||
|
||||
With a token set, clients send `Authorization: Bearer <token>`; the `qbzd`
|
||||
CLI on the same machine picks it up from `qbzd.toml` automatically (or from
|
||||
`QBZD_TOKEN`). `qbzd setup` has the same field on its Network screen
|
||||
("Access token").
|
||||
|
||||
## OpenRC and runit
|
||||
|
||||
Do not reuse the systemd unit on a non-systemd host. `qbzd` generates a
|
||||
|
||||
Reference in new issue
Block a user