Default --port to 0 for OS-assigned ephemeral port (ticket 019)

Reads back the actual bound port via listener.local_addr() since
binding to 0 means the requested and real ports differ.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-05 15:06:46 +01:00
co-authored by Claude Sonnet 5
parent 51e577f01e
commit b3701cd2e9
+8 -3
View File
@@ -25,8 +25,9 @@ use settings::Settings;
/// Observability dashboard from terminal output. /// Observability dashboard from terminal output.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Args { struct Args {
/// Port to serve the API and webapp on. /// Port to serve the API and webapp on. Defaults to 0, letting the OS assign
#[arg(long, default_value_t = 8420)] /// an ephemeral free port.
#[arg(long, default_value_t = 0)]
port: u16, port: u16,
/// Directory containing the built webapp (index.html + assets). /// Directory containing the built webapp (index.html + assets).
@@ -91,10 +92,14 @@ async fn main() {
let listener = TcpListener::bind(("0.0.0.0", args.port)) let listener = TcpListener::bind(("0.0.0.0", args.port))
.await .await
.expect("failed to bind listener"); .expect("failed to bind listener");
let bound_port = listener
.local_addr()
.expect("failed to read back bound address")
.port();
eprintln!( eprintln!(
"ottyl serving on http://localhost:{} (reading logs from stdin)", "ottyl serving on http://localhost:{} (reading logs from stdin)",
args.port bound_port
); );
axum::serve(listener, app) axum::serve(listener, app)