//! The standalone server binary: stderr tracing plus //! [`crabidy_server::serve`] on the fixed listen address. The whole stack //! lives in the library so the bundled `cbd` binary can host it too //! (architecture/cbd-bundle.md D1). use clap::Parser; use tracing_subscriber::{prelude::*, EnvFilter}; #[derive(Parser)] #[command(author, version, about)] struct Cli { #[command(subcommand)] command: Option, } #[derive(clap::Subcommand)] enum Command { /// Hash a password for the `[auth]` section of crabidy-server.toml /// (architecture/roles-auth.md). Reads the password as one line /// from stdin and prints the PHC string — nothing else, so output /// can be piped. The password itself is never printed or logged. HashPassword, } #[tokio::main] async fn main() -> Result<(), Box> { let cli = Cli::parse(); if let Some(Command::HashPassword) = cli.command { return hash_password(); } let _log_guard = init_tracing(); crabidy_server::serve(crabidy_server::LISTEN_ADDR.parse()?).await?; Ok(()) } /// Reads one line from stdin and prints its argon2 PHC hash. fn hash_password() -> Result<(), Box> { let mut password = String::new(); std::io::stdin().read_line(&mut password)?; let password = password.trim_end_matches(['\r', '\n']); if password.is_empty() { return Err("empty password".into()); } println!("{}", crabidy_server::auth::hash_password(password)?); Ok(()) } /// Installs the global tracing subscriber. /// /// The filter honors `RUST_LOG`; without it, our own crates log at debug and /// everything else at info. Returns the guard that flushes the non-blocking /// writer on shutdown. fn init_tracing() -> tracing_appender::non_blocking::WorkerGuard { let (non_blocking, guard) = tracing_appender::non_blocking(std::io::stderr()); let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| { EnvFilter::new( "info,crabidy_server=debug,crabidy_core=debug,tidaldy=debug,ytdy=debug,audio_player=debug", ) }); let fmt_layer = tracing_subscriber::fmt::layer() .with_writer(non_blocking) .with_target(true) .with_file(true) .with_line_number(true); // .init() also installs the log-to-tracing bridge for libraries that // use the `log` crate (symphonia, cpal, ...). tracing_subscriber::registry() .with(env_filter) .with(fmt_layer) .init(); guard }