Appearance
Host config
<host-home>/host.json is the Host's only top-level configuration file. The schema is IMatrixHostConfig (projects/matrix-3/packages/host-service/src/types.ts:51-61):
ts
interface IMatrixHostConfig {
readonly kind: 'MatrixHostConfig';
readonly version: 1;
readonly home: string;
readonly externalUrl?: string;
readonly http: { readonly host: string; readonly port: number | null };
readonly transport: IHostTransportConfig;
readonly auth: IHostAuthConfig;
readonly runtimeStorage: { readonly recordsDir: string; readonly logsDir: string };
readonly packageStorage: { readonly globalDir: string; readonly systemDir: string };
}Loading and writing
HostStateStore.loadOrCreateConfig (host-state-store.ts:31-44) is the single entry point. On read it:
- If
<home>/host.jsondoes not exist, generates the default (defaultHostConfig,host-paths.ts:16-48) and writes it. - If it exists, parses and runs
normalizeMatrixHostConfig(host-state-store.ts:251-318) to fill in defaults, normalize paths, and reject unknown shapes. - If the in-memory normalized form differs from what was on disk, writes the normalized form back. This is intentional: editing
host.jsonand restarting will canonicalize it.
All writes go through atomicWriteJson (projects/matrix-3/packages/host-service/src/util/atomic-write.ts:17-20): write to a .tmp.<pid>.<ts> file, fsync, then rename. Reading a half-written file is impossible.
Default host.json
json
{
"kind": "MatrixHostConfig",
"version": 1,
"home": "/home/me/.matrix",
"http": {
"host": "127.0.0.1",
"port": null
},
"transport": {
"root": "COM.OPEN-MATRIX.LOCAL.AUTHORITY",
"authorityRoot": "COM.OPEN-MATRIX.LOCAL.AUTHORITY",
"nats": {
"mode": "embedded",
"port": 4270,
"wsPort": 4271,
"dataDir": "nats/host-default",
"pidFile": "nats/host-default/nats-server.pid"
}
},
"auth": {
"mode": "local-client"
},
"runtimeStorage": {
"recordsDir": "runtimes",
"logsDir": "logs/runtimes"
},
"packageStorage": {
"globalDir": "packages/global",
"systemDir": "packages/system"
}
}port: null means "let the OS pick." transport.nats.port: 4270 is the wrapper-default NATS port; the .deb postinst overrides this to 4222 for production-style installs.
Field reference
http
ts
interface IHostHttpConfig {
readonly host: string; // e.g. "127.0.0.1", "0.0.0.0"
readonly port: number | null; // null = OS-allocated
}The Host itself does not run an HTTP server. This config is consumed by the gateway runtime (@open-matrix/system-gateway-http) when the Host writes that runtime's environment file. Pinning a known port here is how operators get stable URLs.
transport
ts
interface IHostTransportConfig {
readonly authorityRoot?: string;
readonly addressRoot?: string;
readonly spaceId?: string;
readonly routeKey?: string;
readonly publicNamespace?: string;
readonly root: string; // legacy; equals authorityRoot for new configs
readonly nats: IHostNatsTransportConfig;
}root is the dot-delimited NATS subject prefix used for every wire message. authorityRoot is the same value, kept for the v1 transition (see repo CLAUDE.md § "Public Space identity"). addressRoot is what public bootstrap clients see; it equals authorityRoot unless overridden.
spaceId, routeKey, publicNamespace are populated by system-auth on device-link approval. Do not edit them by hand.
auth
ts
interface IHostAuthConfig {
readonly mode: 'local-client' | 'public-session';
readonly sessionSecret?: string;
readonly actorTimeoutMs?: number;
readonly providers?: { readonly google?: { ... } };
}mode: "local-client"— Host acts as a local client; runtimes use the bus directly without browser-session machinery. Right for headless and per-user laptop installs.mode: "public-session"— required for browser-served packages (matrix-web,matrix-edge) on a multi-tab dev box. The auth runtime issues per-tab session tokens. See repoAGENTS.md§ "Worker Bootstrap Gotchas" — this trips up worker bootstrap when missed.
runtimeStorage, packageStorage
Relative paths under <home>. Defaults:
| Field | Default | Resolved path |
|---|---|---|
runtimeStorage.recordsDir | runtimes | <home>/runtimes |
runtimeStorage.logsDir | logs/runtimes | <home>/logs/runtimes |
packageStorage.globalDir | packages/global | <home>/packages/global |
packageStorage.systemDir | packages/system | <home>/packages/system |
Paths are joined by hostPaths at host-paths.ts:50-62. These are the only knobs the Host respects for filesystem layout; do not symlink things under <home> and expect them to be honored — runtime spawn assumes direct paths.
Editing the config
bash
# Show the current config (the Host normalizes on read).
cat <host-home>/host.json | jq .
# Edit and let the next start canonicalize.
$EDITOR <host-home>/host.json
hivecast stop --home <home>
hivecast start --home <home>
# Or signal a config reload to a running Host (host-control RPC).
matrix invoke host.control config.reload '{}'config.reload triggers MatrixHostService.applyUpdatedHostConfig (matrix-host-service.ts:169-198): stops every runtime, restarts NATS (if embedded), rewrites host.status.json, refreshes every per-runtime environment file, then auto-restarts persisted runtimes. It is a real restart, not a no-op.