From f36bdefe9faa1cec62abf254abf8b7b00b1df236 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 10 Jun 2026 14:38:47 +0200 Subject: [PATCH] Add support for catatonin, and add --no-init --- README.md | 1 + composefs-run/src/main.rs | 4 +++ composefs-run/src/run.rs | 51 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5bbf4ef..94ed703 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ tracking. - No detached mode, always assumes `-i`. - By default, writable overlays are transient, stored in /var/tmp. This can be overridden with `--overlay-dir` +- By default runs catatonit in the container to forward signals ### Quick start diff --git a/composefs-run/src/main.rs b/composefs-run/src/main.rs index 65911f4..c3ca8ed 100644 --- a/composefs-run/src/main.rs +++ b/composefs-run/src/main.rs @@ -317,6 +317,10 @@ pub(crate) struct Cli { #[clap(short = 'i', long, hide = true)] interactive: bool, + /// Disable the default init process (catatonit) as PID 1 + #[clap(long)] + no_init: bool, + /// Add a host device to the container (HOST_PATH[:CONTAINER_PATH[:PERMISSIONS]]) #[clap(long, value_parser = clap::value_parser!(DeviceSpec))] device: Vec, diff --git a/composefs-run/src/run.rs b/composefs-run/src/run.rs index 42518ff..fc3e362 100644 --- a/composefs-run/src/run.rs +++ b/composefs-run/src/run.rs @@ -371,6 +371,25 @@ fn setup_netns(bundle_dir: &Path) -> Result { Ok(netns_path) } +const CATATONIT_PATHS: &[&str] = &[ + "/usr/libexec/catatonit/catatonit", + "/usr/libexec/podman/catatonit", + "/usr/local/libexec/podman/catatonit", + "/usr/local/lib/podman/catatonit", + "/usr/libexec/catatonit", + "/usr/bin/catatonit", +]; + +fn find_catatonit() -> Result { + for path in CATATONIT_PATHS { + let p = Path::new(path); + if p.exists() { + return Ok(p.to_owned()); + } + } + anyhow::bail!("catatonit not found") +} + fn setup_pasta(netns_path: &Path, pid_file: &Path, publish: &[PortSpec]) -> Result { let mut pasta_cmd = Command::new("pasta"); pasta_cmd @@ -556,7 +575,7 @@ fn build_runtime_spec( // ── Resolve image + CLI into effective values ─────────────────────── - let args = if cli.cmd.is_empty() { + let mut args = if cli.cmd.is_empty() { let mut args = oci_config.entrypoint().clone().unwrap_or_default(); args.extend(oci_config.cmd().clone().unwrap_or_default()); ensure!( @@ -610,6 +629,20 @@ fn build_runtime_spec( SystemdMode::Auto => is_systemd_command(&args), }; + let use_init = !cli.no_init && !systemd_mode; + let init_path = if use_init { + match find_catatonit() { + Ok(path) => { + args.insert(0, "/dev/init".into()); + args.insert(1, "--".into()); + Some(path) + } + Err(_) => None, + } + } else { + None + }; + let host_network = netns_path.is_none(); // Capabilities: start from podman's default set (containers.conf), @@ -932,6 +965,22 @@ fn build_runtime_spec( )?; mounts.extend(etc_mounts); + if let Some(ref path) = init_path { + mounts.push( + MountBuilder::default() + .typ("bind") + .source(path) + .destination("/dev/init") + .options(vec![ + "bind".into(), + "ro".into(), + "nosuid".into(), + "nodev".into(), + ]) + .build()?, + ); + } + spec.set_mounts(Some(mounts)); // Poststop hook: unmount bundle and clean up the container directory