use crate::http::response::response_interceptor; use anyhow::Result; use axum::middleware::from_fn; use bollard::Docker; use clap::Parser; use std::{net::SocketAddr, path::PathBuf}; mod http; mod nix; mod node; mod route; /// GitOps+WebUI for arion-based stacks #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// Path to root of stacks #[arg(short = 'd', long = "stack-dir", env = "STAX_DIR")] stack_dir: PathBuf, /// Address:port to bind #[arg(short, long, default_value = "0.0.0.0:3000", env = "STAX_BIND")] bind: SocketAddr, /// Path to arion #[arg( long = "arion-bin", env = "STAX_ARION_BIN", default_value = "/run/current-system/sw/bin/arion" )] arion_binary: PathBuf, } #[derive(Clone)] pub struct AppState { pub stack_dir: PathBuf, pub arion_bin: PathBuf, pub docker: Docker, } #[tokio::main] async fn main() -> Result<()> { // Initialize logging and env _ = dotenvy::dotenv(); tracing_subscriber::fmt::init(); // Try to connect to docker server let docker = Docker::connect_with_local_defaults()?; // Ping to make sure it works let version = docker.version().await?; tracing::info!("docker version: {}", version.version.unwrap()); // Parse args let args = Args::parse(); tracing::info!("listening on {}", &args.bind); let state = AppState { stack_dir: args.stack_dir, arion_bin: args.arion_binary, docker, }; let app = route::router() .with_state(state) .layer(from_fn(response_interceptor)); axum::Server::bind(&args.bind) .serve(app.into_make_service()) .await?; Ok(()) }