Decision — hostd, the host service

Status: accepted 2026-10-12.

The decision

  • One service, hostd, runs as root on each host. It has two jobs: information about the host (hardware, OS, the MixOS mode, network management state, devices, power) and privileged actions on the host. It is the host agent of the VT-native design: the only MixOS code on the host besides mix.
  • No generic exec. No verb runs a caller-supplied command, script or shell string. Each verb does one job, checks its arguments against a schema and does the work natively (writes the file itself, calls networkd, resolved, logind or iwd over Varlink or D-Bus).
  • Written in Rust. Mix is the client. A root process that interprets scripts is too much attack surface.
  • A verb that can't be reversed is not added. Exception: the two desk power verbs, desk.restart and desk.stop (see Amendments).
  • Every new verb is reviewed on its own, and the verb list stays short.

Callers and transport

  • Local callers use a Unix socket. Identity comes from the kernel (SO_PEERCRED) and the caller's cgroup, never from the request.
  • Reads are also served on the Bus, like any other service's.
  • Writes from other nodes are accepted only when signed by a controller key listed in that host's policy, over the target node, a nonce and an expiry. Mesh trust alone never authorises a write. A host with no listed controller accepts no remote writes. Enforcement is on the receiving host.
  • Ports below 1024 are not hostd's job. A service that binds one gets AmbientCapabilities=CAP_NET_BIND_SERVICE in its own unit.

Tiers

TierExamplesGate
readhost info, network state, devicescaller identity
reversibleWi-Fi connect, link configuration, device bind, suspenda standing grant, plus a dead-man check or a kept previous state
reversible, wide blast radiusfirewall, host package upgrade, reboota grant, a second signature from an independent reviewer, and a rate limit
irreversible—no verb exists

Autonomy within limits set in advance

  • Standing grants, not per-call prompts. A grant names the caller (from the kernel), the verbs, argument limits and an optional expiry. Only creating or widening a grant needs a person, confirmed through physical input that no Bus caller can synthesise.
  • Reversible by construction. A verb applies its change, runs a health check, and reverts unless the check passes in time. It keeps the previous state (the previous file, or a filesystem snapshot) behind a receipt that hostd.undo restores.
  • Limits: a rate limit per caller and verb, a circuit breaker after repeated rollbacks, and a freeze that drops hostd to reads only.
  • Audit: one journal record per call.

Files hostd owns

hostd writes only files it names itself (networkd files are /etc/systemd/network/50-hostd-*) and never edits a file it didn't write.

Why

  • Agents need to change host configuration (network, WireGuard, power, devices) without sudo from a session, and without a person approving each call.
  • MixOS core has no polkit. hostd is the mechanism and its policy in one small binary, with rules as data instead of scripts.
  • Closed verbs make a stolen credential worth far less than a root shell.

Consequences

  • Session code never shells out to sudo; a missing host action is a new hostd verb.
  • Write verbs arrive one reviewed verb at a time. The first is net.link.apply; the verbs, grants and refusals are documented in the host service manual.
  • Root on the host means uid 0 in hostd's own pid and user namespaces, proven through a pidfd. Root inside a container is never root on the host, with or without uid remapping.

Amendments

2026-10-13: desk power verbs are an exception to "no irreversible verbs"

desk.restart and desk.stop restart or power off one desk machine. A powered-off desk cannot be put back by hostd, so no undo can exist. The desk must still be able to restart or stop itself, so the two verbs are admitted as exceptions to the irreversibility rule. They are not a pattern for other verbs.

Reversibility is replaced by these limits, which apply to both verbs:

  • One desk per grant. The verb takes no machine name. The grant's desks limit must name exactly one valid machine, and that machine is the only one the verb can touch. A caller with no desk, or two, is refused.
  • The host is never powered. The verbs run machinectl reboot or machinectl poweroff on the named machine only.
  • A standing grant, rate limited. Nothing runs without a grant, and a grant carries a rate limit and an expiry.
  • Freeze applies. hostd.freeze refuses both verbs.
  • Every call is recorded, as a receipt and in the audit journal. hostd.undo refuses both verbs.

Deferred (Mark, 2026-10-13): the second signature from an independent reviewer that the reboot tier requires is not built for desk.*. Security gates are added once the desktop is ready for daily use, where they are needed. Until then, the grant's rate limit and expiry are the only second check.

This page as Markdown · This page describes the current main branch of MixOS.