Operations¶
Getting a hive running is the easy part; keeping one up, encrypted, and observable while
real people lean on it is the day-2 job. This page is the operator's toolkit — turning on
TLS, tucking hivemind-core behind a reverse proxy, running it as a managed service,
watching who connects and who gets turned away, and growing past a single instance. None
of it needs special flags: hivemind-core listen takes none. It's all
~/.config/hivemind-core/server.json and the ordinary system tooling you already know.
In a nutshell
- TLS is configured per network protocol in
server.json, or terminated at a reverse proxy in front ofhivemind-core. hivemind-coreemitshive.client.connect/disconnect/connection.errorevents on the OVOS messagebus, and logs rejected connections atERROR.- SQLite and JSON backends are single-node; Redis is the shared backend for running multiple
hivemind-coreinstances against one store.
TLS¶
TLS is configured per network protocol in server.json, not on the command line. The
relevant keys live under network_protocol.hivemind-websocket-plugin (and the HTTP
plugin, if used):
{
"network_protocol": {
"hivemind-websocket-plugin": {
"host": "0.0.0.0",
"port": 5678,
"ssl": true,
"cert_dir": "~/.local/share/hivemind",
"cert_name": "hivemind"
}
}
}
Set ssl to true and point cert_dir/cert_name at the certificate to serve
(<cert_dir>/<cert_name>.crt and .key). TLS is off by default.
Self-signed vs real certificates. On a trusted local network a self-signed
certificate is sufficient; satellites must then be told to accept it by passing
--selfsigned on their connect commands (hivemind-voice-sat, hivemind-voice-relay,
HiveMind-cli, …). For anything exposed beyond the LAN, serve a CA-issued certificate so
satellites validate it normally — or terminate TLS at a reverse proxy (below) and leave
hivemind-core itself plaintext on the loopback interface. See
Security for the certificate guidance.
Reverse proxy¶
For production it is common to terminate TLS at nginx or Caddy in front of the WebSocket
listener rather than configuring ssl on hivemind-core itself. The proxy holds the real (CA-issued)
certificate on 443 and forwards to hivemind-core on 127.0.0.1:5678, upgrading the
WebSocket connection. When you do this, do not also expose 5678/5679 directly to
the internet — only the proxy should be reachable.
The Docker deployment guide covers a concrete proxy setup; see Docker Deployment.
systemd¶
Run hivemind-core as a managed service. Reuse the unit from the
OVOS Skills Server guide:
# /etc/systemd/system/hivemind-core.service
[Unit]
Description=HiveMind Core
After=network.target ovos-messagebus.service
Requires=ovos-messagebus.service
[Service]
Type=simple
User=ovos
ExecStart=/home/ovos/.venvs/ovos/bin/hivemind-core listen
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
The After=/Requires=ovos-messagebus.service lines matter for an OVOS skills server:
its agent protocol talks to ovos-messagebus, which must be up first. An
A2A server or persona server does not require ovos-messagebus
— drop those two lines if you are not running OVOS.
Connection errors and observability¶
Server-side connection failures mostly surface to the client as a silent socket disconnect —
the satellite simply fails to complete the handshake. Server-side, however, hivemind-core emits
internal-bus events on the OVOS messagebus that its agent protocol is wired to (in OVOS
mode this is ovos-messagebus). Rejected connections raise an error event:
| Event | Emitted when |
|---|---|
hive.client.connect |
A client connects (payload carries key, session_id). |
hive.client.disconnect |
A client disconnects (payload carries key). |
hive.client.connection.error |
A connection is rejected — invalid access key or protocol-version mismatch. |
Both rejection paths emit the same hive.client.connection.error event but with
distinct error payload values, so you can tell them apart:
handle_invalid_key_connected(a client presented an unknown / disallowed API key) emits{"error": "invalid access key", "peer": <peer>}and logsClient provided an invalid api key.handle_invalid_protocol_version(a client failed the protocol-version requirements) emits{"error": "protocol error", "peer": <peer>}and logsClient does not satisfy protocol requirements.
An operator can observe invalid-key and bad-protocol-version attempts in two ways:
- Watch the messagebus. Listen for
hive.client.connection.erroron the OVOS messagebushivemind-corepublishes to (for an OVOS skills server, theovos-messagebusthe agent protocol connects to) and inspect theerror/peerfields. This is the structured, real-time signal — wire it into your monitoring to alert on repeated rejected connections from a single peer (a sign of a misconfigured satellite or a brute-force attempt). - Read the logs. The same two handlers log at
ERRORlevel (Client provided an invalid api key/Client does not satisfy protocol requirements), so the rejections are visible injournalctl -u hivemind-coreeven without a bus listener.
Normal hive.client.connect / hive.client.disconnect events on the same bus give you a
running picture of which satellites are attached.
Scaling and multi-instance¶
A single hivemind-core instance keeps client and permission state in its database
backend. The backend choice determines whether you can run
more than one instance against the same state:
- SQLite (default) and JSON are single-node — the database is a local file; only
one
hivemind-coreprocess should own it. - Redis (
hivemind-redis-database) is the shared backend. Point multiplehivemind-coreinstances at the same Redis and they share client records and permissions, so you can run several instances (behind a load balancer, or for redundancy) without each maintaining its own client list. Add a client once and every instance sees it.
Select the backend in server.json under the database block; the same configuration is
read by listen and by every client-management command, so they all operate on the same
store. See Database Backends for the full configuration and
the migrate-db workflow.
Health checking¶
hivemind-core does not expose a dedicated health endpoint, so health checks are
practical rather than built-in:
- Is the WebSocket port accepting handshakes? The most direct liveness probe is a TCP
connect to the configured port (
5678by default) — if the socket accepts the connection the listener is up. A fuller check is to attempt a real client handshake with a known-good API key and confirm it succeeds; ahive.client.connectevent on the bus (and nohive.client.connection.error) confirms an end-to-end healthy path. - Service liveness. Under systemd,
systemctl is-active hivemind-coreand theRestart=on-failurepolicy cover process-level health; pair that with the socket probe above for the network path. - Presence announce/scan. If HiveMind-presence is running
alongside
hivemind-core, ahivemind-presence scanshould find its announcement on the local network — a coarse confirmation that the node is reachable and advertising. Note presence is an optional, separate process fromhivemind-core listen, so its absence does not by itself meanhivemind-coreis down.
Next¶
- Docker Deployment — containerized
hivemind-core, Redis, and the reverse-proxy setup. - Database Backends — single-node vs shared (Redis) state.
- Security — certificates, keys, and permissions.
- Discovery — presence announce/scan for health and reach.
Source¶
Validated against the HiveMind source:
hivemind_core/protocol.py— thehive.client.connect/disconnect/connection.errorevents and the invalid-key vs protocol-version rejection pathshivemind_core/config.py— theserver.jsonschema, per-protocol TLS keys, and the database block