uptrakit

Home Assistant and MQTT Integration

Home Assistant and MQTT Integration

Uptrakit integrates with MQTT brokers to publish software version state. Once an MQTT client is configured and connected, Uptrakit publishes the installed and latest versions for every tracked software item to the broker automatically. Home Assistant Discovery is an optional layer on top that creates update entities in Home Assistant — one per tracked software item per host — so you can view versions and trigger updates from the Home Assistant UI.

Uptrakit also publishes per-host summary entities: a single update entity per host summarising the overall state of all non-featured software items (APT packages, Homebrew formulae, npm globals, etc.) on that host. See Host Summary Update Entities below.

Startup state delivery

When an MQTT service first connects, the controller delivers the complete current state as a series of host-batched pages (up to 100 active hosts per page). The MQTT service accumulates all pages before publishing retained topics to the broker. For small tenants this is typically a single message; for large deployments it is transparent — retained topics appear on the broker once the last page is received.

MQTT State Topics (always active)

Once an MQTT client is enabled and connected to the broker, Uptrakit publishes the following retained topics for every (software item, host) pair regardless of whether Home Assistant Discovery is enabled:

TopicRetainedPurpose
{prefix}/hosts/{host_id}/items/{item_id}/stateInstalled version string (empty if unknown)
{prefix}/hosts/{host_id}/items/{item_id}/latest_versionLatest available version string (empty if unknown)
{prefix}/hosts/{host_id}/items/{item_id}/attributesJSON attributes (see below)
{prefix}/hosts/{host_id}/items/{item_id}/setCommand topic — publish "install" to trigger an update

The items/{item_id}/attributes payload contains:

{
  "in_progress": false,
  "update_category": "security",
  "release_date": "2025-01-15",
  "last_checked_at": "2025-01-15T12:00:00Z"
}
FieldTypeDescription
in_progressbooleantrue while an update is pending or executing
update_categorystring?Classification of the pending update: "security", "bugfix", "feature", or "unknown". Absent if no update is available.
release_datestring?ISO 8601 date of the latest release ("YYYY-MM-DD"). Absent when release metadata is unavailable.
last_checked_atstring?ISO 8601 timestamp of the last installed-version check. Absent if never checked.

Additionally, Uptrakit publishes the following retained identity and metadata topics per host:

TopicRetainedPurpose
{prefix}/hosts/{host_id}/hostnameRaw hostname string
{prefix}/hosts/{host_id}/friendly_nameUser-defined display name
{prefix}/hosts/{host_id}/infoJSON: OS type, OS version, architecture
{prefix}/hosts/{host_id}/tagsJSON array of tag names assigned to the host
{prefix}/hosts/{host_id}/agentJSON: agent last-seen timestamp and version
{prefix}/hosts/{host_id}/connectivity/state"online" or "offline" — real-time agent connectivity
{prefix}/hosts/{host_id}/connectivity/attributesJSON: {"last_seen": "…", "version": "…"}

The info payload:

{ "os_type": "linux", "os_version": "Ubuntu 24.04", "architecture": "x86_64" }

The tags payload:

["production", "web-server"]

The agent payload:

{ "last_seen": "2025-01-15T12:00:00Z", "version": "1.2.3" }

The connectivity/state topic is published immediately when an agent connects or disconnects and is propagated across all controllers via NATS. It reflects live connection status, not a stale DB poll.

For every host that has at least one tracked non-featured software item, Uptrakit also publishes:

TopicRetainedPurpose
{prefix}/hosts/{host_id}/state"unknown" when updates pending, "up-to-date" otherwise
{prefix}/hosts/{host_id}/latest_version"N available" when updates pending, "up-to-date" otherwise
{prefix}/hosts/{host_id}/attributesJSON: package update summary (see below)
{prefix}/hosts/{host_id}/setCommand topic — publish "install" to update all outdated non-featured items
{prefix}/hosts/{host_id}/security/state"unknown" when security updates pending, "up-to-date" otherwise
{prefix}/hosts/{host_id}/security/latest_version"N available" when security updates pending, "up-to-date" otherwise
{prefix}/hosts/{host_id}/security/attributesJSON: {"in_progress": bool, "pending_count": N}
{prefix}/hosts/{host_id}/security/setCommand topic — publish "install" to update security packages only

The hosts/{host_id}/attributes payload contains:

{
  "in_progress": false,
  "pending_count": 5,
  "total_count": 142,
  "bugfix_count": 3,
  "feature_count": 1
}
FieldTypeDescription
in_progressbooleantrue while a batch update is pending or executing
pending_countintegerPackages with an available update (any category)
total_countintegerTotal tracked packages on this host
bugfix_countintegerPending packages classified as "bugfix"
feature_countintegerPending packages classified as "feature"

Where {prefix} is the Topic Prefix configured on the MQTT client (default: uptrakit).

All topics update automatically whenever a version check completes, an update is triggered, an update finishes, or host tags are changed. No extra configuration is required.

Prerequisites

Before enabling Home Assistant Discovery:

  1. An MQTT broker is reachable by both Uptrakit and Home Assistant (e.g. Mosquitto).
  2. An MQTT client is configured via the MQTT Clients shared surface in the Uptrakit UI (found under the Configuration section in Settings) and the MQTT service is running and connected to the broker.
  3. Home Assistant has the MQTT integration enabled and pointed at the same broker.
  4. At least one agent is connected and has performed a version check for the software items you want to track. Items whose versions are not yet known will appear but show no version data until the first version check completes.

Enabling Home Assistant Discovery

Discovery is configured per MQTT client:

  1. Navigate to Settings and open the MQTT Clients tab (under the Configuration section).
  2. Click Create Client to add a new client, or click the row action on an existing one and select Edit.
  3. Enable the Home Assistant Discovery toggle.
  4. Optionally change the Discovery Prefix (default: homeassistant). This must match the MQTT Discovery prefix configured in Home Assistant (default is also homeassistant).
  5. Save the configuration.

The CLI no longer has direct MQTT client commands. All MQTT client management is performed through the MQTT Clients shared surface in the web interface.

What Entities Are Created

Uptrakit creates one Home Assistant update entity for every (software item, host) combination where:

  • The software item is enabled, featured, and not deactivated.
  • The host is active (not deactivated) and assigned to the software item.

Each entity displays:

AttributeDescription
Installed versionThe currently installed version on the host (blank if unknown)
Latest versionThe newest available version (blank if unknown)
Update availabletrue when latest > installed
In progresstrue while an update is pending or executing (displays a spinner in the HA UI)
Update categoryClassification of the pending update ("security", "bugfix", "feature", "unknown") — shown as an entity attribute when an update is available
Release dateDate of the latest release (when available from release metadata)
Last checked atTimestamp of the most recent installed-version check
Release URLLink to the upstream release page (GitHub releases only; absent otherwise)
Release summaryFirst 500 characters of the release notes (GitHub releases only; absent otherwise)
Entity pictureSoftware item icon/logo displayed as a thumbnail in the HA dashboard (when an icon URL is set on the software item)

When the plugin for a software item fetches releases from GitHub, Uptrakit includes release_url and release_summary in the HA MQTT discovery config for each entity. Home Assistant surfaces these as entity attributes, giving users a direct link to the GitHub release page and a preview of the changelog without leaving Home Assistant.

For plugins that only track version numbers (e.g. apt, Homebrew, Docker Hub) the release_url and release_summary attributes are omitted from the discovery config.

App icons

Each software item supports an optional icon_url field (HTTPS only, max 2048 characters). When set, the URL is included as entity_picture in the HA MQTT discovery config. Home Assistant displays this image as the entity thumbnail in the dashboard and in lovelace cards. To set or update an icon URL, edit the software item in the Uptrakit web UI or pass --icon-url to the CLI.

Dual availability

Each software item update entity in Home Assistant requires both the Uptrakit MQTT service and the target host's agent to be online before it reports as available. This is implemented using HA's availability array with availability_mode: "all":

availability:
  - topic: "{prefix}/status"
    payload_available: "online"
    payload_not_available: "offline"
  - topic: "{prefix}/hosts/{host_id}/connectivity/state"
    payload_available: "online"
    payload_not_available: "offline"
availability_mode: all

The host packages and host security entities use the same dual-availability configuration.

The connectivity binary sensor itself retains a single availability_topic pointing only to the MQTT service status ({prefix}/status). Using the agent connectivity state as a prerequisite for the connectivity sensor would be circular — the connectivity sensor's state is the agent status.

All entities for a given host — featured software items, host summaries, security updates, and the connectivity sensor — are grouped under a single HA device per host. The device is identified by uptrakit_host_{tenant_id_hex}_{host_id_hex} and named after the host's friendly name (the user-defined display name set on each host). This means all software items, packages, security, and connectivity entities for a host appear together under one device in Home Assistant.

Each software item entity is named after the software item (e.g. "nginx"). Entity IDs are assigned on first registration using a stable default_entity_id in the form update.uptrakit_{friendly_name_slug}_{item_slug}, where slugs are lowercase with non-alphanumeric characters replaced by underscores. For example, software item "uptrakit pangolin" on a host with friendly name "pangolin.uk.home.yantsen.su" gets the entity ID update.uptrakit_pangolin_uk_home_yantsen_su_uptrakit_pangolin.

Triggering Updates from Home Assistant

When an update is available, an Install button appears on the entity card. Pressing it sends an MQTT command to Uptrakit via the command topic for that entity.

Uptrakit validates the request and, if accepted, creates an update_history record with:

  • actor_type = "mqtt"
  • actor_id = <actor_service_id> (the UUID of the MQTT service instance that received the command)

The update is then dispatched to the appropriate agent exactly as if it had been triggered from the web UI or CLI.

In-progress state feedback: Uptrakit immediately publishes {"in_progress": true} to the {prefix}/hosts/{host_id}/items/{item_id}/attributes topic after accepting the update command. Home Assistant recognises this attribute on the update entity and displays a spinner. Once the agent reports the final result (completed or failed), Uptrakit publishes updated state topics including {"in_progress": false}.

Uptrakit never triggers updates automatically. Update execution always requires an explicit user action — from the web UI, CLI, or Home Assistant.

Host Summary Update Entities

In addition to per-software-item entities, Uptrakit creates two Home Assistant update entities per host for non-featured software tracking. Both represent auto-discovered packages (APT, Homebrew, npm, etc.) grouped at the host level.

Both host summary entities are disabled by default in Home Assistant. You must explicitly enable them in Settings > Devices & Services > Entities before they appear in your dashboard. This prevents noise for users who do not need package-level tracking in HA.

All-packages entity ({friendly_name} packages)

Tracks all outdated non-featured items on the host regardless of category.

Security updates entity ({friendly_name} security updates)

Tracks only non-featured items where update_category = "security". Pressing Install on this entity applies only security updates, leaving other pending updates in place.

When Are the Entities Created

Both entities are published when:

  • The host has at least one enabled, non-deactivated, non-featured software item tracked.
  • The MQTT client is connected and has the host's tenant assigned.

If a host has no tracked non-featured items, no entities are published for it.

What the Entities Show

Pendingstate (installed)latest_versionHA behaviour
0"up-to-date""up-to-date"No update badge
N > 0"unknown""N available"Update badge, shows "N available"

Home Assistant shows the Update available badge whenever installed_version != latest_version. When updates are pending, state is "unknown" (there is no single aggregate installed version) and latest_version shows the count, triggering the badge.

Each entity exposes the following attributes:

AttributeTypeDescription
in_progressbooleantrue while a batch update is pending or running
pending_countintegerNumber of qualifying packages with an available update
total_countintegerTotal tracked packages on this host (all-packages entity only)
bugfix_countintegerPending packages classified as "bugfix" (all-packages entity only)
feature_countintegerPending packages classified as "feature" (all-packages entity only)

Triggering a Host Batch Update from Home Assistant

When at least one update is available, an Install button appears on the entity card.

All-packages entity: Pressing Install sends an MQTT command to {prefix}/hosts/{host_id}/set. The controller finds all outdated non-featured items and dispatches a batch update.

Security entity: Pressing Install sends an MQTT command to {prefix}/hosts/{host_id}/security/set. The controller filters the batch to only items with update_category = "security".

In both cases, Uptrakit validates the request and, if accepted:

  1. Finds the qualifying outdated items (all, or security-only).
  2. Creates an update_history record per item and a single update_batch.
  3. Sends an execute_batch_update command to the agent for each plugin group.
  4. Immediately sets in_progress: true in the attributes topic so the HA spinner appears.

Once the agent completes the update, Uptrakit updates installed versions and publishes fresh state topics, returning in_progress: false and recalculating pending_count.

It is not possible to select individual non-featured items via the HA Install button. Individual item control is available via the Uptrakit web UI.

Device and Entity Naming

All entities (featured software items, host summaries, security) are grouped under a single HA device per host:

  • Device: identifiers: ["uptrakit_host_{tenant_hex}_{host_hex}"], name: {friendly_name}
EntityUnique IDNameDefault entity ID
Software itemuptrakit_{tenant_hex}_{host_hex}_{item_hex}{item_name}update.uptrakit_{fn_slug}_{item_slug}
All-packagesuptrakit_{tenant_hex}_{host_hex}_pkgs{friendly_name} packagesupdate.uptrakit_{fn_slug}_packages
Securityuptrakit_{tenant_hex}_{host_hex}_sec{friendly_name} security updatesupdate.uptrakit_{fn_slug}_security_updates
Connectivityuptrakit_{tenant_hex}_{host_hex}_conn{friendly_name} agentbinary_sensor.uptrakit_{fn_slug}_agent

Where {tenant_hex} and {host_hex} are UUID strings with dashes removed, and {fn_slug} is the friendly name slugified (lowercased, non-alphanumeric characters replaced by underscores).

Agent Connectivity Sensor

Uptrakit creates one Home Assistant binary_sensor entity per host to report whether the Uptrakit agent for that host is currently connected to the controller.

Entity properties

PropertyValue
Platformbinary_sensor
Device classconnectivity
State ONAgent is connected ("online")
State OFFAgent is disconnected ("offline")
Enabled by defaultYes

Unlike the update entities (which are disabled by default), the connectivity sensor is enabled by default because knowing whether an agent is reachable is core operational information.

How it works

The connectivity state is published immediately to {prefix}/hosts/{host_id}/connectivity/state ("online" or "offline") whenever:

  • An agent successfully connects and is approved by the controller.
  • An agent WebSocket connection closes (graceful disconnect, network drop, or process exit).

The event is propagated across all controllers via NATS (HostConnectivityUpdated), so the MQTT service sees the correct state regardless of which controller the agent is connected to. It is not derived from a database poll.

Additional attributes are available on the {prefix}/hosts/{host_id}/connectivity/attributes topic:

{ "last_seen": "2025-01-15T12:34:56Z", "version": "1.2.3" }

The last_seen field is updated on each agent connect and disconnect event. The version field reflects the agent version reported at connect time (null when the agent just disconnected).

Reconnect Resilience

If the MQTT broker restarts or the connection is interrupted, Uptrakit automatically republishes all state and version topics (and Home Assistant discovery configs, if HA Discovery is enabled) when the connection is re-established. This ensures the broker always has current retained data after network events.

If Home Assistant restarts while the broker and Uptrakit remain connected, Uptrakit detects the HA birth message (online on {ha_discovery_prefix}/status) and immediately republishes all HA discovery configs so HA picks them up fresh. State and version topics remain retained on the broker and do not need re-sending. This follows the standard HA MQTT birth/will pattern.

High Availability and Workload Distribution

When multiple MQTT service instances are deployed, each instance exclusively owns a subset of MQTT client configurations via the workload claim protocol. A tenant's clients may be spread across different instances, but each individual client is served by exactly one instance.

If an MQTT instance disconnects, its claimed clients become available and are automatically re-assigned to other running instances. Home Assistant entities may briefly become unavailable during the transition but will recover automatically once the new instance starts serving.

Automatic Stale Entity Cleanup

When software items are deactivated and recreated (for example, during Docker container re-discovery), they receive new UUIDs. Each UUID produces a distinct HA discovery config topic. Without cleanup, the old retained topic remains on the broker, causing Home Assistant to show ghost entities with stale version data.

Uptrakit automatically detects when items or hosts are removed from a tenant's state and publishes empty retained payloads to the corresponding topics. This clears the stale retained messages from the broker and causes Home Assistant to remove the orphaned entities. The cleanup covers:

  • Removed software item/host pairs: state, latest_version, attributes, and HA discovery config topics are cleared; command topic subscriptions are removed.
  • Removed host summaries: packages and security entity topics (state, latest_version, attributes, command, and HA discovery config) are cleared.
  • Removed host metadata: hostname, friendly_name, info, tags, agent, and connectivity topics (including HA discovery config for the connectivity sensor) are cleared.

Cleanup runs automatically on every state update push. No manual intervention is required.

Why Some Software Items May Not Appear

SymptomCause
Item not visible in HASoftware item is not featured (non-featured items appear in host summary entities)
Item not visible in HASoftware item or host is deactivated
Entity shows blank versionsVersion check has not run yet since the MQTT client was configured
Entity shows blank versionsNo agent is connected for that host
No entities at allHA discovery not enabled on the MQTT client
No entities at allMQTT service is not connected to the broker
No entities at allHA MQTT integration not configured for the same broker
State topics absent on brokerMQTT client not enabled or MQTT service not running

Custom CA Certificates for Private Brokers

When connecting to MQTT brokers that use a private or internal certificate authority (e.g. self-signed certificates or enterprise CAs), you can provide a custom CA certificate in PEM format.

This is configured per MQTT client in the MQTT Clients extension (found under the Configuration section in Settings):

  1. Create or edit an MQTT client.
  2. Set the transport to TLS.
  3. Paste the CA certificate PEM into the CA Certificate (PEM) field.
  4. Save the configuration.

The CA certificate is encrypted at rest using AES-256-GCM and transmitted to the MQTT service via the wire protocol. The MQTT service uses the provided PEM as the trusted CA for TLS connections instead of the system trust store. See Secrets and Encryption for details.

If no custom CA is provided, the MQTT service falls back to the system trust store (default behavior for public brokers).

Security Notes

  • MQTT credentials (username, password, CA certificate) are stored encrypted at rest using AES-256-GCM. See Secrets and Encryption.
  • The MQTT command topics that accept Install commands are scoped per entity and are accessible to anyone with publish access to the broker. Ensure your broker uses authentication and access control to limit who can publish to Uptrakit command topics.
    • Software item command topics: {prefix}/hosts/{host_id}/items/{item_id}/set
    • Host summary command topics: {prefix}/hosts/{host_id}/set
    • Host security command topics: {prefix}/hosts/{host_id}/security/set
  • The new read-only topics (info, tags, agent, connectivity/*) expose OS metadata, organisational tags, and agent version/connectivity. This information is also available in the Uptrakit web UI. The ip_address field is intentionally not published to avoid exposing network topology.
  • Update requests received via MQTT are validated by the controller (same checks as REST API triggers):
    • Tenant scope verification (the MQTT client must be assigned the same tenant as the target resource).
    • Host assignment and agent approval checks.
    • Duplicate update prevention (no two concurrent updates for the same host).

Troubleshooting

Discovery topics are published but Home Assistant doesn't see any entities:

  • Confirm HA MQTT integration is pointed at the same broker.
  • Confirm the discovery prefix in Uptrakit matches HA's MQTT discovery prefix (default homeassistant).
  • In HA, go to Settings > Devices & Services > MQTT and check whether discovery is enabled.

Install button not visible:

  • The Install button only appears when latest_version > installed_version. Verify that the version check has run and the latest version is populated (visible in the Uptrakit web UI under the software item's version list).

MQTT service is connected but no version data is pushed:

  • Check that at least one agent has reported version check results for the relevant software items.
  • Manually trigger a version check: uptrakit check --item <id> or from the web UI.
  • After the check completes, Uptrakit automatically pushes updated states to connected MQTT services.

Update command received but nothing happens:

  • Check the Uptrakit controller logs for service_trigger_update errors.
  • Verify the agent for the target host is connected (uptrakit services list or the web UI).
  • Check whether an update is already pending for that (host, software item) pair in the update history.