Skip to content

NATS config

A Host owns one local NATS bus. There are two operating modes; the choice lives in host.json at transport.nats.mode.

Two modes

mode: "embedded"

MatrixHostService._startHostNatsIfNeeded (matrix-host-service.ts:966-1021) spawns nats-server as a child of the Host process. This is the hivecast wrapper default for new homes.

  • Lifetime: dies with the Host. NATS comes back when the Host comes back.
  • Ports: defaults 4270 (NATS) + 4271 (WS).
  • Data dir: <home>/nats/host-default/.
  • Config file written to <dataDir>/nats-server.conf on every Host start (atomic write).
  • Pidfile: <home>/nats/host-default/nats-server.pid.

The wrapper actually overrides this for product use. Even in embedded configs, hivecast install rewrites the config to mode: "external" and spawns NATS as an independent sibling (see below). The reason is in the comment at hivecast.mjs:561-582: production runs NATS and the Host as two systemd services, and a Host crash should not take NATS down.

mode: "external"

The Host connects to a NATS that someone else manages. This is the .deb default and the wrapper's effective default after install.

  • The Host does not spawn NATS. _startHostNatsIfNeeded returns null.
  • Required: transport.nats.url (e.g. nats://127.0.0.1:4222).
  • Optional: transport.nats.wsUrl, transport.nats.credentialsRef.
  • The Host will refuse to start if mode=external and url is missing (matrix-host-service.ts:968-973).

The wrapper's NATS sibling

hivecast.mjs:561-723 supervises NATS as a fully detached process so the Host and NATS can crash independently:

  • startNatsSibling (hivecast.mjs:654-685) spawns nats-server -c <conf> with detached: true, windowsHide: true, and stdio: ['ignore', stdout, stderr], then child.unref(). Pid is written to the configured pidFile.
  • isNatsSiblingRunning (hivecast.mjs:627-636) reads the pidfile and checks process liveness with process.kill(pid, 0).
  • stopNatsSibling (hivecast.mjs:687-723) reads the pidfile, sends SIGTERM (3s grace), then SIGKILL (1s grace), then removes the pidfile.

The pidfile-with-liveness-check is the only synchronization between the wrapper and host-service. Restarting host-service alone (e.g. systemctl restart hivecast-host.service) does not touch NATS.

Config schema

ts
// projects/matrix-3/packages/host-service/src/types.ts:16-26
interface IHostNatsTransportConfig {
  readonly mode: 'embedded' | 'external';
  readonly url?: string;
  readonly wsUrl?: string;
  readonly credentialsRef?: string;
  readonly port?: number;
  readonly wsPort?: number;
  readonly dataDir?: string;
  readonly pidFile?: string;
  readonly binaryPath?: string;
}
FieldUse
modeembedded for Host-managed; external for everything else
urlNATS URL the Host connects to
wsUrlWebSocket URL the gateway exposes for browsers
credentialsRefPath or ref to NATS credentials; resolved via @open-matrix/nats-auth
portTCP port for embedded mode (default 4270)
wsPortWebSocket port for embedded mode (default 4271)
dataDirJetStream store directory, relative to <home>
pidFileNATS pidfile path, relative to <home>
binaryPathOverride the bundled nats-server binary path

The wrapper's nats-server.conf

For wrapper installs, ensureNatsConfigFile (hivecast.mjs:606-625) writes a minimal config:

text
host: "127.0.0.1"
port: 4270
jetstream {
  store_dir: "/home/me/.matrix/nats/host-default"
}
websocket {
  host: "127.0.0.1"
  port: 4271
  no_tls: true
}

The .deb postinst (build-deb-installer.js:334-345) writes a substantively identical file at /var/lib/hivecast/nats/service/nats-server.conf with port 4222/4223 and bind host driven by ${HIVECAST_BIND_HOST}.

What does NOT live in host.json

NATS users, accounts, JWTs, and operator keys are not in host.json. That file deliberately stays minimal. NATS auth lives separately in @open-matrix/nats-auth and credentialsRef (typically file:credentials.json) points into <home>/credentials/.

Common operations

bash
# Inspect the running NATS.
sudo systemctl status hivecast-nats.service     # systemd
ps -p $(cat <home>/nats/host-default/nats-server.pid)  # wrapper

# Tail NATS logs.
sudo journalctl -u hivecast-nats.service -f     # systemd
tail -f <home>/logs/nats.stdout.log             # wrapper

# Restart only NATS without restarting the Host (systemd only).
sudo systemctl restart hivecast-nats.service
# Note: host-service has Requires=hivecast-nats.service, so restarting
# NATS will cascade-restart the Host too.

# Wrapper: restart the NATS sibling.
hivecast stop  --home <home>     # also stops NATS sibling
hivecast start --home <home>

See also