diff --git a/crates/zgrok-edge/Cargo.toml b/crates/zgrok-edge/Cargo.toml index c0384d4..fa1d881 100644 --- a/crates/zgrok-edge/Cargo.toml +++ b/crates/zgrok-edge/Cargo.toml @@ -13,6 +13,7 @@ path = "src/main.rs" [dependencies] zgrok-protocol = { path = "../zgrok-protocol" } +clap = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] } tokio-util = { workspace = true } tokio-rustls = { workspace = true } diff --git a/crates/zgrok-edge/src/main.rs b/crates/zgrok-edge/src/main.rs index dfe82e1..14e5a05 100644 --- a/crates/zgrok-edge/src/main.rs +++ b/crates/zgrok-edge/src/main.rs @@ -1,25 +1,60 @@ -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; use anyhow::{Context, Result}; +use clap::Parser; use zgrok_edge::{EdgeServer, TlsConfig}; -fn main() -> Result<()> { - let https_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 443); - let http_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 80); +#[derive(Parser, Debug)] +#[command(name = "zgrok-edge")] +#[command(about = "Edge/gateway server for zgrok tunneling service")] +#[command(version)] +struct Args { + /// HTTPS listen port + #[arg(long, default_value = "443")] + https_port: u16, + + /// HTTP redirect listen port (0 to disable) + #[arg(long, default_value = "80")] + http_port: u16, + + /// Listen address + #[arg(long, default_value = "0.0.0.0")] + listen: IpAddr, - let cert_path = std::env::var("ZGROK_CERT_PATH") - .map(PathBuf::from) - .unwrap_or_else(|_| PathBuf::from("/etc/zgrok/cert.pem")); + /// Path to TLS certificate file (PEM format) + #[arg(long, env = "ZGROK_CERT_PATH", default_value = "/etc/zgrok/cert.pem")] + cert: PathBuf, - let key_path = std::env::var("ZGROK_KEY_PATH") - .map(PathBuf::from) - .unwrap_or_else(|_| PathBuf::from("/etc/zgrok/key.pem")); + /// Path to TLS private key file (PEM format) + #[arg(long, env = "ZGROK_KEY_PATH", default_value = "/etc/zgrok/key.pem")] + key: PathBuf, - let tls_config = TlsConfig::new(cert_path, key_path); + /// Base domain for tunnel subdomains + #[arg(long, default_value = "zgrok.io")] + domain: String, - let server_config = zgrok_edge::server::EdgeServerConfig::new(https_addr, tls_config) - .with_http_redirect(http_addr); + /// Control plane URL + #[arg(long, env = "ZGROK_CONTROL_URL")] + control_url: Option, + + /// Enable verbose logging + #[arg(short, long, action = clap::ArgAction::Count)] + verbose: u8, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + let https_addr = SocketAddr::new(args.listen, args.https_port); + let tls_config = TlsConfig::new(args.cert, args.key); + + let mut server_config = zgrok_edge::server::EdgeServerConfig::new(https_addr, tls_config); + + if args.http_port > 0 { + let http_addr = SocketAddr::new(args.listen, args.http_port); + server_config = server_config.with_http_redirect(http_addr); + } let server = EdgeServer::new(server_config).context("Failed to create edge server")?; @@ -27,7 +62,10 @@ fn main() -> Result<()> { rt.block_on(async { println!("Starting zgrok edge server..."); println!("HTTPS: {}", https_addr); - println!("HTTP redirect: {}", http_addr); + if args.http_port > 0 { + println!("HTTP redirect: {}:{}", args.listen, args.http_port); + } + println!("Domain: {}", args.domain); if let Err(e) = server.run().await { eprintln!("Server error: {}", e);