From 31b564729082f1839eb1d55f5121a49157c54267 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sun, 25 Jan 2026 09:12:28 +0000 Subject: [PATCH] feat: remowt-nix-daemon --- --- /dev/null +++ b/crates/remowt-nix-daemon/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "fleet-nix-daemon" +description = "Nix daemon proxy endpoint + connection logic for fleet" +version.workspace = true +edition = "2021" + +[dependencies] +anyhow.workspace = true +bifrostlink.workspace = true +bifrostlink-macros.workspace = true +camino.workspace = true +remowt-client.workspace = true +serde = { workspace = true } +thiserror.workspace = true +tokio = { workspace = true, features = ["net", "io-util", "rt", "process"] } +tracing.workspace = true +uuid.workspace = true --- /dev/null +++ b/crates/remowt-nix-daemon/src/lib.rs @@ -0,0 +1,65 @@ +use std::process::Stdio; + +use bifrostlink::declarative::endpoints; +use bifrostlink::Config; +use serde::{Deserialize, Serialize}; +use std::result::Result; +use tokio::process::Command; + +pub const NIX_DAEMON_SOCKET: &str = "/nix/var/nix/daemon-socket/socket"; + +pub struct NixDaemon; + +#[derive(Serialize, Deserialize, Debug, thiserror::Error)] +pub enum Error { + #[error("nix daemon unavailable: {0}")] + DaemonUnavailable(String), + #[error("tunnel socket unavailable: {0}")] + Tunnel(String), +} + +#[endpoints(ns = 4)] +impl NixDaemon { + #[endpoints(id = 1)] + async fn connect_daemon(&self, socket: String) -> Result<(), Error> { + let mut daemon = tokio::net::UnixStream::connect(NIX_DAEMON_SOCKET) + .await + .map_err(|e| Error::DaemonUnavailable(e.to_string()))?; + let mut tunnel = tokio::net::UnixStream::connect(&socket) + .await + .map_err(|e| Error::Tunnel(e.to_string()))?; + tokio::spawn(async move { + if let Err(e) = tokio::io::copy_bidirectional(&mut daemon, &mut tunnel).await { + tracing::debug!("nix daemon tunnel ended: {e}"); + } + }); + Ok(()) + } + + #[endpoints(id = 2)] + async fn serve_store(&self, store: String, socket: String) -> Result<(), Error> { + let mut child = Command::new("nix-daemon") + .arg("--stdio") + .arg("--store") + .arg(&store) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .map_err(|e| Error::DaemonUnavailable(e.to_string()))?; + let tunnel = tokio::net::UnixStream::connect(&socket) + .await + .map_err(|e| Error::Tunnel(e.to_string()))?; + let mut stdin = child.stdin.take().expect("piped"); + let mut stdout = child.stdout.take().expect("piped"); + tokio::spawn(async move { + let mut tunnel = tunnel; + let (mut tr, mut tw) = tunnel.split(); + let _ = tokio::join!( + tokio::io::copy(&mut tr, &mut stdin), + tokio::io::copy(&mut stdout, &mut tw), + ); + let _ = child.wait().await; + }); + Ok(()) + } +} -- gitstuff