Install with Portainer¶
Portainer is a web interface for Docker. In Portainer, a stack is a group of containers defined by a Docker Compose file. This guide gives two ways to deploy spa2mqtt as a stack.
| Method | Use it when |
|---|---|
| A. Stack from the published image | Normal use. Fast, nothing to build. |
| B. Stack from the repository | Fallback. The host cannot pull from ghcr.io, or you want to run a branch that has no image. |
Both methods take every setting from environment variables and use no bind mounts. A bind
mount maps a file from the host into the container. Portainer under Home Assistant OS
keeps its stack files in a folder that the host cannot see, and the host's /data is
read-only. A bind mount there fails with mkdir /data: read-only file system. Environment
variables avoid that problem.
Check the bus first
Run the read-only monitor once before you install. See Run the read-only monitor below.
A. Stack from the published image¶
- In Portainer, open your environment and select Stacks > Add stack.
- Set Name to
spa2mqtt. -
Select Web editor. Paste the contents of
deploy/portainer-stack.yml:# spa2mqtt stack for Portainer: published image, settings from environment variables only. # # Paste this into Portainer > Stacks > Add stack > Web editor, then add the variables in # the "Environment variables" section below the editor. SPA_IP and MQTT_BROKER are required. # There are no volumes on purpose: Portainer on Home Assistant OS cannot bind-mount files # ("mkdir /data: read-only file system"). # # Guide: https://seanrleach.co.uk/spa2mqtt/install/portainer/ # Jacuzzi J345 through a ProLink module: SPA_IP = the ProLink's address, SPA_PORT=4257, # SPA_DEFINITION=jacuzzi_j345. See https://seanrleach.co.uk/spa2mqtt/tubs/jacuzzi-j345/ services: spa2mqtt: image: ghcr.io/srleach/spa2mqtt:${SPA2MQTT_TAG:-2} container_name: spa2mqtt restart: unless-stopped environment: SPA_IP: ${SPA_IP:?Set SPA_IP to the RS485-to-TCP adapter address} SPA_PORT: ${SPA_PORT:-8899} SPA_DEFINITION: ${SPA_DEFINITION:-jacuzzi_j235} # SAFETY: false = receive-only. Read the Safety page before you set true. SPA_TRANSMIT: ${SPA_TRANSMIT:-false} MQTT_BROKER: ${MQTT_BROKER:?Set MQTT_BROKER to the MQTT broker address} MQTT_PORT: ${MQTT_PORT:-1883} MQTT_USERNAME: ${MQTT_USERNAME:-} MQTT_PASSWORD: ${MQTT_PASSWORD:-} LOG_LEVEL: ${LOG_LEVEL:-INFO} -
Below the editor, find Environment variables. Select Add an environment variable for each value in the table. You can also select Advanced mode and paste
NAME=valuelines.Variable Required Example Meaning SPA_IPYes 192.168.1.100Address of the RS485-to-TCP adapter (or the ProLink module) MQTT_BROKERYes 192.168.1.7Address of the MQTT broker MQTT_USERNAMEIf the broker needs a login spaBroker user name MQTT_PASSWORDIf the broker needs a login Broker password SPA_PORTNo 8899TCP port of the adapter. 4257for a ProLink moduleSPA_DEFINITIONNo jacuzzi_j235Tub definition. jacuzzi_j345for a J345SPA_TRANSMITNo falseLeave falseuntil you have read SafetyLOG_LEVELNo INFODEBUGfor more detailSPA2MQTT_TAGNo 2Image tag. See Releases and versions The stack refuses to deploy if
SPA_IPorMQTT_BROKERis missing. This stops a container that would only log connection errors.For a Jacuzzi J345 with a ProLink module, the J345 guide lists the values.
-
Select Deploy the stack.
In Home Assistant, open Settings > Devices & services > MQTT. A device named after the tub definition, for example Jacuzzi J235, appears within a few seconds. Its buttons and the setpoint show as unavailable while transmit is off. That is expected.
Home Assistant OS host addresses
If the MQTT broker is the Mosquitto add-on on the same Home Assistant OS host, set
MQTT_BROKER to the host's LAN address. The name core-mosquitto resolves only on
the add-on network, not on the network that Portainer stacks use.
Update¶
The tag 2 follows every 2.x.y release. To get the newest image for the tag:
- Open Stacks > spa2mqtt.
- Select Editor, then Update the stack.
- Turn on Re-pull image and redeploy, then select Update.
Without the re-pull option, Portainer reuses the image that it already has. On some Portainer versions the same action is named Pull and redeploy.
Roll back or pin a version¶
Set SPA2MQTT_TAG to a full version, for example 2.0.0, then update the stack. The
container stays on that version until you change the variable.
B. Stack from the repository (build)¶
This method makes Portainer clone the repository and build the image on the Docker host. Building takes a few minutes and needs internet access to PyPI and Docker Hub.
- Select Stacks > Add stack, set Name to
spa2mqtt, and select Repository. - Set Repository URL to
https://github.com/srleach/spa2mqtt. - Set Repository reference to a release tag such as
refs/tags/v2.0.0. A tag gives you a known version.refs/heads/mainbuilds the newest code. - Set Compose path to
docker-compose.yml. This is the development compose file at the repository root. It builds from source and has no bind mounts. - Add the same Environment variables as in method A.
SPA2MQTT_TAGhas no effect here. - Select Deploy the stack.
To update, change the reference if needed, then select Pull and redeploy on the stack page. Portainer fetches the repository again and rebuilds the image.
Set or change environment variables¶
Open Stacks > spa2mqtt > Editor. The Environment variables section is below the compose editor. Change a value, then select Update the stack. Portainer recreates the container with the new values.
Read the logs¶
- Open Containers and select
spa2mqtt. - Select Logs.
- Turn on Auto-refresh logs to follow new lines.
The log shows the adapter and broker connections, warnings, and whether transmit is enabled.
Run the read-only monitor¶
The monitor decodes the bus and never transmits. Stop the spa2mqtt container first,
because most adapters accept only one TCP client.
- Open Containers, select
spa2mqtt, and select Stop. - Select Containers > Add container.
- Set Name to
spa2mqtt-monitorand Image toghcr.io/srleach/spa2mqtt:2. - Under Advanced container settings > Command & logging, set Command to
spa2mqtt monitor 192.168.1.100(your adapter's address). Add-p PORTand-d DEFINITIONif yours are not8899andjacuzzi_j235, for examplespa2mqtt monitor 192.168.1.50 -p 4257 -d jacuzzi_j345. Set Console to Interactive & TTY. - Under Restart policy, select Never.
- Select Deploy the container, then open its Logs. A report appears at once and then every 10 seconds.
- When you are done, stop and remove
spa2mqtt-monitor, then startspa2mqttagain.
If you have a shell on the Docker host, this one line does the same:
Enable transmit¶
Read Safety first. Then set SPA_TRANSMIT to true in the stack's
environment variables and update the stack. The log shows TRANSMIT ENABLED. To go back
to receive-only, set it to false and update the stack again.
Limits of an environment-only setup¶
The ha: settings (unique_id_prefix, legacy_topics, device_name and others) and a
USB serial adapter need a config.yml, and Portainer under Home Assistant OS cannot mount
one. The defaults suit almost every install: the device name and identifier come from the
tub definition. If you need to change them, run spa2mqtt with
Docker Compose on a host that allows bind mounts.