feat(deploy): bind-address flags for browser-facing ports + nginx docs
By default hbbs and hbbr bind every port to the wildcard, which collides with operators wanting to put nginx/Caddy in front of the dashboard (443) and the two browser-facing WebSocket ports (21118 rendezvous, 21119 relay) for TLS termination. Operators reported having to choose between exposing hbbs directly (no TLS for `wss://`, breaks browsers since the page is HTTPS) or moving the daemon to a different port. New flags: - hbbs `--http-listen=<HOST>` pins the HTTP API + dashboard port. - hbbs `--ws-listen=<HOST>` pins the WS rendezvous port (port + 2). - hbbr `--ws-listen=<HOST>` pins the WS relay port (port + 2). All default to the wildcard (current behaviour). Set to `127.0.0.1` to free up the corresponding public port for nginx. The plain TCP/UDP ports used by desktop clients (21115 NAT test, 21116 rendezvous, 21117 relay) intentionally stay on the wildcard — desktop clients bring their own framing + secretbox encryption and don't go through nginx. Implementation: a small `bind_tcp_listener(host, port)` helper in common.rs that falls through to the existing `listen_any` when host is empty, otherwise binds explicitly. Reused for both ws_port (rendezvous + relay) and the http_port; the latter just builds a `SocketAddr` inline since axum::serve takes one. Documentation: new "TLS deployment with nginx" section in docs/CONFIGURATION.md covering the port plan, the bind flags, full example nginx vhost config (three server blocks: 443 dashboard, 21118 WSS rendezvous, 21119 WSS relay) with the WebSocket Upgrade plumbing and bump-up timeouts that long sessions need, plus the firewall list and the four common failure modes (SSL protocol error, connection refused, 502, hung 200 instead of 101). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-2
@@ -46,7 +46,7 @@ const BLACKLIST_FILE: &str = "blacklist.txt";
|
||||
const BLOCKLIST_FILE: &str = "blocklist.txt";
|
||||
|
||||
#[tokio::main(flavor = "multi_thread")]
|
||||
pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
||||
pub async fn start(port: &str, key: &str, ws_listen: &str) -> ResultType<()> {
|
||||
let key = get_server_sk(key);
|
||||
if let Ok(mut file) = std::fs::File::open(BLACKLIST_FILE) {
|
||||
let mut contents = String::new();
|
||||
@@ -82,10 +82,21 @@ pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
||||
log::info!("Listening on tcp :{}", port);
|
||||
let port2 = port + 2;
|
||||
log::info!("Listening on websocket :{}", port2);
|
||||
// The WS port (21119 default) is the only browser-facing endpoint at
|
||||
// hbbr — operators put nginx/Caddy in front of it for TLS. Allow
|
||||
// pinning it to localhost so the reverse proxy can claim the public
|
||||
// port without colliding. The plain TCP relay port (21117) is for
|
||||
// desktop clients and stays on the wildcard.
|
||||
let ws_listen = ws_listen.to_owned();
|
||||
let main_task = async move {
|
||||
loop {
|
||||
log::info!("Start");
|
||||
io_loop(listen_any(port).await?, listen_any(port2).await?, &key).await;
|
||||
io_loop(
|
||||
listen_any(port).await?,
|
||||
crate::common::bind_tcp_listener(&ws_listen, port2 as i32).await?,
|
||||
&key,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
let listen_signal = crate::common::listen_signal();
|
||||
|
||||
Reference in New Issue
Block a user