Skip to content

Configuration

hal0’s runtime configuration lives in a single TOML file at /etc/hal0/hal0.toml. Every write is atomic; every field is schema-validated; a bad edit can never produce a half-written file.

PathWhat it holds
/etc/hal0/hal0.tomlThe main configuration file.
/etc/hal0/hardware.jsonOutput of the hardware probe (see below).
/etc/hal0/openwebui.envOpenWebUI env, written by the installer.
/etc/hal0/slots/<name>.envPer-slot env file consumed by the systemd unit.

/etc/hal0/ is preserved across hal0 update. The installer never overwrites a user-modified config file — it skips with a warning if the file already exists.

Three supported workflows:

  • Dashboard. The Settings view exposes most fields with a form for each section. Saves go through the atomic-write path.
  • CLI.
    Terminal window
    hal0 config edit # opens $EDITOR
    hal0 config validate # schema check without writing
    hal0 config show # print merged view
    hal0 config migrate # apply schema migrations to an older config
  • Direct edit. Just open the file. On the next hal0-api restart (or a hal0 config validate run), the schema enforces shape — a typo fails loudly, not silently.

Every config write goes through:

NamedTemporaryFile(delete=False) → write → fsync → os.replace()

If the process crashes mid-write, the prior file is fully intact — os.replace() is atomic on POSIX filesystems. There’s no window in which /etc/hal0/hal0.toml is half-written.

The same pattern applies to per-slot env files; a failed slot config update leaves the previous env in place.

The config schema is Pydantic-defined in src/hal0/config/schema.py and exported as JSON Schema for reference. Every field has:

  • A type (Python type or JSON Schema primitive).
  • A default value where reasonable.
  • A constraint set (regex for slot names, range bounds for ports).
  • Inline documentation that the dashboard surfaces as help text.

A failed validation surfaces as a structured config.invalid error with details.path pointing at the offending field.

See Config schema reference for the full field list.

/etc/hal0/hardware.json is probe output, not config — it’s regenerated by hal0 probe and consumed by the slot loader to pick sensible defaults and surface VRAM/RAM fit warnings inline.

Re-run the probe whenever the hardware changes (BIOS UMA carveout, GPU swap, RAM upgrade):

Terminal window
hal0 probe

The output is structured: cpu_*, mem_*, gpu_*, npu_*, plus provider availability flags.

  • Hot-reload of selected fields (changing an idle timeout without restarting the slot).
  • Encrypted secrets storage for upstream API keys.
  • Multi-file config (drop-in fragments under /etc/hal0/conf.d/).