Skip to content

feat(linux): run the container command under a configured init - #1200

Open
indrajithek wants to merge 9 commits into
urunc-dev:mainfrom
indrajithek:feat/linux-urunit-init
Open

indrajithek wants to merge 9 commits into
urunc-dev:mainfrom
indrajithek:feat/linux-urunit-init

Conversation

@indrajithek

@indrajithek indrajithek commented Nov 10, 2026 •

Copy link
Copy Markdown

This PR Depends on #1136, which has to be merged first. Until then, this PR also shows the #1136 commits. The actual ones are the last three.

Description

Argo Workflows wraps the command of every step in its emissary (argoexec emissary ... -- <command>). On Linux guests the wrapped command does not start with urunit, so it still goes on the kernel command line, which drops everything after the second --. So this change introduce two things

  1. A new annotation com.urunc.unikernel.init, holds the absolute path of an init inside the container rootfs. When it is set, urunc boots that init and passes the whole container command to it through the urunit configuration I proposed earlier in fix(linux): pass the application command to urunit in config #1136.
  2. When urunc gets /dev/null as stdin from the shim (no terminal and no stdin attached), it adds STDIN:0 to the urunit configuration, so urunit gives the application /dev/null instead of the console (feat: give the application /dev/null as stdin when it has none nubificus/urunit#18). Without it, emissary sees a terminal and tries to start the command on a pty.

Related issues

How was this tested?

Wrote test cases (similar to Hyperlight test cases) in annotations_test.go. I think that covers almost all validation scenarios. Tests were done manual in UbuntuVM, Virtiofsd 1.13.0 was used with urunit from nubificus/urunit#18. The e2e targets (make test_*) were not run as they first need to rebuilt with latest urunit with ARC/ARV

LLM usage

Only claude Code Opus 5.5 with XHigh effort is used (manual mode). Decision making or architecture is not by AI. If code generation was used, it's reviewed manually line by line (Mainly used on annotation test coverage, but it seemed to be ok so I proceeded with that).

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint). Linter fails on some old files which I didnt touched in this PR. So doesnt matter I guess
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl). Before running this all linux images need to rebuild with latest urunit with ARC/ARV
  • If LLMs were used: I have read the llm policy.

The Linux kernel command line cannot carry an arbitrary argument list:
an empty argument disappears, a literal `--` cuts off the rest, the
list is truncated at 2048 bytes and more than 32 arguments panic the
kernel.

When urunit is the init, write the application command in the urunit
configuration as `ARC`/`ARV` entries, as FreeBSD guests already do, and
stop passing it on the kernel command line. Also return a clear error
when an argument contains a newline.

This fix requires a urunit that reads `ARC`/`ARV`.

Fixes: urunc-dev#1067
Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
Add the `ARC`/`ARV` entries to the documented urunit configuration
format and update the list of actions urunit performs.

Ref: urunc-dev#1067
Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
Noticed urunc-dev#1068 is also addressing arguments containing a newline.
Removing it from this PR to avoid conflicts.

Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
Remove the test cases created for urunc-dev#1136.

Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
Add the `com.urunc.unikernel.init` annotation, also read from
`urunc.json`, with the absolute path of an init inside the container
rootfs. When it is set, urunc boots that init and passes the container
command to it as arguments, unless the command already starts urunit.

Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
When urunc gets `/dev/null` as stdin from the shim, add `STDIN:0` to
the urunit configuration, so urunit gives the application `/dev/null`
instead of the console. A container with stdin attached keeps the
console.

This requires a urunit that reads `STDIN` (nubificus/urunit#18). Older
urunit versions ignore the entry.

Signed-off-by: Indrajith <29561593+indrajithek@users.noreply.github.com>
@netlify

netlify Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

👷 Deploy request for urunc pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 78b7135

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Argo Workflows main container command is cut at the second --

1 participant