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:
+23
-1
@@ -1,6 +1,7 @@
|
||||
use clap::App;
|
||||
use hbb_common::{
|
||||
allow_err, anyhow::{Context, Result}, get_version_number, log, tokio, ResultType
|
||||
allow_err, anyhow::{Context, Result}, get_version_number, log, tcp::listen_any, tokio,
|
||||
tokio::net::TcpListener, ResultType,
|
||||
};
|
||||
use ini::Ini;
|
||||
use sodiumoxide::crypto::sign;
|
||||
@@ -11,6 +12,27 @@ use std::{
|
||||
time::{Instant, SystemTime},
|
||||
};
|
||||
|
||||
/// Bind a TCP listener for `port`. When `host` is empty (the default for
|
||||
/// every flag that accepts it), falls through to `listen_any` which binds
|
||||
/// the dual-stack `[::]` wildcard. When `host` is set, binds only to that
|
||||
/// address — used by deployments that put nginx/Caddy out front for TLS
|
||||
/// termination on the WS / HTTP ports and want hbbs/hbbr's plain sockets
|
||||
/// reachable only from localhost.
|
||||
pub async fn bind_tcp_listener(host: &str, port: i32) -> ResultType<TcpListener> {
|
||||
if host.is_empty() {
|
||||
return listen_any(port as u16).await;
|
||||
}
|
||||
let host_with_brackets = if host.contains(':') && !host.starts_with('[') {
|
||||
format!("[{}]", host)
|
||||
} else {
|
||||
host.to_string()
|
||||
};
|
||||
let addr: SocketAddr = format!("{}:{}", host_with_brackets, port).parse()?;
|
||||
let l = TcpListener::bind(addr).await?;
|
||||
log::info!("listen on tcp {}", addr);
|
||||
Ok(l)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn get_expired_time() -> Instant {
|
||||
let now = Instant::now();
|
||||
|
||||
Reference in New Issue
Block a user