Docker 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 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 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 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 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 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 conifgure 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
            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
Kubernetes/OpenShift Setup
TLS Configuration Overview for Kubernetes/OpenShift
The Helm charts for both Kubernetes and OpenShift support dynamic TLS configuration through values.yaml and --set flags, eliminating the need to manually edit and repackage chart files. The approach differs between single-node and high-availability (HA) deployments:
Key Differences:
| Deployment Type | TLS Termination Location | Certificate Format | Recommended Approach | 
|---|---|---|---|
| Single Node | Mosquitto Broker | Separate cert + key files | Direct Mosquitto TLS | 
| HA Cluster | HAProxy Load Balancer | Combined PEM file (cert+key) | HAProxy TLS Termination | 
Why Different Approaches?
- Single Node: TLS is configured directly on the Mosquitto broker since there's no load balancer in front.
 - HA Cluster: TLS termination at HAProxy provides centralized certificate management, simplifies the setup, and allows the load balancer to handle secure connections before routing to Mosquitto brokers.
 
Single Node TLS Configuration
For single-node deployments, TLS is configured directly on the Mosquitto broker.
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 
Configuration Using Helm Values (Recommended)
Step 1: Prepare Certificates
# Encode certificates to base64
cat server.crt | base64 -w 0 > server_crt_base64.txt
cat server.key | base64 -w 0 > server_key_base64.txt
Step 2: Install with TLS Configuration
# Read base64 content
CERT_CONTENT=$(cat server_crt_base64.txt)
KEY_CONTENT=$(cat server_key_base64.txt)
# Install with TLS enabled
helm install my-mosquitto mosquitto-3.1-platform-3.1-kubernetes-sn.tgz -n singlenode \
  --set licenseKey=<your-license-key> \
  --set nameserver=10.0.0.10 \
  --set mosquitto.config.enableTls=true \
  --set mosquitto.tls.enabled=true \
  --set mosquitto.tls.certContent="$CERT_CONTENT" \
  --set mosquitto.tls.keyContent="$KEY_CONTENT" \
  --set mosquitto.tls.tlsMountPath="/mosquitto/certs" \
  --set mosquitto.tls.certName="server.crt" \
  --set mosquitto.tls.keyName="server.key"
Configuration Parameters
mosquitto.config.enableTls: Enable TLS listener on port 8883. Default:falsemosquitto.tls.enabled: Enable TLS certificate mounting. Default:falsemosquitto.tls.secretName: Kubernetes Secret name. Default:mosquitto-server-tlsmosquitto.tls.certContent: Base64-encoded certificate contentmosquitto.tls.keyContent: Base64-encoded private key contentmosquitto.tls.tlsMountPath: Directory path for mounted certificates. Default:/mosquitto/certsmosquitto.tls.certName: Certificate filename. Default:server.crtmosquitto.tls.keyName: Private key filename. Default:server.keymosquitto.tls.certFile: Certificate key in Secret. Default:server.crtmosquitto.tls.keyFile: Private key key in Secret. Default:server.key
Alternative: Using Existing Kubernetes Secret
If you prefer to create the Secret separately:
# Create Kubernetes Secret
kubectl create secret generic mosquitto-server-tls -n singlenode \
  --from-file=server.crt=./server.crt \
  --from-file=server.key=./server.key
# Install referencing existing secret
helm install my-mosquitto mosquitto-3.1-platform-3.1-kubernetes-sn.tgz -n singlenode \
  --set licenseKey=<your-license-key> \
  --set nameserver=10.0.0.10 \
  --set mosquitto.config.enableTls=true \
  --set mosquitto.tls.enabled=true \
  --set mosquitto.tls.secretName=mosquitto-server-tls
What Happens Under the Hood
When you enable TLS, the Helm chart automatically:
- Creates a Kubernetes Secret with your certificates
 - Mounts the Secret as a volume in the Mosquitto StatefulSet at 
/mosquitto/certs - Updates 
mosquitto.confto enable the TLS listener on port 8883:listener 8883
protocol mqtt
certfile /mosquitto/certs/server.crt
keyfile /mosquitto/certs/server.key - Exposes port 8883 on the Mosquitto service
 
Verify TLS Configuration
# Check the Mosquitto service ports
kubectl get svc mosquitto-loadbalancer -n singlenode
# Test TLS connection
mosquitto_sub -h <mosquitto-external-ip> -p 8883 --cafile ca.crt -u <username> -P <password> -t '#'
Important Path Configuration Notes
IMPORTANT: Follow these conventions to avoid path configuration errors:
tlsMountPath: Should be a DIRECTORY path only (e.g.,/mosquitto/certs)certName/keyName: Should be FILENAMES only (e.g.,server.crt,server.key)- Final path is constructed as: 
tlsMountPath/certName=/mosquitto/certs/server.crt - ❌ WRONG: Setting 
tlsMountPathto/mosquitto/certs/server.crt(includes filename) - ✅ CORRECT: 
tlsMountPath="/mosquitto/certs"andcertName="server.crt" 
HA Cluster TLS Configuration
For High-Availability (HA) cluster deployments, TLS termination occurs at the HAProxy load balancer, not on individual Mosquitto brokers. This is the recommended approach for production HA deployments.
Why HAProxy TLS for HA?
- ✅ Centralized certificate management: Update certificates in one place
 - ✅ Simplified configuration: No need to configure TLS on each broker
 - ✅ Better performance: Offload TLS processing to HAProxy
 - ✅ Easier certificate rotation: Update one HAProxy Secret vs. multiple broker Secrets
 
Prerequisites
Ensure you have the following:
- Server Certificate (
server.crt): The public server certificate - Private Key (
server.key): The private key associated with the server certificate 
Prepare HAProxy PEM Certificate
HAProxy requires certificates in PEM format with the certificate and private key combined in a single file:
# Combine certificate and key into a single PEM file
cat server.crt server.key > haproxy_combined.pem
# Encode to base64 for Kubernetes Secret
cat haproxy_combined.pem | base64 -w 0 > haproxy_combined_base64.txt
Important: The order matters! Certificate first, then the private key.
Configuration Using Helm Values (Recommended)
Install with HAProxy TLS Configuration
# Read base64 content
PEM_CONTENT=$(cat haproxy_combined_base64.txt)
# Install with HAProxy TLS enabled
helm install my-ha-cluster mosquitto-3.1-platform-3.1-kubernetes-cluster.tgz -n ha \
  --set licenseKey=<your-license-key> \
  --set nameserver=10.0.0.10 \
  --set haproxy.tls.enabled=true \
  --set haproxy.tls.pemContent="$PEM_CONTENT" \
  --set haproxy.tls.secretName="haproxy-tls-certs" \
  --set haproxy.tls.pemFile="haproxy_combined.pem" \
  --set haproxy.ports.secureListener=8883
HAProxy TLS Configuration Parameters
haproxy.tls.enabled: Enable HAProxy TLS termination. Default:falsehaproxy.tls.secretName: Kubernetes Secret name for HAProxy certificates. Default:haproxy-tls-certshaproxy.tls.pemFile: PEM filename (combined cert+key). Default:haproxy_combined.pemhaproxy.tls.pemContent: Base64-encoded PEM content (cert+key combined)haproxy.tls.pemPath: Full path to PEM file in container. Default:/etc/haproxy/certs/haproxy_combined.pemhaproxy.tls.tlsHaproxyPemDirPath: Directory path for HAProxy certificates. Default:/etc/haproxy/certshaproxy.ports.secureListener: HAProxy secure MQTT port. Default:8883haproxy.ports.secureListenerTarget: Target port for secure connection. Default:8883
Alternative: Using Existing Kubernetes Secret
# Create Kubernetes Secret with PEM file
kubectl create secret generic haproxy-tls-certs -n ha \
  --from-file=haproxy_combined.pem=./haproxy_combined.pem
# Install referencing existing secret
helm install my-ha-cluster mosquitto-3.1-platform-3.1-kubernetes-cluster.tgz -n ha \
  --set licenseKey=<your-license-key> \
  --set nameserver=10.0.0.10 \
  --set haproxy.tls.enabled=true \
  --set haproxy.tls.secretName=haproxy-tls-certs
What Happens Under the Hood
When you enable HAProxy TLS, the Helm chart automatically:
- Creates a Kubernetes Secret (
haproxy-tls-certs) with your PEM certificate - Mounts the Secret as a volume in the HAProxy Deployment at 
/etc/haproxy/certs - Updates HAProxy configuration to add a secure frontend:
frontend mqtt_frontend_secure
bind *:8883 ssl crt /etc/haproxy/certs/haproxy_combined.pem
mode tcp
maxconn 10000
default_backend mqtt_backend
timeout client 10m - Exposes port 8883 on the HAProxy LoadBalancer service
 - Routes secure traffic to Mosquitto brokers (non-TLS communication between HAProxy and brokers)
 
Verify HAProxy TLS Configuration
# Check HAProxy service ports (should show both 1883 and 8883)
kubectl get svc haproxy -n ha
# Test TLS connection through HAProxy
mosquitto_sub -h <haproxy-external-ip> -p 8883 --cafile ca.crt -u <username> -P <password> -t '#'
End-to-End Encryption (Optional)
If you require encryption between HAProxy and Mosquitto brokers (end-to-end encryption), you can enable TLS on both:
helm install my-ha-cluster mosquitto-3.1-platform-3.1-kubernetes-cluster.tgz -n ha \
  --set licenseKey=<your-license-key> \
  --set nameserver=10.0.0.10 \
  --set haproxy.tls.enabled=true \
  --set haproxy.tls.pemContent="$HAPROXY_PEM_CONTENT" \
  --set mosquitto.config.enableTls=true \
  --set mosquitto.tls.enabled=true \
  --set mosquitto.tls.certContent="$MOSQUITTO_CERT_CONTENT" \
  --set mosquitto.tls.keyContent="$MOSQUITTO_KEY_CONTENT"
Note: This is typically not required for most deployments, as communication between HAProxy and Mosquitto occurs within the Kubernetes cluster network.
Updating TLS Configuration
To update certificates after initial deployment:
Single Node
# Update with new certificates
helm upgrade my-mosquitto mosquitto-3.1-platform-3.1-kubernetes-sn.tgz -n singlenode \
  --reuse-values \
  --set mosquitto.tls.certContent="$NEW_CERT_CONTENT" \
  --set mosquitto.tls.keyContent="$NEW_KEY_CONTENT"
HA Cluster
# Update HAProxy certificates
helm upgrade my-ha-cluster mosquitto-3.1-platform-3.1-kubernetes-cluster.tgz -n ha \
  --reuse-values \
  --set haproxy.tls.pemContent="$NEW_PEM_CONTENT"
Troubleshooting
Single Node Issues
Connection Refused on Port 8883
- Verify 
mosquitto.config.enableTls=trueis set - Check service exposes port 8883: 
kubectl get svc mosquitto-loadbalancer -n singlenode - Verify certificates are mounted: 
kubectl exec mosquitto-0 -n singlenode -- ls -la /mosquitto/certs 
Certificate Validation Errors
- Ensure certificate matches the hostname/IP you're connecting to
 - Use 
--cafileflag to provide CA certificate if not in system trust store 
HA Cluster Issues
Connection Refused on Port 8883 (HAProxy)
- Verify 
haproxy.tls.enabled=trueis set - Check HAProxy service exposes port 8883: 
kubectl get svc haproxy -n ha - Verify PEM file is mounted: 
kubectl exec <haproxy-pod> -n ha -- ls -la /etc/haproxy/certs 
Invalid PEM Format
- Ensure certificate and key are combined in correct order: certificate first, then key
 - Verify base64 encoding is correct: 
echo "$PEM_CONTENT" | base64 -d | openssl x509 -text 
HAProxy Not Starting
- Check HAProxy logs: 
kubectl logs <haproxy-pod> -n ha - Common issue: Missing or incorrectly formatted PEM file
 
Security Best Practices
- Use Strong Certificates: Use certificates from a trusted CA or properly configured self-signed certificates
 - Secure Private Keys: Never commit private keys to version control
 - Rotate Certificates Regularly: Update certificates before expiration
 - Use Kubernetes Secrets: Store certificates in Kubernetes Secrets, not in plain text
 - Restrict Secret Access: Use Kubernetes RBAC to limit who can access certificate Secrets
 - Monitor Certificate Expiration: Set up alerts for certificate expiration
 - For HA: Always use HAProxy TLS termination instead of individual broker TLS for easier management