nspawn

package
v0.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultStopPoll     = 500 * time.Millisecond
	DefaultStopAttempts = 60
)

DefaultStopPoll and DefaultStopAttempts bound the wait for a machine to deregister from systemd-machined (30s total).

View Source
const MCPMountDir = nshelper.MCPMountDir

MCPMountDir is the fixed container path where the host directory holding an MCP server binary is bind-mounted by EnsureBind. The mount is runtime-only (gone on poweroff) so the binary never enters the rootfs and survives `intuneme recreate`.

View Source
const NsenterHelperDir = nshelper.Dir

NsenterHelperDir is the root-owned directory holding the privileged helper.

View Source
const NsenterHelperPath = nshelper.Path

NsenterHelperPath is the fixed helper authorized by the intuneme-exec sudoers rule. The helper resolves the container leader itself; the caller supplies only the script to run as the container user.

View Source
const StandardPATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

StandardPATH is the standard executable search path expected by Ubuntu.

Variables

View Source
var ErrSessionBusTimeout = errors.New("container user session bus timeout")

ErrSessionBusTimeout matches (errors.Is) an Exec error whose launch failed because the container user session bus did not appear in time.

Functions

func Boot

func Boot(r runner.Runner, rootfs, machine, intuneHome, containerHome string, sockets, nvidiaDevices []BindMount) error

Boot starts the nspawn container in the background using sudo.

func BuildBootArgs

func BuildBootArgs(rootfs, machine, intuneHome, containerHome string, sockets []BindMount, nvidiaDevices []BindMount) []string

BuildBootArgs returns the systemd-nspawn arguments to boot the container. DRI devices are detected internally; nvidiaDevices are detected by the caller because Nvidia also needs host library and ICD setup.

func BuildShellArgs

func BuildShellArgs(machine, user string) []string

BuildShellArgs returns the machinectl shell arguments for an interactive session. Uses a login shell so /etc/profile.d scripts run (sets XAUTHORITY, audio, etc).

func EnsureBind added in v0.19.0

func EnsureBind(r runner.Runner, hostDir, probePath string) error

EnsureBind makes hostDir available read-only at MCPMountDir inside the running machine, idempotently. It first probes whether probePath already exists inside the container (via the privileged helper) and only calls the scoped machine helper if it does not. The helper forces a read-only bind of a user-owned directory at the fixed MCP mount path, so it re-establishes the mount after a recreate without exposing broad machinectl management.

func Exec added in v0.9.0

func Exec(r runner.Runner, uid int, command string) error

Exec runs a command non-interactively inside the container as the given user. It invokes the privileged helper, which resolves and validates the container leader itself and drops to the configured UID before exec. Requires passwordless sudo for the helper (installed by intuneme init/start via /etc/sudoers.d/intuneme-exec).

When the prologue gave up waiting for the user session bus, the returned error matches ErrSessionBusTimeout (errors.Is). Its text is the same either way.

func ExecForeground added in v0.19.0

func ExecForeground(r runner.Runner, uid int, command string) error

ExecForeground runs a command inside the container in the FOREGROUND with the caller's stdin/stdout/stderr attached. Unlike Exec it does not background the process; this is required for stdio-transport servers (e.g. MCP) where the parent must speak JSON-RPC over the child's stdin/stdout. No TTY is allocated (the helper does not allocate a TTY), which keeps the JSON-RPC framing intact. Reuses the same helper as Exec, so the intuneme-exec sudoers rule authorizes it passwordless.

func HostDisplay added in v0.12.0

func HostDisplay() string

HostDisplay returns the host's DISPLAY value, falling back to ":0". It validates that the corresponding X11 socket exists.

func HostWaylandSocket added in v0.20.1

func HostWaylandSocket(runtimeDir string) string

HostWaylandSocket returns the host path of the session's Wayland socket.

The name is not fixed. Compositors number their socket by the first free slot, so Mutter typically lands on wayland-0 while Sway and Hyprland commonly use wayland-1. Assuming wayland-0 means the bind is silently skipped on those sessions, /run/host-wayland never appears in the container, and the session script leaves WAYLAND_DISPLAY unset — so Edge fails to connect to any compositor and GTK apps fall back to X11.

$WAYLAND_DISPLAY is the authoritative answer. Per the Wayland protocol it holds either a socket name relative to $XDG_RUNTIME_DIR or an absolute path; both are accepted here.

func IsRunning

func IsRunning(r runner.Runner, machine string) bool

IsRunning checks if the machine is registered with machinectl.

func LeaderPID added in v0.9.0

func LeaderPID(r runner.Runner, machine string) (string, error)

LeaderPID returns the PID of the container's init process (Leader) as reported by machinectl, which is used to enter the container's namespaces via nsenter.

func MachineUnit added in v0.17.0

func MachineUnit(r runner.Runner, machine string) (string, error)

MachineUnit returns the systemd unit currently backing the machine.

func Shell

func Shell(r runner.Runner, machine, user string) error

Shell opens an interactive session in the container via machinectl shell.

func ShellQuote added in v0.19.0

func ShellQuote(s string) string

ShellQuote single-quotes s for safe interpolation into a /bin/sh command.

func Stop

func Stop(r runner.Runner, machine string) error

func StopAndWait added in v0.19.2

func StopAndWait(r runner.Runner, machine string, pollInterval time.Duration, maxAttempts int) error

StopAndWait powers off the container and blocks until systemd-machined has deregistered it, or the poll budget is exhausted.

Every caller that touches the rootfs afterwards MUST use this rather than Stop: `machinectl poweroff` only signals the container's init and returns immediately, so systemd-nspawn is still tearing down the rootfs (and its /sys, /proc and cgroup mounts) when Stop returns. Deleting the rootfs in that window fails partway through with "Directory not empty", leaving a half-erased tree behind.

func ValidateSudo

func ValidateSudo(r runner.Runner) error

ValidateSudo prompts for the sudo password if needed.

func WriteDisplayMarker added in v0.12.0

func WriteDisplayMarker(r runner.Runner, rootfs, display string) error

WriteDisplayMarker writes the host DISPLAY value into the container rootfs so that container scripts and services can read it. Uses sudo install because the rootfs /etc/ is owned by root.

Types

type BindMount

type BindMount struct {
	Host      string
	Container string
	ReadOnly  bool
}

BindMount represents a host:container bind mount pair.

func DetectBlockDevices added in v0.20.0

func DetectBlockDevices() []BindMount

DetectBlockDevices scans for all block devices and resolves their block device paths. Intune reads these directly to verify encryption and requires the full block topology to be present in the container.

func DetectDRIDevices added in v0.13.0

func DetectDRIDevices() []BindMount

DetectDRIDevices scans for DRM card and render devices. Returns individual device bind mounts instead of a directory bind so nspawn can grant each node in the cgroup DeviceAllow list.

func DetectHostSockets

func DetectHostSockets(uid int) []BindMount

DetectHostSockets checks which optional host sockets/files exist and returns bind mount pairs for them.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL