From e2917a73f901665b44c7a1a9df889642433a0ba7 Mon Sep 17 00:00:00 2001 From: Razvan Dimescu Date: Thu, 9 Apr 2026 15:12:59 +0300 Subject: [PATCH] fix: human-readable advisory when TLS data_dir is not writable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When numa runs as non-root on a system with a privileged default data_dir (e.g. /usr/local/var/numa on macOS), TLS CA setup fails with a raw "Permission denied (os error 13)" and HTTPS proxy is silently disabled. The user sees a cryptic warning with no path forward. Detect std::io::ErrorKind::PermissionDenied on the tls error, print a diagnostic naming the data_dir and offering two fixes (install as system resolver, or point data_dir at a writable path), and keep the graceful-degradation behavior — DNS resolution and plain-HTTP proxy continue to work without HTTPS. All other TLS setup errors fall through to the existing log::warn!. Co-Authored-By: Claude Opus 4.6 --- src/main.rs | 10 +++++++++- src/tls.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 20f0dba..67f4abd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -223,7 +223,15 @@ async fn main() -> numa::Result<()> { ) { Ok(tls_config) => Some(ArcSwap::from(tls_config)), Err(e) => { - log::warn!("TLS setup failed, HTTPS proxy disabled: {}", e); + match e.downcast_ref::() { + Some(io_err) if io_err.kind() == std::io::ErrorKind::PermissionDenied => { + eprint!( + "{}", + numa::tls::data_dir_permission_advisory(&resolved_data_dir) + ); + } + _ => log::warn!("TLS setup failed, HTTPS proxy disabled: {}", e), + } None } } diff --git a/src/tls.rs b/src/tls.rs index 7c7620a..d37ea9b 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -40,6 +40,39 @@ pub fn regenerate_tls(ctx: &ServerCtx) { } } +/// Human-readable diagnostic for TLS data-dir permission failures. +/// Triggered when numa can't write its local CA to the configured +/// data dir (typically `/usr/local/var/numa` without root). HTTPS +/// proxy is disabled; DNS resolution and plain-HTTP proxy keep +/// working. +pub fn data_dir_permission_advisory(data_dir: &Path) -> String { + let o = "\x1b[1;38;2;192;98;58m"; // bold orange + let r = "\x1b[0m"; + format!( + " +{o}Numa{r} — HTTPS proxy disabled: cannot write TLS CA to {}. + + The data directory is not writable by the current user. Numa needs + to persist a local Certificate Authority there to serve .numa over + HTTPS. DNS resolution and plain-HTTP proxy continue to work. + + Fix — pick one: + + 1. Install Numa as the system resolver (sets up a writable data dir): + + sudo numa install (on Windows, run as Administrator) + + 2. Point data_dir at a path you can write. + Create ~/.config/numa/numa.toml with: + + [server] + data_dir = \"/path/you/can/write\" + +", + data_dir.display() + ) +} + /// Build a TLS config with a cert covering all provided service names. /// Wildcards under single-label TLDs (*.numa) are rejected by browsers, /// so we list each service explicitly as a SAN.