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.
| Path | What it holds |
|---|---|
/etc/hal0/hal0.toml | The main configuration file. |
/etc/hal0/hardware.json | Output of the hardware probe (see below). |
/etc/hal0/openwebui.env | OpenWebUI env, written by the installer. |
/etc/hal0/slots/<name>.env | Per-slot env file consumed by the systemd unit. |
/etc/hal0/proxmox.json | Optional PVE API token for the host-pressure segment in the memory bar. 0600, redacted on read. |
/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.
If hal0 is running in an LXC on a Proxmox node, dropping a read-only
PVEAuditor token into /etc/hal0/proxmox.json (Settings → Proxmox
integration writes this for you) lights up the “Proxmox host” segment
in the dashboard’s unified-memory bar. Without it, the panel stays
quiet and the memory bar shows the LXC’s cgroup slice only.
Editing the config
Section titled “Editing the config”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 $EDITORhal0 config validate # schema check without writinghal0 config show # print merged viewhal0 config migrate # apply schema migrations to an older config - Direct edit. Just open the file. On the next
hal0-apirestart (or ahal0 config validaterun), the schema enforces shape — a typo fails loudly, not silently.
Atomic writes
Section titled “Atomic writes”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.
Schema validation
Section titled “Schema validation”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.
The hardware.json file
Section titled “The hardware.json file”/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, or changing the LXC’s dev0–dev3 passthrough
set):
hal0 probeThe output is structured: cpu_*, mem_*, gpu_*, npu_*, plus
provider availability flags.
Coming soon — outline
Section titled “Coming soon — outline”- 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/).