Deployment
14 min
the node runs as a container in either of two modes inside litmus edge it finds the instance on its own, needing no hostname and no nats credentials — the normal production deployment outside litmus edge it reads the same devices and publishes the same sparkplug messages, but you supply the litmus edge address and credentials for its nats broker quick start # covers the marketplace path and the verification steps; this page covers everything else inside litmus edge use these steps when you manage the container yourself rather than through the marketplace download the image archive from litmus central https //portal litmus io/accelerators/le sparkplug edge node?tab=downloads , or pull it from the registry if you have registry access in litmus edge, navigate to applications > images, then upload and import the archive navigate to applications > containers, click run, and enter the command see overview of docker run https //docs litmus io/litmusedge/product features/applications/containers/overview of docker run docker run d name le sparkplug restart unless stopped \\ v le sparkplug data /le sparkplug/data \\ e edge api token="\<litmus edge api token>" \\ e group id="plant1" \\ e node id="line1" \\ e mqtt url="tcp\ //192 168 1 20 1883" \\ le sparkplug\ v2 0 1 with registry access, use the registry path in place of the local image name us docker pkg dev/litmus customer facing/litmus solutions/le sparkplug\ v2 0 1 there is no latest tag, so the version is always explicit the node reaches litmus edge through the docker gateway, which it detects from the container's default route set edge docker gateway ip to name that gateway explicitly when detection does not find the right one add p 9090 9090 to reach the metrics and health endpoints from outside the container outside litmus edge external mode adds two things to the deployment above the litmus edge address, and credentials for its nats broker beyond the quick start prerequisites # , it needs litmus edge reachable from the container host by hostname or ip address an api account, whose api key gives the node access to the litmus edge nats broker see create an api account https //docs litmus io/litmusedge/product features/system/access control/tokens/create api account the nats proxy enabled on the litmus edge instance see tokens https //docs litmus io/litmusedge/product features/system/access control/tokens docker run d name le sparkplug restart unless stopped \\ v le sparkplug data /le sparkplug/data \\ e edge external="true" \\ e edge hostname="edge 01 plant example com" \\ e edge api token="\<litmus edge api token>" \\ e edge access account api key="\<api account api key>" \\ e group id="plant1" \\ e node id="line1" \\ e mqtt url="tcp\ //192 168 1 20 1883" \\ us docker pkg dev/litmus customer facing/litmus solutions/le sparkplug\ v2 0 1 setting effect edge external=true switches to external mode, where the litmus edge address must be given explicitly edge hostname hostname or ip address of the litmus edge instance required in external mode edge access account api key api account key the node builds the nats connection tls\ //admin \<key>@\<edge hostname> 4222 from it the generated connection always uses port 4222, so a port in edge hostname applies to the api only keys containing characters such as / or a space need no escaping — the node encodes them connect with an explicit nats url set nats url when the generated connection does not fit, such as a non default port or a user other than admin it takes precedence over edge access account api key , which is then unnecessary e nats url="tls\ //admin \<api account api key>@edge 01 plant example com 4222" the scheme decides encryption tls\ // connects over tls, nats\ // connects without it edge hostname is still required, because the node reaches the litmus edge api through it — only the nats connection comes from nats url persist the data directory the node keeps its sparkplug state in /le sparkplug/data every deployment path mounts the docker volume le sparkplug data there, which is also what the marketplace application does path in the container contents seqnum/\<group> \<node> bdseq txt the birth/death sequence number for the next mqtt session \<group> \<node> db/ the store and forward buffer, when that feature is enabled config/config json the configuration file, when you use one a configuration file goes at config/config json inside the volume see configuration # for the file format upgrade to a new version state lives in the volume, not the container, so an upgrade replaces the container and keeps the volume note the sparkplug group id, node id, and volume name of the running container, then stop and remove it deploy the new version with the same group id, node id, and volume name confirm the handover on the broker ndeath from the old session, then nbirth from the new one, carrying the next birth/death sequence number secure the mqtt connection with tls the node connects over tls when the broker url uses the ssl // or mqtts\ // scheme and you supply the certificate authority that signed the broker's certificate add a client certificate and key when the broker requires mutual tls certificates are supplied as base64 encoded text, not file paths, because the node reads them from settings rather than from disk encode the certificates encode each pem file, including its begin and end lines, as a single line of base64 base64 < ca pem | tr d '\n' base64 < client crt | tr d '\n' base64 < client key | tr d '\n' \[convert] tobase64string(\[io file] readallbytes("ca pem")) \[convert] tobase64string(\[io file] readallbytes("client crt")) \[convert] tobase64string(\[io file] readallbytes("client key")) the output must be one unbroken string a base64 value with line breaks in it fails to decode configure the connection purpose marketplace parameter environment variable broker url, tls scheme mqtt broker url mqtt url ca certificate mqtt ca certificate mqtt ca cert client certificate mqtt client certificate mqtt client cert client private key mqtt client key mqtt client key skip verification not exposed mqtt skip cert verify the equivalent config json fields sit on each broker object — see configuration # the url scheme decides whether the connection is encrypted at all ssl // and mqtts\ // use tls, tcp\ // and mqtt // do not no other schemes are accepted, so a tls\ // broker url is rejected at startup mqtt skip cert verify turns off verification of the broker's certificate the connection stays encrypted, but the node accepts any certificate the broker presents it is deliberately absent from the marketplace form, so setting it takes a configuration file or a self managed container multiple brokers with different authorities a configuration file carries one certificate set per broker, which is the reason to prefer a file when brokers have different certificate authorities { "edge api token" "\<litmus edge api token>", "group id" "plant1", "node id" "line1", "mqtt" { "servers" \[ { "url" "ssl //broker a example com 8883", "user" "sparkplug", "password" "\<password>", "ca cert" "\<base64 ca certificate>", "client cert" "\<base64 client certificate>", "client key" "\<base64 client key>" }, { "url" "ssl //broker b example com 8883", "ca cert" "\<base64 ca certificate>" } ] } } the node publishes to one broker at a time and moves to the next in the list when the session ends certificate errors a successful tls connection logs connected from the mqtt component with the ssl // url in the server field, followed by birth set published certificate problems are logged and do not stop the node from starting message from mqtt meaning decode ca cert base64 the ca value is not valid base64 the node continues with the system trust store, and the client certificate is skipped decode client cert base64 the client certificate value is not valid base64 decode client key base64 the client key value is not valid base64 load client certificate and key the pair decoded but do not form a usable key pair, so the certificate and key do not match the first three are most often caused by line breaks surviving the encoding verify the deployment follow quick start # steps 2 and 3 — the log messages and broker topics are the same in both modes outside litmus edge, read the logs with docker logs le sparkplug and add p 9090 9090 to reach the health endpoint curl i http //127 0 0 1 9090/healthz 200 ok means the mqtt session is up 503 unavailable means it is not, or that host application gating is enabled and the host has not reported online yet in external mode, if the nats component never logs connected , the api account key or the nats proxy is the place to look if nats connects but the birth set reports no devices, the node reached the nats broker while the api returned nothing — check the api token and the hostname the generated nats connection is encrypted, but the node does not verify the litmus edge certificate, because litmus edge presents a self signed certificate the same applies to its calls to the litmus edge api sparkplug requires the birth/death sequence number to keep advancing from one session to the next lose this volume and the node restarts that counter, so host applications read the new session as out of order and mark the node stale keep the volume, and its name, across upgrades never run two nodes with the same sparkplug group id and node id, and never point two containers at the same volume either one puts two sparkplug identities on the same topics and corrupts the sequence number state the client certificate and key are read only when a ca certificate is also set supplying a client pair on its own leaves the connection without client authentication, and nothing in the configuration is rejected skipping verification removes protection against an attacker impersonating your broker use it only to isolate a certificate problem in testing, and never in production the fix in production is to supply the correct ca certificate