diff --git a/virtweb_backend/Cargo.lock b/virtweb_backend/Cargo.lock index a984526..4cadb48 100644 --- a/virtweb_backend/Cargo.lock +++ b/virtweb_backend/Cargo.lock @@ -918,6 +918,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "either" version = "1.9.0" @@ -2644,6 +2650,7 @@ dependencies = [ "anyhow", "bytes", "clap", + "dotenvy", "env_logger", "futures", "futures-util", diff --git a/virtweb_backend/Cargo.toml b/virtweb_backend/Cargo.toml index 2d096bf..03746f2 100644 --- a/virtweb_backend/Cargo.toml +++ b/virtweb_backend/Cargo.toml @@ -43,3 +43,4 @@ ipnetwork = "0.20.0" num = "0.4.1" rust-embed = { version = "8.1.0" } mime_guess = "2.0.4" +dotenvy = "0.15.7" \ No newline at end of file diff --git a/virtweb_backend/src/app_config.rs b/virtweb_backend/src/app_config.rs index 2afb8fa..4ce9bea 100644 --- a/virtweb_backend/src/app_config.rs +++ b/virtweb_backend/src/app_config.rs @@ -8,6 +8,10 @@ use std::str::FromStr; #[derive(Parser, Debug, Clone)] #[clap(author, version, about, long_about = None)] pub struct AppConfig { + /// Read arguments from env file + #[clap(short, long, env)] + pub config: Option, + /// Listen address #[clap(short, long, env, default_value = "0.0.0.0:8000")] pub listen_address: String, @@ -20,7 +24,7 @@ pub struct AppConfig { /// /// Warning! These origins won't be usable for OpenID authentication, /// only for local auth - #[clap(long, env)] + #[clap(short = 'o', long, env)] pub additional_origins: Vec, /// Proxy IP, might end with a star "*" @@ -28,7 +32,7 @@ pub struct AppConfig { pub proxy_ip: Option, /// Secret key, used to sign some resources. Must be randomly generated - #[clap(long, env, default_value = "")] + #[clap(short = 'S', long, env, default_value = "")] secret: String, /// Specify whether the cookie should be transmitted only over secure connections @@ -36,11 +40,11 @@ pub struct AppConfig { pub cookie_secure: bool, /// Auth username - #[arg(long, env, default_value = "admin")] + #[arg(short = 'u', long, env, default_value = "admin")] pub auth_username: String, /// Auth password - #[arg(long, env, default_value = "admin")] + #[arg(short = 'P', long, env, default_value = "admin")] pub auth_password: String, /// Disable authentication WARNING! THIS IS UNSECURE, it was designed only for development @@ -88,16 +92,16 @@ pub struct AppConfig { /// /// Warning! This directory MUST be changed if `/tmp` is not in the same disk as the storage /// directory! - #[arg(long, env, default_value = "/tmp")] + #[arg(short, long, env, default_value = "/tmp")] pub temp_dir: String, /// Hypervisor URI. If not specified, "" will be used instead - #[arg(long, env)] + #[arg(short = 'H', long, env)] pub hypervisor_uri: Option, /// Trusted network. If set, a client from a different will not be able to perform request other /// than those with GET verb (aside for login) - #[arg(long, env)] + #[arg(short = 'T', long, env)] pub trusted_network: Vec, } @@ -108,6 +112,21 @@ lazy_static::lazy_static! { } impl AppConfig { + /// Parse environment variables from file, if requedst + pub fn parse_env_file() -> anyhow::Result<()> { + if let Some(c) = Self::parse().config { + log::info!("Load additional environment variables from {c}"); + let conf_file = Path::new(&c); + + if !conf_file.is_file() { + panic!("Specified configuration is not a file!"); + } + dotenvy::from_path(conf_file)?; + } + + Ok(()) + } + /// Get parsed command line arguments pub fn get() -> &'static AppConfig { &ARGS @@ -227,3 +246,14 @@ pub struct OIDCProvider<'a> { #[serde(skip_serializing)] pub configuration_url: &'a str, } + +#[cfg(test)] +mod test { + use crate::app_config::AppConfig; + + #[test] + fn verify_cli() { + use clap::CommandFactory; + AppConfig::command().debug_assert() + } +} diff --git a/virtweb_backend/src/main.rs b/virtweb_backend/src/main.rs index 401f0d4..00522ff 100644 --- a/virtweb_backend/src/main.rs +++ b/virtweb_backend/src/main.rs @@ -33,6 +33,9 @@ use virtweb_backend::utils::files_utils; async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + // Load additional config from file, if requested + AppConfig::parse_env_file().unwrap(); + log::debug!("Create required directory, if missing"); files_utils::create_directory_if_missing(AppConfig::get().iso_storage_path()).unwrap(); files_utils::create_directory_if_missing(AppConfig::get().vnc_sockets_path()).unwrap();