# `Hyper.Node.FireVMM.Jailer`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/node/fire_vmm/jailer.ex#L1)

Builds the `hyper-suidhelper jailer` command for one VM.

The BEAM does not invoke the jailer directly. Instead it calls the setuid helper
with the `jailer` subcommand; the helper reads the firecracker binary path, chroot
base, parent cgroup, and cgroup version from its trusted `/etc/hyper/config.toml`,
re-acquires root, and `execve`s the jailer (same pid, so `MuonTrap.Daemon` keeps
supervising it).

This means the BEAM passes only untrusted-origin values: `--id`, `--uid`, `--gid`,
repeated `--cgroup KEY=VALUE`, and `--api-sock`. The helper derives and validates
everything else; it also inserts the `--` separator between its own flags and
firecracker's flags.

Because firecracker is chrooted to `<chroot_base>/<exec>/<id>/root`, the API
socket it opens at `/api.socket` lives at `host_socket` on the host — that's the
path the controller connects to.

# `t`

```elixir
@type t() :: %{binary: String.t(), args: [String.t()], host_socket: Path.t()}
```

# `cgroup_dir`

```elixir
@spec cgroup_dir(Hyper.Vm.Id.t()) :: Path.t()
```

Host path of the VM's cgroup leaf (`/sys/fs/cgroup/<parent>/<id>`), the cgroup
the jailer creates for firecracker. Reconstructed (the jailer owns its
placement) so a relaunch can clear the stale leaf left by a prior incarnation.

# `cgroup_parent_dir`

```elixir
@spec cgroup_parent_dir() :: Path.t()
```

Host path of the cgroup dir holding every VM's leaf (`/sys/fs/cgroup/<parent>`).
Its immediate subdir names are vm_ids - the leaves the jailer creates for
firecracker - so listing it (directories only; the dir also holds cgroup control
files) enumerates the cgroup leaves on this host.

Note the cgroup hierarchy has NO `<exec>` level: the jailer (cgroup v2,
`--parent-cgroup <parent>`) places firecracker directly at `<parent>/<id>`,
unlike the chroot (`<chroot_base>/<exec>/<id>`). Confirmed via
`/proc/<pid>/cgroup` = `0::/<parent>/<id>`.

# `chroot_dir`

```elixir
@spec chroot_dir(Hyper.Vm.Id.t()) :: Path.t()
```

Host path of the VM's per-VM jail dir (`<chroot_base>/<exec>/<id>`).

# `chroot_root`

```elixir
@spec chroot_root(Hyper.Vm.Id.t()) :: Path.t()
```

Host path of the VM's chroot root (`<chroot_base>/<exec>/<id>/root`).

# `command`

```elixir
@spec command(Hyper.Node.FireVMM.Opts.t()) :: t()
```

# `host_socket`

```elixir
@spec host_socket(Hyper.Vm.Id.t()) :: Path.t()
```

Host-side path of the API socket firecracker opens inside the jail.

Deterministic in `id` alone, so the controller and the API client can each
derive it independently and are guaranteed to agree. We do not control where
the jailer places the socket, so the path is reconstructed here.

# `host_vsock`

```elixir
@spec host_vsock(Hyper.Vm.Id.t()) :: Path.t()
```

Host-side path of the vsock Unix-domain socket firecracker opens inside the jail.

Firecracker creates the vsock UDS at `uds_path` relative to its chroot root,
so on the host it lives at `<chroot_root>/vsock.sock`. Deterministic in `id`
alone, mirroring `host_socket/1`.

# `test_system`

```elixir
@spec test_system() :: :ok | {:error, term()}
```

Test whether the jailer and system pre-requisites are available.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
