From 89d0937473224eefb057a9adbba362361b749be1 Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 1 Jun 2026 17:15:06 +0200 Subject: [PATCH] priv: derive flake ref from agent name; WriteNspawnFlags takes flags only --- hive-c0re/src/priv_client.rs | 20 ++++-------- hive-priv/src/main.rs | 62 ++++++++++++++++++++++++++++-------- hive-sh4re/src/priv_proto.rs | 13 +++++--- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/hive-c0re/src/priv_client.rs b/hive-c0re/src/priv_client.rs index 04a3e935..06ae9603 100644 --- a/hive-c0re/src/priv_client.rs +++ b/hive-c0re/src/priv_client.rs @@ -42,18 +42,12 @@ pub async fn kill_container(name: &str) -> Result<()> { ok(call(&PrivRequest::KillContainer { name: name.to_owned() }).await?) } -pub async fn update_container(name: &str, flake_ref: &str) -> Result<(String, String)> { - check(call(&PrivRequest::UpdateContainer { - name: name.to_owned(), - flake_ref: flake_ref.to_owned(), - }).await?) +pub async fn update_container(name: &str) -> Result<(String, String)> { + check(call(&PrivRequest::UpdateContainer { name: name.to_owned() }).await?) } -pub async fn create_container(name: &str, flake_ref: &str) -> Result<(String, String)> { - check(call(&PrivRequest::CreateContainer { - name: name.to_owned(), - flake_ref: flake_ref.to_owned(), - }).await?) +pub async fn create_container(name: &str) -> Result<(String, String)> { + check(call(&PrivRequest::CreateContainer { name: name.to_owned() }).await?) } pub async fn destroy_container(name: &str) -> Result<()> { @@ -65,10 +59,10 @@ pub async fn list_containers() -> Result { Ok(stdout) } -pub async fn write_nspawn_conf(container: &str, content: &str) -> Result<()> { - ok(call(&PrivRequest::WriteNspawnConf { +pub async fn write_nspawn_flags(container: &str, extra_nspawn_flags: &str) -> Result<()> { + ok(call(&PrivRequest::WriteNspawnFlags { container: container.to_owned(), - content: content.to_owned(), + extra_nspawn_flags: extra_nspawn_flags.to_owned(), }).await?) } diff --git a/hive-priv/src/main.rs b/hive-priv/src/main.rs index fa0d0727..be805fd0 100644 --- a/hive-priv/src/main.rs +++ b/hive-priv/src/main.rs @@ -37,6 +37,10 @@ const SIBLING_CONTAINERS: &[&str] = &["hive-forge", "hive-matrix", "hive-gateway /// Root of the per-agent unix-socket dirs on the host. const SOCKET_DIR_ROOT: &str = "/run/hive-agent"; +/// Host path of the meta flake (mirrors `meta::meta_dir()`). +/// The flake ref for agent `` is `{META_DIR}#{name}`. +const META_DIR: &str = "/var/lib/hyperhive/meta"; + #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt() @@ -163,16 +167,16 @@ async fn exec(req: PrivRequest) -> Result<(String, String)> { container_run(&["kill", &container_system_name(name)]).await } - PrivRequest::UpdateContainer { ref name, ref flake_ref } => { + PrivRequest::UpdateContainer { ref name } => { validate_container_name(name)?; - validate_flake_ref(flake_ref)?; - container_run(&["update", &container_system_name(name), "--flake", flake_ref]).await + let flake_ref = agent_flake_ref(name); + container_run(&["update", &container_system_name(name), "--flake", &flake_ref]).await } - PrivRequest::CreateContainer { ref name, ref flake_ref } => { + PrivRequest::CreateContainer { ref name } => { validate_container_name(name)?; - validate_flake_ref(flake_ref)?; - container_run(&["create", &container_system_name(name), "--flake", flake_ref]).await + let flake_ref = agent_flake_ref(name); + container_run(&["create", &container_system_name(name), "--flake", &flake_ref]).await } PrivRequest::DestroyContainer { ref name } => { @@ -182,10 +186,9 @@ async fn exec(req: PrivRequest) -> Result<(String, String)> { PrivRequest::ListContainers => container_run(&["list"]).await, - PrivRequest::WriteNspawnConf { ref container, ref content } => { + PrivRequest::WriteNspawnFlags { ref container, ref extra_nspawn_flags } => { validate_container_system_name(container)?; - let path = format!("/etc/nixos-containers/{container}.conf"); - std::fs::write(&path, content).with_context(|| format!("write {path}"))?; + write_nspawn_flags(container, extra_nspawn_flags)?; Ok((String::new(), String::new())) } @@ -354,9 +357,42 @@ fn validate_name_chars(name: &str) -> Result<()> { Ok(()) } -fn validate_flake_ref(flake_ref: &str) -> Result<()> { - if flake_ref.is_empty() || flake_ref.contains('\n') || flake_ref.contains('\0') { - bail!("invalid flake_ref {flake_ref:?}"); +/// Derive the meta-flake ref for an agent by name. +fn agent_flake_ref(name: &str) -> String { + format!("{META_DIR}#{name}") +} + +/// Update `/etc/nixos-containers/.conf`: strips network-isolation +/// vars (`PRIVATE_NETWORK`, `HOST_ADDRESS*`, `LOCAL_ADDRESS*`, `HOST_BRIDGE`, +/// `EXTRA_NSPAWN_FLAGS`), forces `PRIVATE_NETWORK=0` and blank network vars, +/// then appends `EXTRA_NSPAWN_FLAGS=""`. +fn write_nspawn_flags(container: &str, extra_nspawn_flags: &str) -> Result<()> { + let path = format!("/etc/nixos-containers/{container}.conf"); + let original = std::fs::read_to_string(&path) + .with_context(|| format!("read {path}"))?; + let mut lines: Vec<&str> = original + .lines() + .filter(|line| { + let t = line.trim_start(); + !t.starts_with("EXTRA_NSPAWN_FLAGS=") + && !t.starts_with("PRIVATE_NETWORK=") + && !t.starts_with("HOST_ADDRESS=") + && !t.starts_with("LOCAL_ADDRESS=") + && !t.starts_with("HOST_ADDRESS6=") + && !t.starts_with("LOCAL_ADDRESS6=") + && !t.starts_with("HOST_BRIDGE=") + }) + .collect(); + let mut out = lines.join("\n"); + if !out.is_empty() { + out.push('\n'); } - Ok(()) + out.push_str("PRIVATE_NETWORK=0\n"); + out.push_str("HOST_ADDRESS=\n"); + out.push_str("LOCAL_ADDRESS=\n"); + out.push_str("HOST_ADDRESS6=\n"); + out.push_str("LOCAL_ADDRESS6=\n"); + out.push_str("HOST_BRIDGE=\n"); + out.push_str(&format!("EXTRA_NSPAWN_FLAGS=\"{extra_nspawn_flags}\"\n")); + std::fs::write(&path, out).with_context(|| format!("write {path}")) } diff --git a/hive-sh4re/src/priv_proto.rs b/hive-sh4re/src/priv_proto.rs index 38b4493e..5a3ef08a 100644 --- a/hive-sh4re/src/priv_proto.rs +++ b/hive-sh4re/src/priv_proto.rs @@ -29,10 +29,12 @@ pub enum PrivRequest { KillContainer { name: String }, /// `nixos-container update --flake ` - UpdateContainer { name: String, flake_ref: String }, + /// The flake ref is derived from `name` by hive-priv. + UpdateContainer { name: String }, /// `nixos-container create --flake ` - CreateContainer { name: String, flake_ref: String }, + /// The flake ref is derived from `name` by hive-priv. + CreateContainer { name: String }, /// `nixos-container destroy ` DestroyContainer { name: String }, @@ -42,9 +44,10 @@ pub enum PrivRequest { // --- Config file writes --- - /// Overwrite `/etc/nixos-containers/.conf` with new content. - /// Written by `lifecycle::set_nspawn_flags` to inject `EXTRA_NSPAWN_FLAGS`. - WriteNspawnConf { container: String, content: String }, + /// Update `/etc/nixos-containers/.conf`: strip network-isolation + /// vars, force `PRIVATE_NETWORK=0`, and set `EXTRA_NSPAWN_FLAGS`. + /// Written by `lifecycle::set_nspawn_flags`. + WriteNspawnFlags { container: String, extra_nspawn_flags: String }, /// Write `/run/systemd/system/container@.service.d/hyperhive-limits.conf` /// with `[Service]\nMemoryMax=\nCPUQuota=\n`.