- Nix 100%
|
Some checks are pending
CI / check (push) Waiting to run
well, the first version I am willing to record |
||
|---|---|---|
| .github/workflows | ||
| flake.nix | ||
| README.md | ||
| tests.nix | ||
unsafe-cell
A jail-nix container that shares user namespace and grants all capabilities (the "unsafe" part), packaging a command into a self-contained executable ("cell"). It provides nix daemon passthrough, configurable networking, and filesystem isolation — enough to run agentic workloads without the friction of full containerization.
Capabilities
Shares user/id mappings 1:1 with the host. All kernel capabilities granted. No PID namespace isolation — host PID 1 visible inside. New mount namespace with only explicitly bound paths.
Nix daemon access via read-only bind of host store (/nix/store) and daemon socket (/run/nix). Nix config and experimental features (nix-command, flakes) set inside the jail. Binary substitution enabled.
Network access is always proxied through tinyproxy with an isolated network namespace (no network routes inside the jail). A socat pair forwards TCP through a Unix socket onto tinyproxy. An optional tinyproxy filter file controls allowed domains; defaults to allow-all (.*).
Working directory bind-mounted at a configurable host path. Optional log directory bind.
Entrypoint runs the command derivation supplied via the command parameter. PATH includes nix, coreutils.
Parameters
command (pkgs -> derivation): Builds the jailed entrypoint. Receives nixpkgs.
worktreePath (string): Host path to bind as /home/cell/worktree inside the jail. Required, no default.
extraCombinators (jail-nix -> list, default _: []): jail-nix combinators appended to the default set.
tinyproxyFilter (string or null): Path to a tinyproxy filter file. null = default allow-all filter (.*); non-null = use the specified filter file.
logDir (string or null): Directory to bind for log output. null = use jail tempdir ($JD).
nixDaemonSocket (string, default "/var/nix/daemon-socket"): Host path to nix daemon socket directory (contains socket).
Implicit assumptions
mkCell builds its output for every system in systems.flakeExposed. Requires nixpkgs and jail-nix as flake inputs.
The nix daemon socket path is assumed to be a directory containing a socket entry — the NIX_REMOTE env var always resolves /run/nix/socket regardless of nixDaemonSocket.
/nix/store is assumed present and readable on the host. NIX_PATH hardcoded to /home/cell/.nix-defexpr/channels.
NIX_CONFIG unconditionally overrides host nix config — forces nix-command, flakes, and substitute = true.
Host-side packages required at nixpkgs evaluation time: socat, coreutils, nix, iproute2, gawk, tinyproxy.
worktreePath is resolved relative to the host-script's CWD at runtime (shell expansion applies).
The default combinator set does not include SSL certificates, app config/state directories, nix registry mapping, nix config files, or secret tokens — these must be supplied by the consumer via extraCombinators.
The host script always creates $JD (temp dir) with tinyproxy config, SSL overlay dirs, and Unix socket — all cleaned up on exit. The SSL overlay dirs are created but unused (dead code from original hardcoded version).
No IPC namespace isolation — inherits from host.