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
|
/// `warning:` — an open LAN renderer (Sonos/Chromecast posture) is the
|
||||||
/// intended default, the Origin shield already guards browsers, and this line
|
/// intended default, the Origin shield already guards browsers, and this line
|
||||||
/// just orients the operator toward the two ways to restrict it further.
|
/// just orients the operator toward the two ways to restrict it further.
|
||||||
/// `addr` is the bound `ip:port`.
|
/// With `[server] token` set the API is already gated, so the line says that
|
||||||
pub fn lan_posture_note(addr: &str) -> String {
|
/// instead of nagging. `addr` is the bound `ip:port`.
|
||||||
format!(
|
pub fn lan_posture_note(addr: &str, token_set: bool) -> String {
|
||||||
"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)"
|
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:
|
/// Version skew — daemon and CLI run different bin semvers (02 §1.6). A warning:
|
||||||
@@ -234,11 +241,12 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[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
|
// 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
|
// by the daemon at boot when the control API is NOT loopback-only and
|
||||||
// test pins the exact wording so it cannot drift from the spec.
|
// no token gates it. This test pins the exact wording so it cannot
|
||||||
let rendered = lan_posture_note("0.0.0.0:6789");
|
// drift from the spec.
|
||||||
|
let rendered = lan_posture_note("0.0.0.0:6789", false);
|
||||||
assert!(
|
assert!(
|
||||||
rendered.contains("control plane listening on 0.0.0.0:6789"),
|
rendered.contains("control plane listening on 0.0.0.0:6789"),
|
||||||
"{rendered}"
|
"{rendered}"
|
||||||
@@ -253,4 +261,18 @@ mod tests {
|
|||||||
"{rendered}"
|
"{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/
|
// FB6: the default bind is now 0.0.0.0 — LAN-first posture (Sonos/
|
||||||
// Chromecast parity), not a misconfiguration. One INFO line, not a
|
// Chromecast parity), not a misconfiguration. One INFO line, not a
|
||||||
// stderr warning; loopback binds stay silent.
|
// 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.
|
// 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.
|
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
|
## OpenRC and runit
|
||||||
|
|
||||||
Do not reuse the systemd unit on a non-systemd host. `qbzd` generates a
|
Do not reuse the systemd unit on a non-systemd host. `qbzd` generates a
|
||||||
|
|||||||
Reference in new issue
Block a user