Add node.log_level config, remove RUST_LOG from service files

Add log_level field to NodeConfig (case-insensitive, default: info).
The daemon now loads config before initializing tracing so the
configured level takes effect. RUST_LOG env var still overrides if
set.

Remove hardcoded Environment=RUST_LOG=info from systemd units and
OpenWrt procd init script — these prevented config-driven log levels
from working.
This commit is contained in:
Johnathan Corgan
2026-03-25 15:34:47 +00:00
parent d801fd0052
commit cb6f263a1d
5 changed files with 43 additions and 34 deletions
-3
View File
@@ -9,9 +9,6 @@ ExecStart=/usr/bin/fips --config /etc/fips/fips.yaml
Restart=on-failure
RestartSec=5
# Logging: RUST_LOG controls verbosity.
Environment=RUST_LOG=info
# Control socket directory (/run/fips/).
# Group-accessible so 'fips' group members can use fipsctl/fipstop.
RuntimeDirectory=fips
@@ -14,7 +14,6 @@ start_service() {
procd_open_instance
procd_set_param command "$PROG" --config "$CONFIG"
procd_set_param env RUST_LOG=info
# Respawn: restart after 5 s, give up after 5 consecutive failures within
# a 3600 s window, then reset the failure counter and try again.
procd_set_param respawn 3600 5 5
-3
View File
@@ -9,9 +9,6 @@ ExecStart=/usr/local/bin/fips --config /etc/fips/fips.yaml
Restart=on-failure
RestartSec=5
# Logging: RUST_LOG controls verbosity.
Environment=RUST_LOG=info
# Control socket directory (/run/fips/).
# Group-accessible so 'fips' group members can use fipsctl/fipstop.
RuntimeDirectory=fips
+26 -27
View File
@@ -7,7 +7,7 @@ use fips::config::{resolve_identity, IdentitySource};
use fips::version;
use fips::{Config, Node};
use std::path::PathBuf;
use tracing::{debug, error, info, warn, Level};
use tracing::{debug, error, info, warn};
use tracing_subscriber::{fmt, EnvFilter};
/// FIPS mesh network daemon
@@ -26,9 +26,32 @@ struct Args {
#[tokio::main(flavor = "current_thread")]
async fn main() {
// Initialize logging
let args = Args::parse();
// Load configuration before initializing logging so we can use
// the config's log_level as the tracing filter default.
let (config, loaded_paths) = if let Some(config_path) = &args.config {
match Config::load_file(config_path) {
Ok(config) => (config, vec![config_path.clone()]),
Err(e) => {
eprintln!("Failed to load configuration from {}: {}", config_path.display(), e);
std::process::exit(1);
}
}
} else {
match Config::load() {
Ok(result) => result,
Err(e) => {
eprintln!("Failed to load configuration: {}", e);
std::process::exit(1);
}
}
};
// Initialize logging: RUST_LOG env var overrides config if set
let log_level = config.node.log_level();
let filter = EnvFilter::builder()
.with_default_directive(Level::INFO.into())
.with_default_directive(log_level.into())
.from_env_lossy();
fmt()
@@ -36,32 +59,8 @@ async fn main() {
.with_target(true)
.init();
let args = Args::parse();
info!("FIPS {} starting", version::short_version());
// Load configuration
debug!("Loading configuration");
let (config, loaded_paths) = if let Some(config_path) = &args.config {
// Explicit config file specified - load only that file
match Config::load_file(config_path) {
Ok(config) => (config, vec![config_path.clone()]),
Err(e) => {
error!("Failed to load configuration from {}: {}", config_path.display(), e);
std::process::exit(1);
}
}
} else {
// Use default search paths
match Config::load() {
Ok(result) => result,
Err(e) => {
error!("Failed to load configuration: {}", e);
std::process::exit(1);
}
}
};
if loaded_paths.is_empty() {
info!("No config files found, using defaults");
} else {
+17
View File
@@ -612,6 +612,11 @@ pub struct NodeConfig {
/// Rekey / session rekeying (`node.rekey.*`).
#[serde(default)]
pub rekey: RekeyConfig,
/// Log level (`node.log_level`). Case-insensitive.
/// Valid values: trace, debug, info, warn, error. Default: info.
#[serde(default)]
pub log_level: Option<String>,
}
impl Default for NodeConfig {
@@ -637,11 +642,23 @@ impl Default for NodeConfig {
session_mmp: SessionMmpConfig::default(),
ecn: EcnConfig::default(),
rekey: RekeyConfig::default(),
log_level: None,
}
}
}
impl NodeConfig {
/// Get the log level as a tracing Level. Default: INFO.
pub fn log_level(&self) -> tracing::Level {
match self.log_level.as_deref().map(|s| s.to_lowercase()).as_deref() {
Some("trace") => tracing::Level::TRACE,
Some("debug") => tracing::Level::DEBUG,
Some("warn") | Some("warning") => tracing::Level::WARN,
Some("error") => tracing::Level::ERROR,
_ => tracing::Level::INFO,
}
}
fn default_tick_interval_secs() -> u64 { 1 }
fn default_base_rtt_ms() -> u64 { 100 }
fn default_heartbeat_interval_secs() -> u64 { 10 }