Skip to content

Ports

Three classes of port matter:

  1. Host ports — the gateway HTTP port and the NATS sibling's two ports. Configured in host.json.
  2. Runtime serve ports — webapp --serve ports. Auto-allocated by default; can be pinned with --port.
  3. External (cloud-side) ports — only relevant for Hosts playing the cloud-platform role; out of scope for this page.

Host ports — defaults

ServiceDefault portSet inCLI override
Gateway HTTP3100host.json http.porthivecast install --http-port <n>
NATS broker4222host.json transport.nats.port (and embedded in nats.url)hivecast install -p <n> or --port <n>
NATS WebSocket4223host.json transport.nats.wsPort (and embedded in nats.wsUrl)hivecast install --ws-port <n>

The gateway HTTP port is what your browser hits. The NATS broker port is what runtimes use for the local bus. The NATS WebSocket port is what browsers use for the bus (via /nats-ws proxied by the gateway).

Allocation logic

parsePort (hivecast.mjs:110-117) handles the flag parsing:

js
function parsePort(value, defaultPort, options = {}) {
  if (!value) return defaultPort;
  if (value === 'auto') return options.allowAuto ? null : defaultPort;
  const parsed = Number.parseInt(value, 10);
  if (!Number.isFinite(parsed)) return defaultPort;
  if (parsed === 0 && options.allowAuto) return null;
  return parsed > 0 ? parsed : defaultPort;
}

Behaviour:

  • --http-port 0 or --http-port auto → null in host.json → host-service / OS allocate
  • --http-port 3100 → exactly 3100
  • --http-port "weird" → falls back to default 3100 (silent)
  • -p 4222 → NATS port pinned
  • omitted → defaults

seedHostProductHome reads these flags at hivecast.mjs:360-362:

js
const httpPort = parsePort(readOption('--http-port'), 3100, { allowAuto: true });
const natsPort = parsePort(readOption('-p', '--port'), 4222);
const natsWsPort = parsePort(readOption('--ws-port'), natsPort + 1);

Note: wsPort defaults to natsPort + 1. Pinning NATS to 4242 without specifying --ws-port gives WS port 4243.

Runtime --serve ports

When you hivecast up <pkg> --serve without --port, the host-service auto-allocates a port (asks the OS for any free port). The runtime registers itself in runtime.json metadata.webapp.servePort, and the gateway proxies traffic from /<routePrefix>/ to that port.

To pin a runtime's serve port:

bash
hivecast up @open-matrix/chat --serve --port 5050 --home <host-home>

Default runtimes (matrix-web, matrix-edge, etc) all auto-allocate. The user only sees the gateway HTTP port (3100) — internal routing handles the rest.

What listens on which port — typical install

0.0.0.0 (or 127.0.0.1) :3100  ← system-gateway-http (matrix HTTP gateway)
127.0.0.1              :4222  ← nats-server (broker)
127.0.0.1              :4223  ← nats-server (WebSocket)
127.0.0.1              :<auto>  ← matrix-web --serve
127.0.0.1              :<auto>  ← matrix-edge --serve
127.0.0.1              :<auto>  ← @open-matrix/director --serve
127.0.0.1              :<auto>  ← @open-matrix/chat --serve
127.0.0.1              :<auto>  ← @open-matrix/inference-settings --serve
127.0.0.1              :<auto>  ← @open-matrix/flowpad --serve
127.0.0.1              :<auto>  ← @open-matrix/smithers --serve

Use lsof -i -P (Linux/macOS) or Get-NetTCPConnection (Windows) to enumerate live listeners.

Pinning the dev two-runtime topology

Per CLAUDE.md "Two-Runtime Dev Topology":

bash
hivecast install --home /tmp/matrix-home --no-start
hivecast start --home /tmp/matrix-home --no-default-runtimes

matrix up @open-matrix/matrix-web --serve --port 5001 \
  --runtime-id WEB --env hivecast --startup auto --restart always

matrix up @open-matrix/matrix-edge --serve --port 5002 \
  --runtime-id EDGE --env hivecast --startup auto --restart always

Browser:

  • http://127.0.0.1:5001/apps/web/ — platform-role shell
  • http://127.0.0.1:5002/apps/edge/ — Device-role shell

Both still go through the gateway on 3100, but pinning the underlying serve ports gives stable URLs for testing.

Container considerations

The .deb postinst auto-detects containers via /.dockerenv or /proc/1/cgroup and binds the gateway and NATS to 0.0.0.0 so they're reachable from outside the container. The wrapper-direct hivecast install does NOT auto-switch — it sticks with 127.0.0.1 unless you explicitly edit host.json.

If you're running in a container without the .deb:

bash
hivecast install --home /tmp/matrix-home --http-port 3100
# Edit host.json to change http.host from "127.0.0.1" to "0.0.0.0"
# Edit nats-server.conf in the same way (or set the host in host.json's transport.nats — but that requires regen)
hivecast start --home /tmp/matrix-home

Or use the .deb, which handles this automatically.

TLS

The default install does NOT terminate TLS. The gateway serves plain HTTP on 3100. For production:

  • Use a reverse proxy (nginx, Caddy) with TLS termination in front of 3100.
  • Cloud-platform Hosts must terminate TLS (e.g. behind a load balancer or via a TLS-terminating proxy).

hivecast.ai itself runs behind a TLS-terminating proxy. The Host doesn't know about TLS.

Privileged ports

Ports below 1024 (e.g. 80, 443) require root or CAP_NET_BIND_SERVICE. The .deb install's hivecast user does NOT have either. To bind 80/443, either:

  • Use a reverse proxy on a privileged port forwarding to 3100.
  • Grant CAP_NET_BIND_SERVICE to /opt/hivecast/node/bin/node (advanced).
  • Run hivecast as root (not recommended).

See also

Source: projects/matrix-3/packages/hivecast/bin/hivecast.mjs lines 110-117 (parsePort), 360-362 (port reads in seedHostProductHome), 584-625 (NATS conf paths and config gen); projects/matrix-3/packages/host-service/src/host-paths.ts lines 30-32 (default 4270/4271 — note: only used in the embedded mode default; external mode uses 4222/4223).