How to Log and Analyze MQTT Messages
with the ELK Stack?

Introduction

The ELK Stack (Elasticsearch, Logstash, and Kibana) is a powerful open-source log management and analytics platform. Elasticsearch, its core component, supports replication, allowing data to be copied across multiple nodes. This ensures high availability by preventing data loss in case of node failures.

Replication in Elasticsearch improves query performance by distributing search requests across replicas. It also enhances scalability, allowing systems to handle more queries efficiently. By default, Elasticsearch creates one replica per shard, but this can be adjusted based on requirements. Proper replication strategies help in load balancing, fault tolerance, and overall system reliability.

Elasticsearch

Elasticsearch is a distributed search and analytics engine designed for handling large volumes of data in real time. It stores data in a NoSQL format using JSON documents and provides fast full-text search capabilities. Data is indexed using an inverted index, allowing quick retrieval and analysis. Elasticsearch is scalable, supporting horizontal scaling by adding more nodes to a cluster. It offers replication and sharding, ensuring data redundancy and high availability. Common use cases include log analysis, security monitoring, and business intelligence.

Logstash

Logstash is a data processing pipeline that collects, transforms, and sends data to various destinations, including Elasticsearch. It can ingest data from multiple sources such as logs, metrics, databases, and message queues. Logstash processes data using a powerful filtering system, allowing transformation, enrichment, and parsing. It supports various plugins to handle different data formats, including JSON, CSV, and syslog. Logstash is often used for log collection, data transformation, and real-time data processing before storage.

Kibana

Kibana is a visualization and analytics tool designed to interact with data stored in Elasticsearch. It provides an intuitive dashboard interface for creating visualizations like charts, graphs, and maps. Kibana enables real-time data exploration, making it easy to analyze logs and monitor system performance. It includes features like machine learning, security monitoring, and alerting. Users can build interactive dashboards and set up alerts for anomalies in data. Kibana is widely used for log analysis, security event monitoring, and business intelligence reporting.



Before we begin, ensure you have:

  • A Linux server (Ubuntu 20.04 recommended)
  • MQTTRoute installed and running
  • Java 8 or later (required for ELK and Kafka)
  • Elasticsearch, Logstash, and Kibana (ELK Stack) installed

Step 1: Install Java 8 for ELK

  • Update the package list : sudo apt update
  • Install OpenJDK 8 : sudo apt install -y openjdk-8-jdk
  • Verify the instalation : java -version
  • Ensure the output shows java8 installed.


If Java is installed on the machine, the following output will be displayed:

Text Copied

openjdk version "1.8.0_442"
OpenJDK Runtime Environment (build 1.8.0_442-8u442-b06~us1-0ubuntu1~20.04-b06)
OpenJDK 64-Bit Server VM (build 25.442-b06, mixed mode)

Step 2: Install and Configure the ELK Stack

  • Install Elasticsearch :

Update System Package : sudo apt update && sudo apt upgrade -y


Download Elasticsearch 8.17.3 :


wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.17.3-amd64.deb


Install elasticsearch : sudo dpkg -i elasticsearch-8.17.3-amd64.deb


Configure elasticsearch :


sudo nano /etc/elasticsearch/elasticsearch.yml


# Network settings
network.host: 0.0.0.0
http.port: 9200


# Cluster settings
cluster.name: my-cluster
node.name: node-1


# Security settings
xpack.security.enabled: true


Start and Enable elasticsearch :


sudo systemctl enable elasticsearch


sudo systemctl start elasticsearch

Check the status to see if Elasticsearch is running properly; the result should appear as shown below:

  • elasticsearch.service - Elasticsearch

Loaded: loaded (/lib/systemd/system/elasticsearch.service; enabled; vendor preset: enabled)

Active: active (running) since Tue 2025-03-25 11:59:26 IST; 16min ago

Docs: https://www.elastic.co

Main PID: 1554 (java)

Tasks: 92 (limit: 18932)

Memory: 8.5G

CGroup: /system.slice/elasticsearch.service

├─1554 /usr/share/elasticsearch/jdk/bin/java -Xms4m -Xmx64m -XX:+UseSerialGC -Dcli.name=server -Dcli.script=/usr/share/elasticsearch/bin/e>

├─2134 /usr/share/elasticsearch/jdk/bin/java -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouc>

└─2158 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

Mar 25 11:58:11 host systemd[1]: Starting Elasticsearch...

Mar 25 11:58:47 host systemd-entrypoint[2134]: CompileCommand: dontinline java/lang/invoke/MethodHandle.setAsTypeCache bool dontinline = true

Mar 25 11:58:47 host systemd-entrypoint[2134]: CompileCommand: dontinline java/lang/invoke/MethodHandle.asTypeUncached bool dontinline = true

Mar 25 11:59:26 host systemd[1]: Started Elasticsearch.

lines 1-16/16 (END)

Generate Password for elasticsearch. By Default the username and password is necessary to connect the elasticsearch version 8.17.3


Use the following command to generate the Elasticsearch password:


sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic


Verify Installation:


After the password is generated successfully, run the following command to verify it:

elasticsearch version 8.17.3 properly installed .
curl -k http://localhost:9200 -u elastic:your_password


If the elasticsearch has properly configured the below results exists :

{
"name" : "hostname",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "kKzyHzjcTGGei6ikXndcFA",
"version" : {
"number" : "8.17.3",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "a091390de485bd4b127884f7e565c0cad59b10d2",
"build_date" : "2025-02-28T10:07:26.089129809Z",
"build_snapshot" : false,
"lucene_version" : "9.12.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}

TLS/SSL configuration in elasticsearch 8.17.3 :


Elasticsearch 8.17.3 includes built-in security and requires TLS/SSL for communication. Follow these steps to configure TLS/SSL for both HTTP and transport layers.


  • Generate SSL certificate :

Elasticsearch includes a built-in tool to generate certificates. Use the following command to generate a certificate:


sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --pem --keep-ca-key --out /etc/elasticsearch/certs.zip


Extract the certificates :


sudo apt install unzip -y
sudo mkdir -p /etc/elasticsearch/certs
sudo unzip /etc/elasticsearch/certs.zip -d /etc/elasticsearch/certs/
sudo chmod -R 750 /etc/elasticsearch/certs
sudo chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs


    2. Configure the elasticsearch for TLS/SSL:


Edit the elasticsearch configuration file using the below command:


sudo nano /etc/elasticsearch/elasticsearch.yml


Add or update the settings:

If the features below are not present in elasticsearch.yml, add them. If they already exist, set or enable them to true.


# Enable security features
xpack.security.enabled: true
xpack.security.enrollment.enabled: true


# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12


# Create a new cluster with the current node only
# Additional nodes can still join the cluster later
cluster.initial_master_nodes: ["hostname"]


# Allow HTTP API connections from anywhere
# Connections are encrypted and require user authentication
http.host: 0.0.0.0


# Allow other nodes to join the cluster from anywhere
# Connections are encrypted and mutually authenticated
#transport.host: 0.0.0.0


Restart Elasticsearch :

Restart the elasticsearch to apply the changes :

sudo systemctl restart elasticsearch.service


Afterward, check whether Elasticsearch is running using the command below: :

sudo systemctl status elasticsearch.service


Verify Elasticsearch TLS/SSL Configuration :

By default our certificate exists in the below directory

sudo /etc/elasticsearch/certs


Use the following command to verify the TLS/SSL installation:

curl -k --cacert /etc/elasticsearch/certs/ca.crt -u elastic:password 'https://localhost:9200'


When Elasticsearch is configured correctly for TLS/SSL, the result appears as shown below:

{
"name" : "hostname",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "kKzyHzjcTGGei6ikXndcFA",
"version" : {
"number" : "8.17.3",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "a091390de485bd4b127884f7e565c0cad59b10d2",
"build_date" : "2025-02-28T10:07:26.089129809Z",
"build_snapshot" : false,
"lucene_version" : "9.12.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}

Install Logstash :


Download Logstash 8.17.3


wget https://artifacts.elastic.co/downloads/logstash/logstash-8.17.3-amd64.deb


Install Logstash 8.17.3


sudo dpkg -i logstash-8.17.3-amd64.deb


Verify Logstash Installation :


Check whether Logstash version 8.17.3 is installed using the command below. If the version is displayed, it means Logstash is installed correctly on our machine.

/usr/share/logstash/bin/logstash --version


The result looks like :

Using bundled JDK: /usr/share/logstash/jdk
logstash 8.17.3


Start and Enable logstash :

sudo systemctl enable logstash

sudo systemctl start logstash


Check the status for Logstash installation :

sudo systemctl status logstash


The output is as follows:

logstash.service - logstash
Loaded: loaded (/lib/systemd/system/logstash.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2025-03-25 12:55:40 IST; 11s ago
Main PID: 4519 (java)
Tasks: 24 (limit: 18932)
Memory: 344.9M
CGroup: /system.slice/logstash.service
└─4519 /usr/share/logstash/jdk/bin/java -Xms1g -Xmx1g -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.compile.invokedynamic=true -XX:+HeapDumpOnOutOfMemoryError ->
Mar 25 12:55:40 hostname systemd[1]: Started logstash.
Mar 25 12:55:40 hostname logstash[4519]: Using bundled JDK: /usr/share/logstash/jdk
lines 1-11/11 (END)

Check Logstash Logs in Log File

1. Logstash writes logs to /var/log/logstash/logstash-plain.log. View logs using:

sudo tail -f /var/log/logstash/logstash-plain.log


2. To check Logstash logs is using journalctl

sudo journalctl -u logstash -f


Download Kibana 8.17.3

To download Kibana 8.17.3, use the below command:

wget https://artifacts.elastic.co/downloads/kibana/kibana-8.17.3-amd64.deb


Install Kibana 8.17.3 :

sudo dpkg -i kibana-8.17.3-amd64.deb


Configure kibana 8.17.3 :

Follow the below steps to configure Kibana
Step-1:

Open the kibana configuration file :sudo nano /etc/kibana/kibana.yml


Step-2:
Uncomment and modify the below setting :

server.port: "5601"
server.host: "localhost"
elasticsearch.hosts: ["http://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "password"
elasticsearch.maxSockets: 1024


After modifying the settings, save and exit the configuration.

Start and Enable Kibana:


sudo systemctl enable kibana

sudo systemctl start kibana


To check whether Kibana is configured properly, the results appear as shown below:


  • kibana.service - Kibana

Loaded: loaded (/lib/systemd/system/kibana.service; enabled; vendor preset: enabled)

Active: active (running) since Tue 2025-03-25 15:14:22 IST; 9min ago

Docs: https://www.elastic.co

Main PID: 1554 (java)

Main PID: 9690 (node)

Tasks: 11 (limit: 18932)

Memory: 598.2M

CGroup: /system.slice/kibana.service

└─9690 /usr/share/kibana/bin/../node/glibc-217/bin/node /usr/share/kibana/bin/../src/cli/dist

Mar 25 15:17:09 hostname kibana[9690]: [2025-03-25T15:17:09.848+05:30][ERROR][http] 400 Bad Request

Mar 25 15:19:46 hostname kibana[9690]: [2025-03-25T15:19:46.504+05:30][INFO ][plugins.securitySolution] Fetch risk engine metrics

Mar 25 15:19:46 hostname kibana[9690]: [2025-03-25T15:19:46.860+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Resources payload was sent successfully

Mar 25 15:19:46 hostname kibana[9690]: [2025-03-25T15:19:46.861+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Accounts payload was sent successfully

Mar 25 15:19:46 hostname kibana[9690]: [2025-03-25T15:19:46.862+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Rules payload was sent successfully

Mar 25 15:19:47 hostname kibana[9690]: [2025-03-25T15:19:47.193+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Alerts payload was sent successfully

Mar 25 15:19:47 hostname kibana[9690]: [2025-03-25T15:19:47.199+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Cloud Accounts payload was sent successfully

Mar 25 15:19:47 hostname kibana[9690]: [2025-03-25T15:19:47.336+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Muted Rules payload was sent successfully

Mar 25 15:19:47 hostname kibana[9690]: [2025-03-25T15:19:47.372+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Installation payload was sent successfully

Mar 25 15:19:47 hostname kibana[9690]: [2025-03-25T15:19:47.406+05:30][INFO ][plugins.cloudSecurityPosture] Cloud Security telemetry: Indices payload was sent successfully


Open kibana in browser :


Once Kibana is configured properly, open it using the following URL:


http://<server_ip>:5601


For example :http://localhost:5601


Configure kibana 8.17.3 with TLS/SSL:


If Elasticsearch is already configured with TLS/SSL (HTTPS), you need to configure Kibana to communicate securely with it.


Now, let's see how to set up Kibana with TLS/SSL:


Step-1 :

Open the configuration file :sudo nano /etc/kibana/kibana.yml


Step-2 :
Copy the certficate from the elasticsearch certs directory to the kibana certs directory :


cp /etc/elasticsearch/certs/elastic-stack-ca.crt /etc/kibana/


Set the corrector permissions for certificates :


chown kibana:kibana /etc/kibana/elastic-stack-ca.crt


chmod 600 /etc/kibana/elastic-stack-ca.crt


Verify the file ownership and permissions :


ls -l /etc/kibana/elastic-stack-ca.crt


The output appears as follows:
-rwxr-x--- 1 kibana kibana 1915 Mar 25 13:56 /etc/kibana/elastic-stack-ca.crt


Step-3 :
Uncomment and modify the below setting :


server.port: 5601
server.host : "localhost"
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "password"
elasticsearch.maxSockets: 1024
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/http_ca.crt" ]


Finally save and exit the kibana configurations.


If you want to access Kibana over HTTPS instead of http://localhost:5601, configure TLS in kibana.yml:


Add these settings:


server.ssl.enabled: true
server.ssl.certificate: "/etc/kibana/kibana.crt"
server.ssl.key: "/etc/kibana/kibana.key"


Step-4 :
Restart the Kibana to get the changes applied:


sudo systemctl restart kibana.service


If you do not have the Elasticsearch user, use the command below to manually reset the password.

Manually Set Password for User


Use the following command in your terminal:


sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u <username> -i


step-4 : Try Accessing Kibana


If you're using Kibana HTTPS, use:


https://localhost:5601


If Kibana SSL is disabled, use:


http://localhost:5601


If Kibana is running on a remote server, replace localhost with the server's IP:


http://your-server-ip:5601


Download MQTT Broker and Running in our machine and it looks like the


Elasticsearch Connector Configuration


The Elasticsearch Connector in CrystalMQ allows seamless data retrieval from the broker and efficient indexing into Elasticsearch. It ensures secure authentication, encrypted communication, and reliable data storage, making it an essential component for managing and analyzing IoT data.


  • Host: Enter the hostname or IP address of the Elasticsearch server.
  • Port: Specify the port on which the Elasticsearch server is listening (default: 9200).
  • Index: Enter the name of the Elasticsearch index for storing or retrieving data.
  • Authentication: Select the authentication method:
    Basic Auth:Authenticate using a username and password.
    PKI Auth:Authenticate using Public Key Infrastructure (PKI) with client certificates.
    JWT Auth:Authenticate using a JSON Web Token (JWT).
  • Access Token: If using JWT authentication, enter a valid JWT access token.
  • SSL: Enable SSL/TLS for a secure connection. If enabled, provide the required certificate files.
  • CA Certificate: Upload the Certificate Authority (CA) certificate if using a self-signed certificate.
  • Client Certificate & Key: If using PKI authentication, upload the required client certificate and client key

1. Authentication in Elasticsearch Connector


Elasticsearch supports multiple authentication methods to ensure secure access.


Basic Authentication


By default, Elasticsearch requires a username and password for authentication. Without valid credentials, the connection will fail, leading to authentication errors. This method is simple and widely used for securing access.


PKI (Public Key Infrastructure) Authentication


PKI authentication uses digital certificates instead of passwords for secure access. In this approach:


  • A Client Certificate and Client Key are required to establish a trusted connection with Elasticsearch.
  • The server verifies the certificate against a trusted Certificate Authority (CA) to ensure authenticity.
  • This method enhances security by eliminating the need for passwords while ensuring encrypted and authenticated communication.

JWT (JSON Web Token) Authentication


JWT authentication provides token-based access control, where an Access Token is used instead of traditional credentials.


  • Authentication providers like Google or Keycloak generate an access token for users.
  • Elasticsearch validates the token using a secret key stored in its configuration.
  • This method enables single sign-on (SSO) and secure, scalable authentication.

2. Encryption: SSL/TLS in Elasticsearch


To protect data in transit, Elasticsearch supports SSL/TLS encryption, ensuring that communication between clients and the server remains private and secure.


Setting Up SSL/TLS Encryption


  • OpenSSL is used to generate security certificates required for encrypted communication.
  • Elasticsearch requires specific certificates:

    1. CA Certificate - A trusted certificate authority that signs other certificates.

    2. Client Certificate - Identifies the client to Elasticsearch.

    3. Client Key - A private key used to authenticate the client certificate.


By configuring authentication and encryption properly, the Elasticsearch Connector in CrystalMQ provides a secure, scalable, and efficient solution for managing IoT data.


Elasticsearch Connector

In the Elasticsearch connector, basic authentication (username and password) is required, so it can be configured as the default.


Elasticsearch Connector Details


Enter the configurations in the Elasticsearch connector, including the Elasticsearch index, to establish the connection.


Once all configuration fields are completed, select 'Save' to save the configurations to the database.


If the Elasticsearch connector is connected successfully, the Enable/Disable toggle button will show green. If there is an issue with the connector, the button will display red.


Elasticsearch Connector


In the above configuration, only Basic Authentication is used, without enabling TLS/SSL encryption.


Use Logstash to view data from Elasticsearch. Let’s see how we can use the Logstash pipeline to capture this data.


Logstash offers various methods to output data, depending on how you want to store, visualize, or forward it. Some common output options include:


  • Elasticsearch
  • File
  • Standard Output (stdout)
  • Kafka
  • Redis
  • AWS S3 / Google Cloud Storage
  • InfluxDB
  • Email
  • TCP / UDP
  • Http
  • Graphite
  • WebSocket
  • Google BigQuery

Step -1 :

Configure Logstash to retrieve data from Elasticsearch:


  • Create a Logstash configuration file
    Create a file named elasticsearch_logstash.conf in the Logstash
    configuration directory

  • Edit the Configuration File
    Open elasticsearch_logstash.conf and add the following configuration:

input {
elasticsearch {
hosts => ["http://your-elasticsearch-host:9200"]
index => "your-index-name"
user => "your-username"
password => "your-password"
}
}
output {
stdout {
codec => json
}
}


Run Logstash


Start Logstash using the following command:


In case Logstash has been installed through a package manager:


sudo /usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/elasticsearch_logstash.conf


For example : sudo /usr/share/logstash/bin/logstash -f

~/Documents/elasticsearch_logstash.conf


After configuring Logstash, use the command below to verify that the configuration has been applied correctly.


sudo /usr/share/logstash/bin/logstash --path.settings /etc/logstash -f
path/to/elasticsearch_logstash.conf --config.test_and_exit


If the configuration is correct, the output is as follows:

Using bundled JDK: /usr/share/logstash/jdk

Sending Logstash logs to /var/log/logstash which is now configured via

log4j2.properties

[2025-03-26T11:40:50,375][WARN ][logstash.runner ] NOTICE: Running

Logstash as a superuser is strongly discouraged as it poses a security risk.

Set 'allow_superuser' to false for better security.

[2025-03-26T11:40:50,386][INFO ][logstash.runner ] Log4j configuration

path used is: /etc/logstash/log4j2.properties

[2025-03-26T11:40:50,388][INFO ][logstash.runner ] Starting Logstash

{"logstash.version"=>"8.17.3", "jruby.version"=>"jruby 9.4.9.0 (3.1.4) 2024-11-

04 547c6b150e OpenJDK 64-Bit Server VM 21.0.6+7-LTS on 21.0.6+7-LTS +indy

+jit [x86_64-linux]"}

[2025-03-26T11:40:50,392][INFO ][logstash.runner ] JVM bootstrap

flags: [-Xms1g, -Xmx1g, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -

Djruby.compile.invokedynamic=true, -

XX:+HeapDumpOnOutOfMemoryError, -

Djava.security.egd=file:/dev/urandom, -

Dlog4j2.isThreadContextMapInheritable=true, -Dlogstash.jackson.stream-

read-constraints.max-string-length=200000000, -

Dlogstash.jackson.stream-read-constraints.max-number-length=10000, -

Djruby.regexp.interruptible=true, -Djdk.io.File.enableADS=true, --add-

exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED, --add-

opens=java.base/java.security=ALL-UNNAMED, --add-

opens=java.base/java.io=ALL-UNNAMED, --add-

opens=java.base/java.nio.channels=ALL-UNNAMED, --add-

opens=java.base/sun.nio.ch=ALL-UNNAMED, --add-

opens=java.management/sun.management=ALL-UNNAMED, -

Dio.netty.allocator.maxOrder=11]

[2025-03-26T11:40:50,462][INFO]

[org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value

override `logstash.jackson.stream-read-constraints.max-string-length`

configured to `200000000`

[2025-03-26T11:40:50,463][INFO]

[org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value

override `logstash.jackson.stream-read-constraints.max-number-length`

configured to `10000`

[2025-03-26T11:40:50,755][WARN ][logstash.config.source.multilocal]

Ignoring the 'pipelines.yml' file because modules or command line options

are specified

[2025-03-26T11:40:51,186][INFO ][org.reflections.Reflections] Reflections

took 177 ms to scan 1 urls, producing 152 keys and 530 values

[2025-03-26T11:40:51,846][INFO ][logstash.javapipeline ] Pipeline `main` is

configured with `pipeline.ecs_compatibility: v8` setting. All plugins in this

pipeline will default to `ecs_compatibility => v8` unless explicitly

configured otherwise.

Configuration OK

[2025-03-26T11:40:51,848][INFO ][logstash.runner ] Using

config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash


Check the Logstash logs using the command below to verify that data is being retrieved from Elasticsearch and displayed in Logstash.


The Logstash log appears as shown below:


Using bundled JDK: /usr/share/logstash/jdk

[WARN ] 2025-03-25 18:16:42.180 [main] runner - 'pipeline.buffer.type'

setting is not explicitly defined.Before moving to 9.x set it to 'heap' and

tune heap size upward, or set it to 'direct' to maintain existing behavior.

[INFO ] 2025-03-25 18:16:42.181 [main] runner - Starting Logstash

{"logstash.version"=>"8.17.3", "jruby.version"=>"jruby 9.4.9.0 (3.1.4) 2024-11-

04 547c6b150e OpenJDK 64-Bit Server VM 21.0.6+7-LTS on 21.0.6+7-LTS +indy

+jit [x86_64-linux]"}

[INFO ] 2025-03-25 18:16:42.185 [main] runner - JVM bootstrap flags: [-Xms1g,

-Xmx1g, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -

Djruby.compile.invokedynamic=true, -

XX:+HeapDumpOnOutOfMemoryError, -

Djava.security.egd=file:/dev/urandom, -

Dlog4j2.isThreadContextMapInheritable=true, -Dlogstash.jackson.stream-

read-constraints.max-string-length=200000000, -

Dlogstash.jackson.stream-read-constraints.max-number-length=10000, -

Djruby.regexp.interruptible=true, -Djdk.io.File.enableADS=true, --add-

exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED, --add-

exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED, --add-

opens=java.base/java.security=ALL-UNNAMED, --add-

opens=java.base/java.io=ALL-UNNAMED, --add-

opens=java.base/java.nio.channels=ALL-UNNAMED, --add-

opens=java.base/sun.nio.ch=ALL-UNNAMED, --add-

opens=java.management/sun.management=ALL-UNNAMED, -

Dio.netty.allocator.maxOrder=11]

[INFO ] 2025-03-25 18:16:42.373 [main] StreamReadConstraintsUtil - Jackson

default value override `logstash.jackson.stream-read-constraints.max-

string-length` configured to `200000000`

[INFO ] 2025-03-25 18:16:42.373 [main] StreamReadConstraintsUtil - Jackson

default value override `logstash.jackson.stream-read-constraints.max-

number-length` configured to `10000`

[WARN ] 2025-03-25 18:16:42.655 [LogStash::Runner] multilocal - Ignoring

the 'pipelines.yml' file because modules or command line options are

specified

[INFO ] 2025-03-25 18:16:43.449 [Api Webserver] agent - Successfully started

Logstash API endpoint {:port=>9601, :ssl_enabled=>false}

[INFO ] 2025-03-25 18:16:43.805 [Converge PipelineAction::Create

]

Reflections - Reflections took 169 ms to scan 1 urls, producing 152 keys and

[INFO ] 2025-03-25 18:16:44.521 [Converge PipelineAction::Create

]

javapipeline - Pipeline `main` is configured with

`pipeline.ecs_compatibility: v8` setting. All plugins in this pipeline will

default to `ecs_compatibility => v8` unless explicitly configured

otherwise.

[INFO ] 2025-03-25 18:16:44.579 [[main]-pipeline-manager] javapipeline -

Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>4,

"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,

"pipeline.max_inflight"=>500,

"pipeline.sources"=>["/home/bevywise/Documents/elasticsearch_logstash.

conf"], :thread=>"#<Thread:0x612a9b3c /usr/share/logstash/logstash-

core/lib/logstash/java_pipeline.rb:138 run>"}

[INFO ] 2025-03-25 18:16:45.277 [[main]-pipeline-manager] javapipeline -

Pipeline Java execution initialization time {"seconds"=>0.7}

[INFO ] 2025-03-25 18:16:45.591 [[main]-pipeline-manager] elasticsearch -

`search_api => auto` resolved to `search_after` {:elasticsearch=>"8.17.3"}

[INFO ] 2025-03-25 18:16:45.593 [[main]-pipeline-manager] elasticsearch -

ECS compatibility is enabled but `target` option was not specified. This

may cause fields to be set at the top-level of the event where they are

likely to clash with the Elastic Common Schema. It is recommended to set

the `target` option to avoid potential schema conflicts (if your data is ECS

compliant or non-conflicting, feel free to ignore this message)

[INFO ] 2025-03-25 18:16:45.597 [[main]-pipeline-manager] javapipeline -

Pipeline started {"pipeline.id"=>"main"}

[INFO ] 2025-03-25 18:16:45.600 [[main]<elasticsearch] searchafter - Create

point in time (PIT)

[INFO ] 2025-03-25 18:16:45.619 [Agent thread] agent - Pipelines running

{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}

[INFO ] 2025-03-25 18:16:45.630 [[main]<elasticsearch] searchafter - Query

start

[INFO ] 2025-03-25 18:16:45.703 [[main]<elasticsearch] searchafter - Query

completed

[INFO ] 2025-03-25 18:16:45.704 [[main]<elasticsearch] searchafter - Closing

point in time (PIT)

{
"message" => "{\"sensor_id\": \"sensor_123\", \"temperature\": 25.5, \"humidity\": 60, \"status\": \"active\"}",
"topic" => "test/search",
"client_id" => "Bevywise-fQ4kK3aI2uQ0",
"timestamp" => 1742478868,
"properties" => "{}",
"@version" => "1",
"@timestamp" => 2025-03-25T12:46:45.691895415Z
}

{
"message" => "{\"sensor_id\": \"sensor123\", \"temperature\": 27, \"humidity\": 712, \"status\": \"active\"}",
"topic" => "test/moniting",
"client_id" => "Bevywise-qI8mQ7rI9uM3",
"timestamp" => 1742817477,
"properties" => "{}",
"@version" => "1",
"@timestamp" => 2025-03-25T12:46:45.693859511Z
}

{
"message" => "{\"sensor_id\": \"sensor123\", \"temperature\": 27, \"humidity\": 712, \"status\": \"active\"}",
"topic" => "test/moniting",
"client_id" => "Bevywise-eP3cT2xW0vA4",
"timestamp" => 1742817662,
"properties" => "{}",
"@version" => "1",
"@timestamp" => 2025-03-25T12:46:45.693957511Z
}


Use Kibana to visualize the data once Elasticsearch has received it from the CrystalMQ Elasticsearch Connector.


Step-1:


Open the browser url like http://<host_ip>:5601


Step-2: Create an Index Pattern


Before visualizing data, you need to define an index pattern to access your MQTT logs.


  • Go to "Stack Management" → "Index Patterns".
  • Click "Create Index Pattern".
  • Enter your index name (e.g., offset_mqtt-*).
  • Select the timestamp field (@timestamp if available).
  • Click "Create index pattern".

Step-3: Chart for MQTT Messages Over Time


Before visualizing data, you need to define an index pattern to access your MQTT logs.


  • Go to "Visualize Library" → Click "Create visualization".
  • Select "Line Chart".
  • Choose your index pattern (offset_mqtt-*).
  • Configure:
    X-axis: Select @timestamp and set interval (e.g., 1m, 1h).
    Y-axis: Select Count to count MQTT messages.
  • Click "Save" and name your visualization.

Step-4: The chart looks as follows:


Bar chart :


Bar Chart


Pie-chart :


Pie Chart


Table View :


Table View


Now, we will use Elasticsearch with TLS/SSL encryption to establish a connection and send messages through Data Connectors in CrystalMQ:



Step-1 : Verify that all certificate paths in the Elasticsearch configuration are provided correctly. If any changes are made, restart Elasticsearch to apply them.



Step-2 : Open the Kibana configuration file and verify that all settings are properly configured for TLS/SSL.



Step-3 : Run CrystalMQ and use the Elasticsearch connector in Data Connectors to connect to Elasticsearch with SSL/TLS encryption.



Step-4 : For SSL/TLS encryption, the CA root certificate is required to connect to Elasticsearch. The client certificate and client key are optional—uploading just the CA root certificate is sufficient to establish the connection.



Elasticsearch


Step-5 : After uploading all the certificates, save the configuration and enable the connector using the Enable/Disable toggle button.



Enable Certificates


Step-6 : The Elasticsearch connector with TLS/SSL encryption has now been successfully connected in CrystalMQ.



Use Logstash to view the logs from the Elasticsearch connector:



Configure Logstash to Retrieve Data from Elasticsearch:

  • Create a Logstash configuration file
    Create a file named elasticsearch_logstash.conf in the Logstash
    configuration directory
  • Edit the Configuration File
    Open elasticsearch_logstash.conf and add the following configuration:

input {
elasticsearch {
hosts => ["https://your_elasticsearch_host:9200"]
user => "elastic"
password => "your_password"
index => "your_index_pattern"
ssl => true
cacert => "/path/to/elasticsearch-ca.crt"
}
}


output {
stdout {
codec => rubydebug
}
}


Save the configuration and use the command below to verify whether it has been established correctly:


sudo /usr/share/logstash/bin/logstash --path.settings /etc/logstash -f

path/to/elasticsearch_logstash.conf --config.test_and_exit


Use Logstash to capture the data from elasticsearch with TLS/SSL :


If you've installed Logstash via a package manager:


sudo /usr/share/logstash/bin/logstash -f

/etc/logstash/conf.d/elasticsearch_logstash.conf


For example : sudo /usr/share/logstash/bin/logstash -f
~/Documents/elasticsearch_logstash.conf


Now Configure the Kibana with elasticsearch TLS/SSL:



Refer to the steps above to configure kibana.yml for Elasticsearch with TLS/SSL encryption.



Open the browser at https://<host_ip>:5601 and visualize the data in Kibana using the instructions above, with options such as bar charts, pie charts, and data views.



In Elasticsearch version 8.17.3, we are using the basic license, so PKI and JWT cannot be used to establish the connection.

To use JWT and PKI authentication, an upgrade to the Platinum license is required.


Using PKI authentication in CrystalMQ:


In PKI authentication, the client certificate and client key are required, while the CA root certificate is optional.


Save the configuration and enable the connector toggle button to connect to Elasticsearch using PKI authentication.


Elasticsearch is now configured with PKI authentication.


If we want to encrypt the data, we can use SSL/TLS with PKI authentication.


To encrypt the data, SSL/TLS can be used along with PKI authentication.


In PKI authentication with SSL/TLS, the client certificate and client key are required, while for SSL-only connections, only the CA root certificate is needed to connect to Elasticsearch.




Save Configurations


Using JWT authentication in CrystalMQ:



In JWT (JSON Web Tokens) authentication, the access token is used to connect to Elasticsearch.


Use an authentication provider, such as Keycloak or Google Console, to obtain the access key.


Now, use the access key with the command below to obtain the access token:


curl --cacert /etc/keycloak.crt -X POST
"https://localhost:8443/realms/myrealm/protocol/openid-
connect/token["](https://localhost:8443/realms/myrealm/protocol/openid-
connect/token") \

-H "Content-Type: application/x-www-form-urlencoded" \

-d "grant_type=client_credentials" \

-d "client_id=elasticsearch" \

-d "client_secret=ACCESS_KEY"


In this command, the Keycloak authentication provider is used to obtain the authentication token.



After obtaining the access token, use it in the Elasticsearch data connector to connect to Elasticsearch using JWT authentication.



Authentication


If we want to encrypt the data, we can use SSL/TLS with PKI authentication.



Upload Client Certificate

When using SSL/TLS with JWT, simply upload the CA root certificate to connect to Elasticsearch.


Optimize MQTT Network!

Actionable MQTT Insights with ELK

Monitor and analyze MQTT broker messages in real time to improve IoT
performance and detect potential issues instantly.