Automating MQTT Broker Management on Kubernetes with IaC and GitOps: Part 2
In the first part of this article, we established the foundational elements of our GitOps-driven deployment. We set up Argo CD as the centerpiece for managing applications using the app-of-apps pattern. Using Terraform, we automated the deployment of these components and introduced best practices for handling sensitive data with SealedSecrets.
Now, in the second part, we’ll shift our focus to securing our MQTT broker cluster by covering essential security topics, including:
Enabling MQTT over TLS: Configuring the broker to secure MQTT communication channels with TLS encryption, ensuring data integrity and confidentiality.
Securing the HiveMQ Control Center with HTTPS: Configuring Kubernetes Ingress to use HTTPS for encrypted connections to the HiveMQ Control Center, preventing potential eavesdropping and man-in-the-middle attacks.
Certificate Management with cert-manager: Automating the issuance and management of certificates for both MQTT and HTTPS connections.
Security is a critical aspect of any production-grade system, especially when sensitive data is transmitted over networks. By implementing these measures, we’ll ensure that both communication channels and access points to the broker are properly secured and ready for production environments. Let’s dive into the details of these security enhancements.
Securing MQTT Traffic with TLS Encryption
Securing TCP-based traffic with TLS encryption is a widely adopted best practice for enhancing data security. TLS (Transport Layer Security) ensures that communication between a client and a server is encrypted, providing confidentiality, integrity, and protection against man-in-the-middle attacks. Since MQTT operates over TCP, the same TLS encryption principles can be applied to secure MQTT traffic.
To enable TLS encryption for MQTT, two key components are required:
A Certificate: The broker needs a certificate to establish encrypted communication. The HiveMQ Platform requires you to provide a Java Keystore which contains the necessary private key and certificate chain.
Modified Broker Configuration: The broker's configuration must be updated to include an additional TLS-enabled listener on the standard MQTT-over-TLS port, 8883. This ensures that secure connections are available alongside any existing non-TLS listeners.
For managing certificates, we’ll use cert-manager, which will handle the creation of certificates.
With these elements in place, we can securely enable MQTT-over-TLS and ensure that sensitive data transmitted between clients and the broker is protected.
Let’s Do a Short Recap of Service Deployment
Let’s recap the general repository and deployment structure we’ve established as discussed in Part 1 of this article. Our GitOps setup is organized to manage each service through two distinct Argo CD applications, allowing us to maintain a clear separation between core service deployments and any additional resource configurations they require.
Each service will usually have in the apps/<service> folder:
1. A primary Argo CD application focused on deploying the actual service, typically through a Helm chart.
2. A secondary Argo CD application pointing to the manifests/<service> folder, responsible for deploying any additional Kubernetes resources needed for the service. This may include configuration files, Secrets, ingress resources, and other custom manifests that aren’t directly managed by the Helm chart.
This approach ensures a modular and flexible structure, enabling us to configure and update each service independently while still tracking all related resources within version control. With this structure in place, we can proceed to install the necessary prerequisites for our setup: cert-manager for TLS certificate management and Traefik as our ingress controller. Each will have its own Argo CD application in the apps/ folder, following our established repository organization.
Setting Up Cert-Manager for Certificate Management
Cert-manager is essential for handling TLS certificates, which we’ll use to secure both MQTT connections (MQTT over TLS) and HTTPS access to the HiveMQ Control Center. By automating certificate provisioning and renewal, cert-manager reduces the complexity of maintaining secure connections, ensuring our broker cluster is always accessible securely. Cert-manager also supports generating certificates in the Java Key Store (JKS) format, which is required for configuring the TLS listener for the HiveMQ platform.
To keep the setup simple, we’ll use a self-signed issuer in this example to generate the required certificates. The setup can easily be adapted for production environments by using one of the different issuer types that cert-manager supports.
Using a self-signed issuer allows us to generate the necessary certificates for testing and development purposes without relying on an external Certificate Authority (CA). With cert-manager managing both certificate issuance and renewal, we ensure that our broker’s TLS configurations remain consistent and up-to-date.
For the cert-manager deployment we are using the official helm chart.
apps/certmanager/cert-manager.yaml
As we do not need to deploy any additional resources for cert-manager no cert-manager-manifests
application is needed. But we are still missing the Issuer
that is needed for actually issuing certificates. Cert-manager fundamentally distinguishes between Issuer
and ClusterIssuer
. Whereas ClusterIssuer
are meant to be used cluster-wide, Issuers are local to the namespace they are created in. We only need an issuer for the HiveMQ Platform in this example and it will reside in the hivemq
namespace. As it is therefore related to the HiveMQ deployment we will consequently add the manifests for creating the issuer into the manifests/hivemq folder.
manifests/hivemq/hivemq-issuer.yaml
Using Traefik as Ingress Controller for Secure Control Center Access
An ingress controller is required to manage and route external traffic to HiveMQ Control Center within the Kubernetes cluster. In this setup, we’ll use Traefik as our ingress controller, a popular choice known for its flexibility and ease of integration with Kubernetes. Traefik will manage the ingress rules and TLS configuration, providing secure HTTPS access to the broker’s web UI.
Using Traefik allows us to:
Expose the HiveMQ Control Center securely over HTTPS.
Configure the ingress with TLS using certificates issued by cert-manager, ensuring that all Control Center traffic is encrypted.
With Traefik handling ingress routing and cert-manager managing certificate issuance, our setup provides a reliable, secure connection model that can easily scale to meet the needs of both development and production environments.
As an alternative to Traefik, you could also use the Nginx Ingress Controller, which basically provides the same functionality.
Installing Traefik
We will install Traefik using the official Helm Chart. If you need to configure the Helm chart you can specify certain values in the application as well. All possible values can be found here.
apps/traefik/traefik.yaml
The secondary application is responsible for deploying additional resources for Traefik such as an IngressRoute
for accessing the Traefik dashboard and a Middleware
to secure the access using basic authentication. A SealedSecret
is used for providing a list of user credentials. These resources are optional and not needed for the HiveMQ Platform deployment. We use them here to further clarify the concept and familiarize you with it. Additionally you will learn how to create a SealedSecret
.
apps/traefik/traefik-manifests.yaml
manifests/traefik/traefik-dashboard.yaml
manifests/traefik/traefik-dashboard-auth-sealedsecret.yaml
Excursions: Creating SealedSecrets with kubeseal
The spec.encryptedData
section in the SealedSecret
above contains encrypted secret data, which was generated with kubeseal using a standard Kubernetes Secret. Kubeseal is a tool designed to help securely manage and encrypt secrets for Kubernetes clusters in a GitOps workflow. With kubeseal, sensitive data is encrypted and stored as SealedSecrets
, which can safely be stored in version control and only decrypted within the target Kubernetes cluster.
To create a SealedSecret
, kubeseal uses a regular Kubernetes Secret as input. Here’s a brief guide on how to do this:
Create a Kubernetes Secret: First, create a regular Kubernetes Secret manifest with the data you want to encrypt.
Seal the Secret with kubeseal: Use kubeseal to encrypt the Secret, generating a SealedSecret resource. This is typically done using the following command:
This will convert the secret definition into a sealed secret which can safely be committed in Git.
For more detailed instructions and additional configuration options, refer to the official kubeseal documentation. This documentation provides extensive information on how to set up kubeseal
, manage secrets, and ensure secure, GitOps-compatible workflows for handling sensitive data.
💡TIP:
Since you should prevent unencrypted secrets from being committed to Git under any circumstances, we recommend taking further measures, e.g. storing secrets in files with the postfix *-secret.yaml
and adding this pattern to your .gitignore
file.
Please refer to the Traefik documentation on how to create credentials and configure a middleware for basic authentication.
Configuring the HiveMQ MQTT Platform
With all the required services deployed, we can now finalize the setup by configuring the HiveMQ Platform and adding the remaining resources. These configurations are crucial to enable secure communication and proper access to the broker's services. Specifically, we need to configure the following:
Certificate for the TLS Listener:
HiveMQ requires a Java KeyStore (JKS) certificate for its
tls-tcp-listener
.The certificate is issued by cert-manager and uses a corresponding secret that holds the password for the keystore. This secret ensures secure access to the private key and certificate chain and will be created as a sealed secret.
TLS Listener Configuration:
The configuration for a Secure TCP Listener needs to be added to the HiveMQ Platform.
The JKS certificate and the secret containing the password will be used.
IngressRoute for the HiveMQ Control Center:
The HiveMQ Control Center is exposed through an IngressRoute to allow HTTPS access.
We'll configure an IngressRoute resource to route external traffic securely to the Control Center, leveraging Traefik as the ingress controller.
Certificate for the IngressRoute:
To secure the IngressRoute, we’ll issue another certificate using cert-manager.
This certificate will be used for TLS termination, ensuring encrypted communication between clients and the web UI.
By completing these configurations, we enable the HiveMQ Platform to handle secure MQTT connections, expose its HiveMQ Control Center securely over HTTPS, and meet all requirements for a production-ready deployment. Let’s dive into the details of implementing these components.
Creating Certificates and Securing the MQTT Traffic
As a first step we will create a sealed secret for the password that is used to secure the keystore. Following the approach described above we create the secret manifest file making sure it is not committed to the Git repository.
hivemq-tls-keystore-secret.yaml
Kubeseal will then be used to create the SealedSecret
Once applied to your Kubernetes Cluster the sealed-secrets operator will pick up the definition and create the Kubernetes Secret for you.
Creating the Java Keystore Certificate for the Secure MQTT Listener is straightforward. Additionally to the properties of the certificate such as commonName or dnsNames we want cert-manager to create a Java Keystore. Therefore we add a keystores.jks
configuration. The Secret containing the password we have defined above is referenced with keystores.jks.passwordSecretRef
.
manifests/hivemq/hivemq-tls-keystore.yaml
With the Java Keystore and the required SealedSecret holding the keystore password in place we have everything we need to secure the MQTT traffic. We are still missing the HiveMQ Platform configuration though.
HiveMQ supports secure MQTT-over-TLS communication by using Secure TCP Listeners. Usually these tls-tcp-listeners
are configured in the config.xml file for HiveMQ. In our case as we are using the HiveMQ Platform Operator for Kubernetes we will add the configuration to the valuesObject of the Argo CD Application we have created in Part 1. The HiveMQ Platform Operator will render a corresponding config.xml
configuration file for the HiveMQ Platform.
The complete HiveMQ Platform Application then looks as follows:
After committing these changes to your repository and Argo CD synchronization you can check if the secure MQTT endpoint and a corresponding Kubernetes Service
object was created.
Getting the Server Certificate for Client Connections
As we are using a self-signed (untrusted) certificate for the MQTT communication now we will need to provide the server certificate to the MQTT client as the CA certificate in order to be able to connect. You can easily obtain the certificate using kubectl
and jq
:
Creating a Certificate and Secure Control Center Traffic
The final step for this Part of our blog series will be the TLS configuration for accessing the HiveMQ Control Center. You now already know all the steps that are necessary to add the required configuration: adding a Certificate
and adding an additional IngressRoute
resource to the HiveMQ manifests.
Let’s start with the Certificate:
manifests/hivemq/hivemq-cc-cert.yaml
As you can see we are again using our self-signed cert-manager Issuer for generating the certificate.
Even though securing the HiveMQ Control Center access is possible using the Helm chart with the respective configuration we will be using an IngressRoute resource in this example.
Defining an IngressRoute
is pretty easy. All you need to do is use the websecure
entrypoint Traefik provides for TLS connections and the secretName
of the certificate that we have defined above. Adjust the hostname in the route matcher according to your configuration.
The HiveMQ Control Center automatically ships with the HiveMQ Platform. To avoid problems with routing HTTP requests to different HiveMQ Cluster Nodes which would invalidate your login information we also need to configure sticky sessions
for the Ingress. With Traefik cookies can be used for this purpose by using the sticky.cookie
configuration.
In Part 1 of this blog series the type of the Control Center Service was set to LoadBalancer
so that it was externally accessible using an assigned IP address. In case you want to limit the Control Center access to HTTPS only over the DNS name you can set the service type to ClusterIP
to not expose the service externally.
Conclusion
In this series, we explored automating MQTT broker management on Kubernetes using Infrastructure as Code (IaC) and GitOps, combining these principles with robust security measures to create a scalable and secure deployment. After establishing a strong foundation with Argo CD, Terraform, and SealedSecrets, we enhanced security by enabling MQTT over TLS, securing the HiveMQ Control Center with HTTPS, and automating certificate management using cert-manager. These steps ensure data integrity, confidentiality, and resilience, making the deployment production-ready while addressing the critical need for secure communication and access. In Part 3 of this series, we will configure the Enterprise Security Extension.
Sven Kobow
Sven Kobow is part of the Professional Services team at HiveMQ with more than two decades of experience in IT and IIoT. In his role as IoT Solutions Architect, he is supporting customers and partners in successfully implementing their solutions and generating maximum value. Before joining HiveMQ, he worked in Automotive sector at a major OEM.