src/server/main.rs
Ref: Size: 2.6 KiB
use std::path::PathBuf;
use clap::Parser;
use tracing::info;
mod config;
mod http;
mod repos;
mod ssh;
#[derive(Parser)]
#[command(name = "git-collab-server", about = "Minimal git hosting server")]
struct Args {
#[arg(short, long)]
config: PathBuf,
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let args = Args::parse();
let config = match config::ServerConfig::from_file(&args.config) {
Ok(c) => c,
Err(e) => {
eprintln!("Failed to load config from {:?}: {}", args.config, e);
std::process::exit(1);
}
};
if !config.repos_dir.exists() {
eprintln!("repos_dir {:?} does not exist", config.repos_dir);
std::process::exit(1);
}
let host_key_path = config.repos_dir.join(".server").join("host_key");
let host_key = match ssh::load_or_generate_host_key(&host_key_path) {
Ok(k) => k,
Err(e) => {
eprintln!("Failed to load/generate SSH host key: {}", e);
std::process::exit(1);
}
};
let fingerprint = match host_key.clone_public_key() {
Ok(pub_key) => pub_key.fingerprint(),
Err(e) => {
eprintln!("Failed to get host key fingerprint: {}", e);
std::process::exit(1);
}
};
info!("HTTP listening on {}", config.http_bind);
info!("SSH listening on {}", config.ssh_bind);
info!("Repos dir: {:?}", config.repos_dir);
info!("Site title: {}", config.site_title);
info!("SSH host key fingerprint: SHA256:{}", fingerprint);
let app_state = http::AppState {
repos_dir: config.repos_dir.clone(),
site_title: config.site_title.clone(),
};
let router = http::router(app_state);
let ssh_config = ssh::session::SshServerConfig {
repos_dir: config.repos_dir.clone(),
authorized_keys_path: config.authorized_keys.clone(),
};
let http_bind = config.http_bind;
let ssh_bind = config.ssh_bind;
let http_listener = match tokio::net::TcpListener::bind(http_bind).await {
Ok(l) => l,
Err(e) => {
eprintln!("Failed to bind HTTP on {}: {}", http_bind, e);
std::process::exit(1);
}
};
let http_fut = axum::serve(http_listener, router);
let ssh_fut = ssh::serve(ssh_bind, host_key, ssh_config);
tokio::select! {
result = http_fut => {
if let Err(e) = result {
eprintln!("HTTP server error: {}", e);
}
}
result = ssh_fut => {
if let Err(e) = result {
eprintln!("SSH server error: {}", e);
}
}
}
}