The ELK Stack — Elasticsearch, Logstash, and Kibana — is the industry-standard open-source platform for centralizing, parsing, and visualizing log data. Elasticsearch stores and indexes log events, Logstash ingests and transforms raw log lines using configurable pipelines, and Kibana provides a browser-based interface for search and visualization. Running the ELK Stack on RHEL 8 gives system administrators a powerful alternative to commercial log management products, with full control over data retention and privacy. This guide walks through installing all three components from the official Elastic 8.x repository and building a working Logstash pipeline for NGINX access logs.
Prerequisites
- A RHEL 8 server with at least 4 GB of RAM (8 GB recommended for production)
- A non-root sudo user and SELinux in enforcing or permissive mode
- Java 17 is not required — Elasticsearch 8.x bundles its own JDK
- Firewall ports 9200 (Elasticsearch) and 5601 (Kibana) to be opened
- NGINX installed and generating access logs at
/var/log/nginx/access.log
Step 1 — Add the Elastic 8.x Repository
Elastic publishes an official RPM repository for all three components. Import the GPG key and create the repo file before running any installs.
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
sudo tee /etc/yum.repos.d/elasticsearch.repo > /dev/null <<'EOF'
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
sudo dnf install -y elasticsearch logstash kibana
Step 2 — Configure and Start Elasticsearch
For a single-node setup, set discovery.type to single-node so Elasticsearch does not wait for cluster formation. Security features (TLS + authentication) are enabled by default in Elasticsearch 8; disable them here for a lab environment, or follow the Elastic security hardening guide for production.
sudo tee -a /etc/elasticsearch/elasticsearch.yml > /dev/null <<'EOF'
discovery.type: single-node
xpack.security.enabled: false
xpack.security.http.ssl.enabled: false
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch
sudo systemctl status elasticsearch
# Verify Elasticsearch is accepting connections
curl -s http://localhost:9200 | python3 -m json.tool
Step 3 — Configure and Start Kibana
Tell Kibana where to find Elasticsearch by setting elasticsearch.hosts in kibana.yml. Kibana listens on 0.0.0.0:5601 by default; tighten this to a specific interface in production.
sudo tee -a /etc/kibana/kibana.yml > /dev/null <<'EOF'
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://localhost:9200"]
EOF
sudo systemctl enable --now kibana
sudo systemctl status kibana
sudo firewall-cmd --permanent --add-port=9200/tcp
sudo firewall-cmd --permanent --add-port=5601/tcp
sudo firewall-cmd --reload
Step 4 — Create a Logstash Pipeline for NGINX Logs
Logstash pipelines are defined in /etc/logstash/conf.d/. The file below reads NGINX access logs, parses each line with the built-in COMBINEDAPACHELOG Grok pattern, and ships the structured events to Elasticsearch under the index nginx-logs.
sudo tee /etc/logstash/conf.d/nginx.conf > /dev/null < "/var/log/nginx/access.log"
start_position => "beginning"
sincedb_path => "/dev/null"
tags => ["nginx"]
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp"
}
mutate {
convert => { "bytes" => "integer" }
remove_field => [ "timestamp" ]
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "nginx-logs-%{+YYYY.MM.dd}"
}
}
EOF
Step 5 — Test the Pipeline and Start Logstash
Always validate a new pipeline configuration with --config.test_and_exit before starting the service. A configuration error at startup will prevent Logstash from processing any events.
# Validate config — should print "Configuration OK"
sudo /usr/share/logstash/bin/logstash
--path.settings /etc/logstash
--config.test_and_exit
sudo systemctl enable --now logstash
sudo systemctl status logstash
# Watch the pipeline come online
sudo journalctl -u logstash -f
Step 6 — Verify Data in Kibana
Open http://<server-ip>:5601 in your browser. Navigate to Management → Stack Management → Index Management to confirm the nginx-logs-* index exists and has documents. Then go to Analytics → Discover, create a data view matching nginx-logs-*, and explore your parsed NGINX events. Fields such as clientip, verb, response, and bytes will be available for filtering and visualization.
# Confirm documents were indexed
curl -s "http://localhost:9200/nginx-logs-*/_count" | python3 -m json.tool
# Check Elasticsearch cluster health
curl -s http://localhost:9200/_cluster/health | python3 -m json.tool
Conclusion
You have successfully installed and configured the full ELK Stack on RHEL 8. Elasticsearch is storing indexed log data, Logstash is parsing NGINX access logs with Grok patterns and forwarding structured events to Elasticsearch, and Kibana is available for searching and visualizing that data in your browser. The single-node configuration used here is ideal for development and small deployments; scaling to a multi-node cluster simply requires adding additional elasticsearch.yml entries and updating the discovery.seed_hosts setting. From this foundation you can add Beats agents on remote hosts to ship logs without the overhead of Logstash, or create Kibana dashboards and alerts to surface anomalies in your log data automatically.
Next steps: Installing Filebeat to Ship Logs to Elasticsearch on RHEL 8, Creating Kibana Dashboards and Alerts for NGINX Logs, and Securing the ELK Stack with TLS and Role-Based Access Control.