diff --git a/flake.nix b/flake.nix index cd79d37..824adfd 100644 --- a/flake.nix +++ b/flake.nix @@ -123,6 +123,11 @@ # Make `nod` available to all users without manual systemPackages entries. environment.systemPackages = [ cfg.package ]; + # gc.lock is root-owned, so regrant it to the nod group readable for GC tracking. + systemd.tmpfiles.rules = [ + "z /nix/var/nix/gc.lock 0640 root ${cfg.group} -" + ]; + systemd.services.nod = { description = "Nix Observability Daemon"; wantedBy = ["multi-user.target"]; diff --git a/src/daemon.rs b/src/daemon.rs index df2e842..64199cf 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -48,18 +48,25 @@ pub fn run_daemon( info!("listening on {}", socket_path.display()); let gc_lock = nix_state_dir.join("gc.lock"); - if gc_lock.exists() { - let gc_tx = tx.clone(); - thread::Builder::new() - .name("gc".into()) - .spawn(move || run_gc_tracker(&gc_lock, gc_tx)) - .context("failed to spawn gc thread")?; - info!("GC tracking enabled ({})", nix_state_dir.display()); - } else { - warn!( - "gc.lock not found at {} — GC tracking disabled", - gc_lock.display() - ); + match std::fs::File::open(&gc_lock) { + Ok(_) => { + let gc_tx = tx.clone(); + thread::Builder::new() + .name("gc".into()) + .spawn(move || run_gc_tracker(&gc_lock, gc_tx)) + .context("failed to spawn gc thread")?; + info!("GC tracking enabled ({})", nix_state_dir.display()); + } + Err(e) => match e.kind() { + std::io::ErrorKind::NotFound => warn!( + "gc.lock not found at {}, GC tracking disabled", + gc_lock.display() + ), + _ => warn!( + "gc.lock at {} unreadable ({e}), GC tracking disabled", + gc_lock.display() + ), + }, } for stream in listener.incoming() {