git.delta.rocks / remowt / refs/commits / 31b564729082

difftreelog

feat remowt-nix-daemon

tltsxumlYaroslav Bolyukin2026-01-25parent: #fdfebf9.patch.diff
in: trunk

2 files changed

addedcrates/remowt-nix-daemon/Cargo.tomldiffbeforeafterboth

no changes

addedcrates/remowt-nix-daemon/src/lib.rsdiffbeforeafterboth
--- /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(())
+	}
+}