Skip to main content
Once a device has an identity (see Enrollment), Omega opens a long-lived session to the platform’s MQTT broker and subscribes the control topics for every module it runs. This page covers the transport, the connection block that configures it, and the full topic namespace so you know exactly what a device publishes and subscribes.

Transports

The transport is chosen by connection.transport: For transport: mqtt, the security of the link comes from the scheme of connection.server_url:
MQTT-over-QUIC is available when the binary is built with the mqtt-quic feature. Without that feature the QUIC path is not compiled in, so a quic:// URL on a default build is rejected at startup rather than silently falling back.

The connection block

The essentials — see Configure for the complete schema, every field, and its _env override.
A few things worth calling out:
  • cert_dir is where identity lives, for the life of the device. Enrollment writes device.crt, device.key, and metadata.json here, and certificate renewal writes the renewed certificate here too. Keep it stable — it deliberately sits at the connection level, not inside jitr, so it outlives the enrollment block after that block is removed.
  • keep_alive is the tuning knob for how fast a device that went dark (power loss, black-holed network) is detected as gone. The broker tears the session down at ~1.5× this value with no traffic. Default 30s → ~45s detection. Lower it for faster detection at the cost of more keepalive chatter.
  • Any string field has an _env twin (server_url_env, device_id_env, root_topic_env, the TLS paths, mqtt.username_env / password_env). Set the _env field to an environment-variable name and Omega reads the value at load time — the way to keep per-device identity and secrets out of a shared config.

The topic namespace

Every topic a module uses is built under a single root topic:
  • If connection.root_topic (or root_topic_env) is set, that is the root verbatim.
  • If it’s left empty, the root defaults to omega/{device_id}.
Under that root, topics follow a consistent shape:
So for a device with device_id: press-42 and no explicit root, its OTA plan topic is omega/press-42/ota/control/plan.
Two module namespaces do not use their own name on the wire, for backward compatibility. The service-runtime module publishes/subscribes under devices/, not service/. This matters when you subscribe from the platform side or debug with mosquitto_sub — match the wire topic in the table below, not the module name.

Topic reference

Root below is {root} = connection.root_topic (default omega/{device_id}). sub = device subscribes (platform → device); pub = device publishes (device → platform).

OTA (core — always present)

Inventory — SBOM / HBOM / PBOM (core, hosted by OTA)

Omega reports digests routinely and sends the full BOM on request or on change, so a large payload only crosses the wire when something actually changed.

Node capabilities (core)

Service runtime (service-runtime feature — publishes under devices/)

Certificate management (core — platform-namespaced)

Certificate topics are not under root_topic. They live in the platform’s $golain control tree, keyed by the device’s platform UUID: {uuid} is the platform device UUID (taken from the certificate serial number). Renewal runs on a background timer — see Enrollment → Renewal.
Modules the profile does not list do not subscribe or publish anything. The table above is the complete set for the current module lineup; deprecated modules that some builds still carry use their own legacy topics and are out of scope here.

Online means fully subscribed

When Omega connects, it subscribes every control topic for every module in modules.required and waits for the broker to acknowledge each one (SUBACK). A subscription the broker denies is fatal — Omega tears down rather than run in a state where the platform believes it can control the device but a topic silently isn’t wired up. The guarantee this buys you: if a device shows online, every control topic it needs is subscribed and acknowledged. There is no half-controllable state. When a device won’t come up and the logs point at a denied subscription, it’s an ACL/permissions problem on the broker for that device’s topics — not something the device can paper over. See Operations for the exact failure surface (exit code, startup-error.log).

See also