diff --git a/site/dashboard.html b/site/dashboard.html
index 0e26752..fa2d965 100644
--- a/site/dashboard.html
+++ b/site/dashboard.html
@@ -1153,13 +1153,10 @@ async function refresh() {
const isWin = stats.data_dir && stats.data_dir.includes(':\\');
const isMac = stats.data_dir && stats.data_dir.includes('/usr/local/');
const logsEl = document.getElementById('footerLogs');
- if (isWin) {
- document.getElementById('footerLogsWrap').style.display = 'none';
- } else {
- logsEl.textContent = isMac
- ? '/usr/local/var/log/numa.log'
- : 'journalctl -u numa -f';
- }
+ logsEl.textContent = isWin
+ ? stats.data_dir + '\\numa.log'
+ : isMac ? '/usr/local/var/log/numa.log'
+ : 'journalctl -u numa -f';
}
// LAN status indicator
@@ -1523,7 +1520,7 @@ setInterval(refresh, 2000);
Config:
· Data:
-
+ · Logs:
Upstream:
· DNSSEC:
diff --git a/src/lib.rs b/src/lib.rs
index 8bb28d6..a16568b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -101,14 +101,11 @@ where
/// Linux root daemon: /var/lib/numa (FHS) — falls back to /usr/local/var/numa
/// if a pre-v0.10.1 install already lives there.
/// macOS root daemon: /usr/local/var/numa (Homebrew prefix)
-/// Windows: %APPDATA%\numa
+/// Windows: %PROGRAMDATA%\numa (same as data_dir — no per-user config on Windows)
pub fn config_dir() -> std::path::PathBuf {
#[cfg(windows)]
{
- std::path::PathBuf::from(
- std::env::var("APPDATA").unwrap_or_else(|_| "C:\\ProgramData".into()),
- )
- .join("numa")
+ data_dir()
}
#[cfg(not(windows))]
{
diff --git a/src/main.rs b/src/main.rs
index b8893b3..34bf747 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,21 +4,32 @@ use numa::system_dns::{
};
fn main() -> numa::Result<()> {
+ // Handle CLI subcommands
+ let arg1 = std::env::args().nth(1).unwrap_or_default();
+
+ #[cfg(windows)]
+ if arg1 == "--service" {
+ // Running under SCM — stderr goes nowhere. Redirect logs to a file.
+ let log_path = numa::data_dir().join("numa.log");
+ let log_file = std::fs::OpenOptions::new()
+ .create(true)
+ .append(true)
+ .open(&log_path)
+ .expect("failed to open log file");
+ env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
+ .format_timestamp_millis()
+ .target(env_logger::Target::Pipe(Box::new(log_file)))
+ .init();
+ numa::windows_service::run_as_service()
+ .map_err(|e| format!("windows service dispatcher failed: {}", e))?;
+ return Ok(());
+ }
+
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.format_timestamp_millis()
.init();
- // Handle CLI subcommands
- let arg1 = std::env::args().nth(1).unwrap_or_default();
match arg1.as_str() {
- #[cfg(windows)]
- "--service" => {
- // Entry point used by Windows SCM (`sc create … binPath="numa.exe --service"`).
- // Blocks until SCM sends Stop; never returns normally.
- numa::windows_service::run_as_service()
- .map_err(|e| format!("windows service dispatcher failed: {}", e))?;
- return Ok(());
- }
"install" => {
eprintln!("\x1b[1;38;2;192;98;58mNuma\x1b[0m — installing\n");
return install_service().map_err(|e| e.into());