Skip to main content
Version: Pro Edition for Eclipse Mosquitto 3.2

Server Certificates

Docker & Linux RPM Setup

Prerequisites

Ensure you have the following files ready before configuring Mosquitto:

  • Server Certificate (server.crt): The public server certificate.
  • Private Key (server.key): The private key associated with the server certificate.

Configuring Pro Edition for Eclipse Mosquitto Broker with a Server Certificate

This document outlines the two available methods for configuring a broker with a server certificate: using a proxy for TLS termination or configuring TLS directly on the broker. In cluster environments, the use of HAProxy, as provided in the default setup, is recommended for managing TLS termination.

Pro Edition for Eclipse Mosquitto TLS termination

Open your mosquitto.conf file to add a certificate to a certain port. Add or modify the following settings to configure the Pro Edition for Eclipse Mosquitto broker to use the server certificate:

# Enable a listener on port 8883 for SSL/TLS connections
listener 8883
protocol mqtt

# SSL/TLS certificate paths
certfile /path/to/server.crt
keyfile /path/to/server.key
  • listener 8883: Sets the port for SSL/TLS communication. Port 8883 is the standard MQTT SSL/TLS port.
  • certfile: Specifies the path to the server's public certificate file.
  • keyfile: Specifies the path to the server's private key file.
HA Proxy TLS termination

In a cluster setup an HA Proxy is used for TLS termination. This is the default config of the frontend haproxy.cfgfile:

frontend mqtt_frontend
bind *:1883
mode tcp
default_backend mqtt_backend
timeout client 10m

In order to enable TLS termination here add the following behind the bind *:<port> parameter: ssl crt /path/to/certs/server.pem This will do the TLS termination at the frontend stage before routing the traffic further to the set backend (here mqtt_backend ).

Client connections

Use an MQTT client to connect to the broker using the secure port (e.g., 8883) to verify that the server certificate is being used:

mosquitto_sub -h <broker-ip> -p 8883 -t test/topic --cafile /path/to/ca.crt

In this example, a --cafile parameter is added to the test because, depending on the device and the server certificate, your underlying system may not have the required CA in place to validate the server certificate you set.

Certificate access

It is important that the files from the specified path are available to Pro Edition for Eclipse Mosquitto. Ensure that the private key file is securely accessible to the Mosquitto service:

sudo chmod 640 /path/to/server.key
sudo chown mosquitto:mosquitto /path/to/server.key

This ensures that only the Mosquitto service has access to the private key, enhancing security.

To apply the changes, restart Pro Edition for Eclipse Mosquitto. Check the Mosquitto logs for troubleshooting if needed.

Configuring Cedalo Platform with a Server Certificate

You can achieve https:// access either via a reverse proxy of your choice or by adding the server certificates directly to the platform via environment variables.

Environment Variables

To configure the server certificates use the following Environment Variables:

  • BASE_URL: URL the platform will be reachable at (should have the same IP/hostname as specified in the certificate)
  • NEXTAUTH_URL: URL the platform will be reachable at (should have the same IP/hostname as specified in the certificate)
  • MOSQUITTO_PLATFORM_HTTPS_KEY_PATH: Path to server's private key file (required)
  • MOSQUITTO_PLATFORM_HTTPS_CERT_PATH: Path to server's certificate (required)
  • MOSQUITTO_PLATFORM_HTTPS_CA_PATH: path to CA certificate (optional)
Example configuration
Docker
            BASE_URL: https://192.168.178.27:3000
NEXTAUTH_URL: https://192.168.178.27:3000
MOSQUITTO_PLATFORM_HTTPS_KEY_PATH: /certs/cert.key
MOSQUITTO_PLATFORM_HTTPS_CERT_PATH: /certs/cert.crt
Docker compose

In docker based deployments make sure, that the linked certificates are reachable. A mount to the local directory allows you to store the used certs in the setup folders:

        volumes:
...
- ./certs:/certs
RPM
            export BASE_URL=https://192.168.178.27:3000
export NEXTAUTH_URL=https://192.168.178.27:3000
export MOSQUITTO_PLATFORM_HTTPS_KEY_PATH=/certs/cert.key
export MOSQUITTO_PLATFORM_HTTPS_CERT_PATH=/certs/cert.crt

Kubernetes/OpenShift TLS setup

This guide matches the 3.2 Helm charts in this repository. Chart directories:

PlatformSingle nodeHA cluster (HAProxy entry point)
Kubernetesmosquitto-3.2-platform-3.2-kubernetes-snmosquitto-3.2-platform-3.2-kubernetes-cluster
OpenShiftmosquitto-3.2-platform-3.2-openshift-snmosquitto-3.2-platform-3.2-openshift-cluster

Throughout this document, kubectl on Kubernetes can be replaced with oc on OpenShift.


TLS configuration overview

The Helm charts support dynamic TLS configuration through values.yaml and --set flags, without manually editing packaged chart files.

DeploymentTypical TLS approach
Single nodeTLS on the Mosquitto broker only (mosquitto.serverOnlyTls). No HAProxy in front of MQTT for this topology.
HA clusterEither TLS termination at HAProxy (haproxy.tls.enabled) or TLS on Mosquitto with HAProxy TCP passthrough (mosquitto.serverOnlyTls.enabled). See HA cluster TLS configuration.

Single node TLS configuration (server-only TLS)

For single-node deployments, TLS is configured directly on the Mosquitto broker using server-only TLS. This enables one-way TLS where only the server presents a certificate to clients.

Prerequisites

Ensure you have the following files ready:

  • Server certificate (server.crt): the public server certificate
  • Private key (server.key): the private key associated with the server certificate

Secret creation

Certificates can be created outside the Helm chart using kubectl or oc. This is the recommended approach for clearer secret lifecycle management. When using external secrets, set mosquitto.serverOnlyTls.createSecret=false.

Note: Secret names and paths below are defaults and can be overridden in Helm values. See Configuration parameters.

Kubernetes

NAMESPACE="your-namespace"

kubectl create secret generic mosquitto-server-tls \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
-n $NAMESPACE

OpenShift

NAMESPACE="your-namespace"

oc create secret generic mosquitto-server-tls \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
-n $NAMESPACE

When creating secrets externally, the secret name must match mosquitto.serverOnlyTls.secretName (default: mosquitto-server-tls) and the secret keys must match certFile and keyFile (defaults: server.crt and server.key). Set mosquitto.serverOnlyTls.createSecret=false in your Helm values or --set.

First-time installation

Kubernetes single node

NAMESPACE="your-namespace"

helm install mosquitto-platform \
./mosquitto-3.2-platform-3.2-kubernetes-sn \
-n $NAMESPACE \
-f values.yaml \
--set mosquitto.serverOnlyTls.enabled=true \
--set mosquitto.serverOnlyTls.createSecret=false

OpenShift single node

NAMESPACE="your-namespace"

helm install mosquitto-platform \
./mosquitto-3.2-platform-3.2-openshift-sn \
-n $NAMESPACE \
-f values.yaml \
--set mosquitto.serverOnlyTls.enabled=true \
--set mosquitto.serverOnlyTls.createSecret=false

Upgrade installation

Kubernetes single node

NAMESPACE="your-namespace"

helm upgrade mosquitto-platform \
./mosquitto-3.2-platform-3.2-kubernetes-sn \
-n $NAMESPACE \
-f values.yaml \
--set mosquitto.serverOnlyTls.enabled=true \
--set mosquitto.serverOnlyTls.createSecret=false

OpenShift single node

NAMESPACE="your-namespace"

helm upgrade mosquitto-platform \
./mosquitto-3.2-platform-3.2-openshift-sn \
-n $NAMESPACE \
-f values.yaml \
--set mosquitto.serverOnlyTls.enabled=true \
--set mosquitto.serverOnlyTls.createSecret=false

Configuration parameters (single node)

Note: All secret names, file names, and mount paths below are defaults and can be customized via Helm values.

  • mosquitto.serverOnlyTls.enabled — Enables the server-only TLS listener on the secure MQTT port (default 8883 in the single-node chart). When enabled, Mosquitto presents a server certificate to clients. Default: false.

  • mosquitto.serverOnlyTls.secretName — Kubernetes Secret name containing server TLS material. The secret must exist if createSecret is false. Default: mosquitto-server-tls.

  • mosquitto.serverOnlyTls.createSecret — If true, Helm creates the secret from certContent and keyContent. If false, create the secret with kubectl/oc as above. Recommended: false for externally managed secrets. Default: true.

  • mosquitto.serverOnlyTls.certFile — Key name inside the Secret for the certificate (must match how you created the secret). Default: server.crt.

  • mosquitto.serverOnlyTls.keyFile — Key name inside the Secret for the private key. Default: server.key.

  • mosquitto.serverOnlyTls.tlsMountPathDirectory only where certificates are mounted in the container (e.g. /mosquitto/certs). Do not append a filename. Default: /mosquitto/certs.

  • mosquitto.serverOnlyTls.certName — Filename only as seen inside the container (e.g. server.crt). Full path: tlsMountPath + / + certName. Default: server.crt.

  • mosquitto.serverOnlyTls.keyName — Filename only for the key (e.g. server.key). Default: server.key.

  • mosquitto.serverOnlyTls.certContent / keyContent — Base64-encoded material; used only when createSecret: true. Ignored when createSecret: false.

Helm value spelling: the chart uses serverOnlyTls (camelCase with lowercase s in “Tls”), e.g. mosquitto.serverOnlyTls.enabled, not serverOnlyTLS.

What happens under the hood (single node)

When you enable mosquitto.serverOnlyTls, the chart:

  1. Mounts the Secret as a volume on the Mosquitto workload at the configured mount path (default /mosquitto/certs).

  2. Updates mosquitto.conf with a TLS listener on the secure port, for example:

    listener 8883
    protocol mqtt
    certfile /mosquitto/certs/server.crt
    keyfile /mosquitto/certs/server.key

    Actual paths are built from tlsMountPath / certName and tlsMountPath / keyName when you override defaults.

  3. Exposes the secure listener port on the Mosquitto Service (per chart defaults).

Verify TLS configuration (single node)

# Service ports
kubectl get svc mosquitto -n $NAMESPACE

# Certificates mounted
kubectl exec mosquitto-0 -n $NAMESPACE -- ls -la /mosquitto/certs/
# Expect: server.crt and server.key

# Mosquitto config
kubectl exec mosquitto-0 -n $NAMESPACE -- grep -A 5 "listener.*8883" /mosquitto/config/mosquitto.conf

# Test TLS (use host/IP and CA that match your cert)
mosquitto_sub -h <mosquitto-external-ip> -p 8883 --cafile ca.crt -u <username> -P <password> -t '#'

Important path configuration notes (single node)

  • tlsMountPath must be a directory path only (e.g. /mosquitto/certs).
  • certName / keyName must be filenames only (e.g. server.crt, server.key).
  • Final paths: tlsMountPath/certName, tlsMountPath/keyName.
  • Wrong: tlsMountPath set to /mosquitto/certs/server.crt (includes filename).
  • Right: tlsMountPath="/mosquitto/certs" and certName="server.crt".

HA cluster TLS configuration

HA charts use HAProxy as the MQTT entry point. TLS can end either at HAProxy or at Mosquitto, controlled by different values—do not confuse them.

Two TLS modes (terminology)

ConceptHelm flagWhere TLS terminatesWhat the client validates
HAProxy TLShaproxy.tls.enabledHAProxy decrypts TLS, then plain MQTT to Mosquitto on mosquitto.ports.listenerTarget (default 1888).The certificate in HAProxy’s combined PEM (haproxy.tls.pemFile, default haproxy_combined.pem).
Server-only TLS on Mosquittomosquitto.serverOnlyTls.enabledMosquitto on mosquitto.ports.secureListenerTarget (default 8883). HAProxy binds 8883 as plain TCP and forwards bytes unchanged (passthrough).server.crt / server.key (or your configured certFile / keyFile) in mosquitto.serverOnlyTls.secretName.

How the flags interact

Rendered from templates/haproxy-config.yaml in the cluster charts. The secure frontend (mqtt_frontend_secure on haproxy.ports.secureListener, default 8883) behaves as follows:

  1. If mosquitto.serverOnlyTls.enabled is true (or mosquitto.mtls.enabled is true): HAProxy binds without ssl crt (TCP only). Traffic goes to mqtt_backend_secure → each broker mosquitto.ports.secureListenerTarget (default 8883). Mosquitto performs the TLS handshake.
  2. Else if haproxy.tls.enabled is true: HAProxy binds with ssl crt <pemPath> and terminates TLS. Traffic goes to mqtt_backend → brokers on mosquitto.ports.listenerTarget (default 1888) in plain MQTT, with optional PROXY v2 per haproxy.proxyProtocol.

haproxy.tls.enabled=false and mosquitto.serverOnlyTls.enabled=true

  • HAProxy 8883 is TCP passthrough to broker 8883.
  • HAProxy does not mount the HAProxy PEM volume (haproxy.tls.enabled gates the volume in deployment-haproxy*.yaml).
  • Mosquitto mounts mosquitto.serverOnlyTls and serves TLS as in the single node section.
  • haproxy.proxyProtocol.enabled must be false. The chart fails if proxy protocol stays enabled while serverOnlyTls or mtls is enabled (templates/mosquitto-config.yaml).

haproxy.tls.enabled=true and mosquitto.serverOnlyTls.enabled=false

  • HAProxy terminates TLS on 8883, forwards plain MQTT to 1888.
  • Requires a combined PEM Secret for HAProxy (see below).
  • haproxy.proxyProtocol.mode cannot be direct; use tls-server, tls-mtls, or tls-mtls-cn with haproxy.proxyProtocol.enabled=true so broker and HAProxy agree on PROXY v2 + TLS metadata.

Both haproxy.tls.enabled=true and mosquitto.serverOnlyTls.enabled=true

  • The template still uses the passthrough branch when serverOnlyTls is on (same effective behavior as serverOnlyTls alone on 8883).
  • If haproxy.tls.enabled stays true, HAProxy still mounts the PEM Secret even though that PEM is not used for the public 8883 bind—redundant and easy to misread.
  • Recommendation: use one model. For TLS at Mosquitto behind HAProxy, set haproxy.tls.enabled=false and mosquitto.serverOnlyTls.enabled=true.

HAProxy TLS configuration parameters (HA cluster charts)

Defaults and behavior match mosquitto-3.2-platform-3.2-kubernetes-cluster / mosquitto-3.2-platform-3.2-openshift-cluster values.yaml unless noted.

  • haproxy.tls.enabled — Enable TLS termination on HAProxy for the secure frontend (bind … ssl crt …). Default: false.
  • haproxy.tls.secretName — Name of the Secret that holds the combined PEM. Default: haproxy-tls-certs.
  • haproxy.tls.createSecret — If true, Helm renders the HAProxy TLS Secret from pemContent (Kubernetes cluster chart: templates/haproxy-tls-certs.yaml is conditional on this). If false, create the Secret yourself before install/upgrade. Present in the Kubernetes cluster chart defaults; the OpenShift cluster chart values.yaml may not list it—--set still works if your chart revision supports the same key in templates/helpers.
  • haproxy.tls.pemFile — Key name inside the Secret for the combined cert+key PEM file. Default: haproxy_combined.pem.
  • haproxy.tls.pemPath — Full path passed to HAProxy crt (must match where the PEM file is mounted in the container). Default: /etc/haproxy/certs/haproxy_combined.pem.
  • haproxy.tls.pemContent — Base64-encoded combined PEM (cert + key). Used when Helm creates the Secret (createSecret: true on Kubernetes cluster chart, or when your OpenShift revision expects inline data in values).
  • haproxy.haproxyCombinedPemFilePath — (Kubernetes cluster chart) Directory mount path for the HAProxy TLS Secret volume on the HAProxy pod. Default: /etc/haproxy/certs.
  • haproxy.tls.tlsHaproxyPemDirPath — (OpenShift cluster chart) Directory mount path for the HAProxy TLS Secret volume. Default: /etc/haproxy/certs.
  • haproxy.ports.secureListener — Service / external secure MQTT port (HAProxy listens here for the secure frontend). Default: 8883.
  • haproxy.ports.secureListenerTarget — Container port HAProxy listens on for that secure frontend. Default: 8883.
  • haproxy.ports.secureNodePort — Optional fixed NodePort when the HAProxy Service is NodePort. Default: null (auto).

Related (not under haproxy.tls, but required when only HAProxy terminates TLS):

  • haproxy.proxyProtocol.enabled / haproxy.proxyProtocol.mode — With haproxy.tls.enabled and mosquitto.serverOnlyTls.enabled false, mode must be tls-server, tls-mtls, or tls-mtls-cn (not direct). With mosquitto.serverOnlyTls.enabled true, set haproxy.proxyProtocol.enabled to false.

Mosquitto server-only TLS configuration parameters (HA cluster charts)

The same mosquitto.serverOnlyTls block applies to HA as to single node; the StatefulSet mounts the Secret and opens the secure listener on mosquitto.ports.secureListenerTarget (default 8883). HAProxy then TCP-forwards external haproxy.ports.secureListener to that port when serverOnlyTls is enabled.

  • mosquitto.serverOnlyTls.enabled — One-way TLS on the broker secure listener. Default: false.
  • mosquitto.serverOnlyTls.secretName — Secret containing server cert and key. Default: mosquitto-server-tls.
  • mosquitto.serverOnlyTls.createSecret — Helm-managed Secret from certContent / keyContent vs external Secret. Default: true (external creation with createSecret: false is common in production).
  • mosquitto.serverOnlyTls.certFile / mosquitto.serverOnlyTls.keyFile — Key names inside the Secret. Defaults: server.crt, server.key.
  • mosquitto.serverOnlyTls.tlsMountPath — Mount directory in the Mosquitto container. Default: /mosquitto/certs.
  • mosquitto.serverOnlyTls.certName / mosquitto.serverOnlyTls.keyName — Filenames as seen after mount (used in mosquitto.conf certfile / keyfile). Defaults: server.crt, server.key.
  • mosquitto.serverOnlyTls.certContent / mosquitto.serverOnlyTls.keyContent — Base64-encoded cert/key; only used when createSecret: true.

Ports used with HAProxy passthrough (defaults from cluster values.yaml):

  • mosquitto.ports.secureListenerTarget — Broker container port for TLS MQTT (HAProxy mqtt_backend_secure targets this). Default: 8883.
  • mosquitto.ports.listenerTarget — Plain cluster listener (used when HAProxy terminates TLS and forwards plain MQTT). Default: 1888 (cluster chart).

Certificates and secrets (HA)

HAProxy TLS (haproxy.tls.enabled=true)

Combine certificate then key (order matters for HAProxy):

cat server.crt server.key > haproxy_combined.pem

Create a Secret whose data key matches haproxy.tls.pemFile (default haproxy_combined.pem) and name matches haproxy.tls.secretName (default haproxy-tls-certs):

NAMESPACE="your-namespace"
kubectl create secret generic haproxy-tls-certs \
--namespace "$NAMESPACE" \
--from-file=haproxy_combined.pem=./haproxy_combined.pem

kubectl create secret --from-file encodes content for the Secret; you do not need a manual base64 step for this workflow.

Kubernetes cluster chart: with haproxy.tls.enabled=true, either set haproxy.tls.createSecret=true and supply haproxy.tls.pemContent as base64-encoded PEM bytes, or haproxy.tls.createSecret=false and pre-create the Secret (Helm skips templates/haproxy-tls-certs.yaml when createSecret is false).

OpenShift cluster chart: values.yaml describes pemContent as base64 of the combined PEM. templates/haproxy-tls-certs.yaml creates a Secret when haproxy.tls.enabled is true; confirm your chart revision for external vs Helm-managed PEMs.

Mosquitto server-only TLS in HA (passthrough)

Same server.crt / server.key Secret shape as single node: default name mosquitto-server-tls, keys matching mosquitto.serverOnlyTls.certFile / keyFile.

HA cluster: TLS termination at HAProxy (typical production choice)

Goal: clients use TLS to HAProxy 8883; HAProxy uses plain MQTT to brokers 1888.

  1. Build haproxy_combined.pem and create haproxy-tls-certs (or your configured names).
  2. Set haproxy.tls.enabled=true, mosquitto.serverOnlyTls.enabled=false.
  3. Set haproxy.proxyProtocol.enabled=true and haproxy.proxyProtocol.mode=tls-server (or tls-mtls / tls-mtls-cn if applicable).

Kubernetes

NAMESPACE="your-namespace"
helm upgrade --install mosquitto-ha ./mosquitto-3.2-platform-3.2-kubernetes-cluster \
-n $NAMESPACE \
-f values.yaml \
--set haproxy.tls.enabled=true \
--set haproxy.tls.createSecret=false \
--set haproxy.proxyProtocol.enabled=true \
--set haproxy.proxyProtocol.mode=tls-server

OpenShift

NAMESPACE="your-namespace"
helm upgrade --install mosquitto-ha ./mosquitto-3.2-platform-3.2-openshift-cluster \
-n $NAMESPACE \
-f values.yaml \
--set haproxy.tls.enabled=true \
--set haproxy.proxyProtocol.enabled=true \
--set haproxy.proxyProtocol.mode=tls-server

The OpenShift cluster chart’s values.yaml does not document haproxy.tls.createSecret the same way as the Kubernetes cluster chart; check templates/haproxy-tls-certs.yaml in your revision for whether Helm always creates the HAProxy TLS Secret when haproxy.tls.enabled is true. Supply haproxy.tls.pemContent (base64 PEM) in values if you rely on chart-managed secrets, or follow your platform team’s pattern for external PEMs.

Optional (Helm-managed HAProxy secret, Kubernetes chart): haproxy.tls.createSecret=true and set haproxy.tls.pemContent to the base64 of haproxy_combined.pem. GNU: base64 -w0 < haproxy_combined.pem; macOS: base64 < haproxy_combined.pem | tr -d '\n'.

HA cluster: TLS termination on Mosquitto (server-only TLS + HAProxy passthrough)

Goal: clients negotiate TLS with Mosquitto; HAProxy only forwards TCP to 8883.

  1. Create mosquitto-server-tls with server.crt and server.key (see Secret creation).
  2. Set mosquitto.serverOnlyTls.enabled=true, mosquitto.serverOnlyTls.createSecret=false when using an external secret.
  3. Set haproxy.tls.enabled=false (recommended).
  4. Set haproxy.proxyProtocol.enabled=false.

After install or upgrade, restart HAProxy so pods load the updated ConfigMap:

kubectl rollout restart deployment haproxy -n $NAMESPACE

Verify

kubectl exec mosquitto-0 -n $NAMESPACE -- ls -la /mosquitto/certs/
kubectl exec mosquitto-0 -n $NAMESPACE -- grep -A 5 "listener.*8883" /mosquitto/config/mosquitto.conf
mosquitto_sub -h <haproxy-external-ip> -p 8883 --cafile ca.crt -u <user> -P <pass> -t '#'

Updating TLS configuration

Server-only TLS (single node, or HA with Mosquitto TLS)

Kubernetes

kubectl create secret generic mosquitto-server-tls \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
-n $NAMESPACE \
--dry-run=client -o yaml | kubectl apply -f -

kubectl rollout restart statefulset mosquitto -n $NAMESPACE

For HA with serverOnlyTls, also restart HAProxy after broker certs change:

kubectl rollout restart deployment haproxy -n $NAMESPACE

OpenShift

oc create secret generic mosquitto-server-tls \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
-n $NAMESPACE \
--dry-run=client -o yaml | oc apply -f -

oc rollout restart statefulset mosquitto -n $NAMESPACE
oc rollout restart deployment haproxy -n $NAMESPACE

(omit the HAProxy line on single node.)

HA cluster (HAProxy TLS termination)

Kubernetes

kubectl create secret generic haproxy-tls-certs \
--from-file=haproxy_combined.pem=./haproxy_combined.pem \
-n $NAMESPACE \
--dry-run=client -o yaml | kubectl apply -f -

kubectl rollout restart deployment haproxy -n $NAMESPACE

OpenShift

oc create secret generic haproxy-tls-certs \
--from-file=haproxy_combined.pem=./haproxy_combined.pem \
-n $NAMESPACE \
--dry-run=client -o yaml | oc apply -f -

oc rollout restart deployment haproxy -n $NAMESPACE

Troubleshooting

Single node

Connection refused on port 8883

  • Confirm mosquitto.serverOnlyTls.enabled=true.
  • Check the Service exposes 8883: kubectl get svc mosquitto -n $NAMESPACE.
  • Confirm mounts: kubectl exec mosquitto-0 -n $NAMESPACE -- ls -la /mosquitto/certs.

Certificate validation errors

  • Certificate SAN/CN must match the hostname or IP clients use.
  • Pass --cafile with the issuing CA if it is not in the client trust store.

HA cluster

Connection refused on 8883 (via HAProxy)

  • At least one of haproxy.tls.enabled, mosquitto.serverOnlyTls.enabled, or mosquitto.mtls.enabled must be true for the secure Service port.
  • kubectl get svc haproxy -n $NAMESPACE

Helm template errors

  • serverOnlyTls / mtls with haproxy.proxyProtocol.enabled=true → set haproxy.proxyProtocol.enabled=false.
  • haproxy.tls.enabled only with proxyProtocol.mode=direct → set mode to tls-server (or mtls variants).

Invalid PEM at HAProxy

  • Concatenate certificate first, then key.
  • Secret key name must match haproxy.tls.pemFile.

HAProxy pod errors

  • kubectl logs deployment/haproxy -n $NAMESPACE
  • Missing or malformed combined PEM is a common cause.

External secret missing

  • With createSecret: false, create Secrets before helm install / helm upgrade when chart validateSecrets is enabled.

Security best practices

  1. Use strong certificates from a trusted CA or a controlled self-signed setup.
  2. Never commit private keys or raw keyContent / pemContent to version control.
  3. Rotate certificates before expiry; automate expiry monitoring where possible.
  4. Store material in Kubernetes/OpenShift Secrets (or a secrets manager that syncs to Secrets).
  5. Restrict Secret access with RBAC.
  6. For HA with HAProxy TLS, in-cluster traffic from HAProxy to Mosquitto is plain MQTT on the cluster network; for end-to-end TLS to the broker, use mosquitto.serverOnlyTls with HAProxy passthrough and accept broker-side cert management and CPU cost.