Implement Apache log analysis with GoAccess and ELK stack for real-time monitoring

Intermediate 45 min Apr 27, 2026 119 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive Apache log monitoring with GoAccess for real-time analysis and ELK stack for centralized log processing, creating powerful Kibana dashboards for web server insights and automated alerting.

Prerequisites

  • Apache HTTP server installed and running
  • Minimum 4GB RAM for ELK stack
  • Root or sudo access
  • At least 20GB free disk space

What this solves

Apache web servers generate massive amounts of log data that contain valuable insights about traffic patterns, errors, and performance issues. This tutorial shows you how to implement a complete log analysis pipeline using GoAccess for real-time terminal-based analysis and the ELK stack (Elasticsearch, Logstash, Kibana) for centralized processing and visualization. You'll create professional dashboards and set up automated alerting for proactive monitoring.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions of all components.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 software-properties-common
sudo dnf update -y
sudo dnf install -y curl wget gnupg2

Install GoAccess for real-time log analysis

GoAccess provides immediate insights into Apache logs with terminal-based and HTML reports.

sudo apt install -y goaccess
sudo dnf install -y epel-release
sudo dnf install -y goaccess

Configure GoAccess for Apache logs

Create a configuration file that matches Apache's default log format and enables real-time updates.

time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"

real-time-html true
port 7890
ws-url wss://example.com:7890

html-prefs {"theme":"bright","perPage":10}
html-report-title Apache Log Analysis

ignore-panel REFERRERS
ignore-panel KEYPHRASES
ignore-panel GEOLOCATION

output /var/www/html/goaccess-report.html

Set up Java repository for Elasticsearch

The ELK stack requires Java. Add the official repositories for the latest versions.

sudo apt install -y openjdk-11-jdk
echo 'JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' | sudo tee -a /etc/environment
source /etc/environment
sudo dnf install -y java-11-openjdk java-11-openjdk-devel
echo 'JAVA_HOME=/usr/lib/jvm/java-11-openjdk' | sudo tee -a /etc/environment
source /etc/environment

Add Elastic Stack repository

Add the official Elastic repository to install Elasticsearch, Logstash, and Kibana.

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elastic-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
sudo tee /etc/yum.repos.d/elastic.repo << '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

Install Elasticsearch

Install Elasticsearch for storing and indexing Apache log data.

sudo apt install -y elasticsearch
sudo dnf install -y elasticsearch

Configure Elasticsearch

Configure Elasticsearch for Apache log storage with appropriate memory settings and network binding.

cluster.name: apache-logs
node.name: apache-logs-node-1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: localhost
http.port: 9200
cluster.initial_master_nodes: ["apache-logs-node-1"]

xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

Configure Elasticsearch JVM heap

Set appropriate heap size based on your server memory. Use 50% of available RAM, maximum 32GB.

-Xms2g
-Xmx2g

Install Logstash

Install Logstash to process and transform Apache logs before sending to Elasticsearch.

sudo apt install -y logstash
sudo dnf install -y logstash

Configure Logstash for Apache logs

Create a Logstash pipeline configuration to parse Apache access logs and error logs.

input {
  file {
    path => "/var/log/apache2/access.log"
    type => "apache_access"
    start_position => "beginning"
  }
  file {
    path => "/var/log/apache2/error.log"
    type => "apache_error"
    start_position => "beginning"
  }
}

filter {
  if [type] == "apache_access" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
    date {
      match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
    }
    mutate {
      convert => { "response" => "integer" }
      convert => { "bytes" => "integer" }
    }
    if [clientip] {
      geoip {
        source => "clientip"
      }
    }
  }
  
  if [type] == "apache_error" {
    grok {
      match => { "message" => "\[%{HTTPDATE:timestamp}\] \[%{WORD:level}\] \[pid %{POSINT:pid}\] %{GREEDYDATA:error_message}" }
    }
    date {
      match => [ "timestamp" , "EEE MMM dd HH:mm:ss.SSSSSS yyyy" ]
    }
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "apache-logs-%{+YYYY.MM.dd}"
  }
  stdout { codec => rubydebug }
}

Install Kibana

Install Kibana for visualizing and creating dashboards from the Apache log data.

sudo apt install -y kibana
sudo dnf install -y kibana

Configure Kibana

Configure Kibana to connect to Elasticsearch and bind to the appropriate network interface.

server.port: 5601
server.host: "0.0.0.0"
server.name: "apache-logs-kibana"
elasticsearch.hosts: ["http://localhost:9200"]
elasticsearch.requestTimeout: 90000
logging.appenders.file.type: file
logging.appenders.file.fileName: /var/log/kibana/kibana.log
logging.appenders.file.layout.type: json
logging.root.appenders: [default, file]

Start and enable ELK services

Start all ELK stack services and enable them to start automatically on boot.

sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
sudo systemctl enable logstash
sudo systemctl start logstash
sudo systemctl enable kibana
sudo systemctl start kibana

Configure Apache log format

Ensure Apache is configured with the combined log format for better parsing. This configuration works with the Logstash grok pattern we defined.

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

CustomLog /var/log/apache2/access.log combined
ErrorLog /var/log/apache2/error.log

Set up log file permissions

Configure proper permissions so Logstash can read Apache log files without compromising security.

Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions.
sudo usermod -a -G adm logstash
sudo chmod 644 /var/log/apache2/access.log
sudo chmod 644 /var/log/apache2/error.log
sudo chown root:adm /var/log/apache2/access.log
sudo chown root:adm /var/log/apache2/error.log

Create GoAccess systemd service

Set up GoAccess as a systemd service for continuous real-time log monitoring.

[Unit]
Description=GoAccess Apache Log Analysis
After=apache2.service

[Service]
Type=simple
User=www-data
Group=www-data
ExecStart=/usr/bin/goaccess /var/log/apache2/access.log -c /etc/goaccess/goaccess.conf --real-time-html --daemonize
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start GoAccess service

Start the GoAccess service to begin real-time log analysis.

sudo systemctl daemon-reload
sudo systemctl enable goaccess
sudo systemctl start goaccess

Configure firewall rules

Open necessary ports for Kibana web interface and GoAccess real-time updates.

sudo ufw allow 5601/tcp comment 'Kibana'
sudo ufw allow 7890/tcp comment 'GoAccess WebSocket'
sudo ufw reload
sudo firewall-cmd --permanent --add-port=5601/tcp
sudo firewall-cmd --permanent --add-port=7890/tcp
sudo firewall-cmd --reload

Create Kibana dashboards

Create index pattern in Kibana

Access Kibana at http://your-server-ip:5601 and create an index pattern for Apache logs.

  1. Open Kibana in your browser
  2. Go to Management → Stack Management → Index Patterns
  3. Click "Create index pattern"
  4. Enter apache-logs-* as the index pattern
  5. Select @timestamp as the time field
  6. Click "Create index pattern"

Import dashboard configuration

Create a comprehensive dashboard with key Apache metrics and visualizations.

{
  "objects": [
    {
      "attributes": {
        "title": "Apache Access Logs Overview",
        "type": "dashboard",
        "description": "Comprehensive Apache log analysis dashboard",
        "panelsJSON": "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15},\"panelIndex\":\"1\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"}]",
        "refreshInterval": {
          "pause": false,
          "value": 30000
        },
        "timeRestore": true,
        "timeTo": "now",
        "timeFrom": "now-24h"
      },
      "id": "apache-overview",
      "type": "dashboard"
    }
  ]
}

Set up real-time monitoring alerts

Create Elasticsearch watcher for error monitoring

Set up automated alerts for Apache error patterns and high traffic spikes.

curl -X PUT "localhost:9200/_watcher/watch/apache_errors" -H 'Content-Type: application/json' -d'
{
  "trigger": {
    "schedule": {
      "interval": "5m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": ["apache-logs-*"],
        "body": {
          "query": {
            "bool": {
              "filter": [
                {
                  "range": {
                    "@timestamp": {
                      "gte": "now-5m"
                    }
                  }
                },
                {
                  "terms": {
                    "response": [500, 502, 503, 504]
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gt": 10
      }
    }
  },
  "actions": {
    "log_error": {
      "logging": {
        "level": "error",
        "text": "High number of Apache server errors detected: {{ctx.payload.hits.total}} errors in the last 5 minutes"
      }
    }
  }
}'

Configure log rotation for Apache logs

Set up log rotation to prevent disk space issues while maintaining log history for analysis. The existing log rotation configuration may need adjustment for higher traffic sites.

/var/log/apache2/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    sharedscripts
    postrotate
        if /bin/systemctl status apache2 > /dev/null ; then \
            /bin/systemctl reload apache2 > /dev/null; \
        fi;
        if /bin/systemctl status logstash > /dev/null ; then \
            /bin/systemctl restart logstash > /dev/null; \
        fi;
    endscript
    create 644 root adm
}

Verify your setup

Check that all services are running correctly and processing logs:

sudo systemctl status elasticsearch
sudo systemctl status logstash
sudo systemctl status kibana
sudo systemctl status goaccess

Verify Elasticsearch is receiving data:

curl -X GET "localhost:9200/_cat/indices?v"
curl -X GET "localhost:9200/apache-logs-*/_search?size=5&pretty"

Test GoAccess HTML report generation:

goaccess /var/log/apache2/access.log -c /etc/goaccess/goaccess.conf --html-report-title="Test Report" -o /tmp/test-report.html

Generate some test traffic and verify logs are being processed:

curl -I http://localhost/
curl -I http://localhost/nonexistent-page
tail -f /var/log/apache2/access.log

Common issues

SymptomCauseFix
Logstash not reading logsPermission denied on log filessudo usermod -a -G adm logstash && sudo systemctl restart logstash
Kibana dashboard emptyNo data in ElasticsearchCheck Logstash status: sudo systemctl status logstash and log parsing errors
GoAccess real-time not workingWebSocket connection failedVerify port 7890 is open and ws-url matches your domain in goaccess.conf
Elasticsearch service fails to startInsufficient heap memoryReduce heap size in /etc/elasticsearch/jvm.options.d/heap.options
High disk usageLog files growing rapidlyConfigure index lifecycle management or adjust log rotation frequency
Grok parsing failures in LogstashCustom Apache log formatUpdate grok pattern in /etc/logstash/conf.d/apache.conf to match your log format

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.