Set up automated log rotation with Elasticsearch index lifecycle management and Kibana dashboard integration for scalable log management. Configure retention policies and monitoring alerts for production environments.
Prerequisites
- Root or sudo access
- 4GB+ RAM for Elasticsearch
- 20GB+ disk space for logs
What this solves
Large-scale applications generate massive log volumes that can fill disk space and degrade Elasticsearch performance. This tutorial configures logrotate with Elasticsearch index lifecycle management (ILM) and Kibana dashboard integration to automatically rotate, archive, and delete logs based on age and size policies.
Step-by-step configuration
Install required packages
Install logrotate and Elasticsearch tools for log management automation.
sudo apt update
sudo apt install -y logrotate curl jq
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-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 apt install -y elasticsearch kibana
Configure Elasticsearch with security
Set up Elasticsearch with authentication and configure cluster settings for log management.
cluster.name: log-management-cluster
node.name: node-1
network.host: 127.0.0.1
http.port: 9200
discovery.type: single-node
Security settings
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
Index lifecycle management
action.destructive_requires_name: true
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%
cluster.routing.allocation.disk.watermark.flood_stage: 95%
Start Elasticsearch and configure passwords
Enable Elasticsearch service and set up authentication credentials.
sudo systemctl enable --now elasticsearch
sudo systemctl status elasticsearch
Wait for Elasticsearch to start
sleep 30
Set passwords for built-in users
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Configure Kibana integration
Set up Kibana to connect to Elasticsearch with authentication.
server.port: 5601
server.host: "127.0.0.1"
server.name: log-management-kibana
elasticsearch.hosts: ["http://127.0.0.1:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "YOUR_KIBANA_SYSTEM_PASSWORD"
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"]
logging.root.level: info
sudo mkdir -p /var/log/kibana
sudo chown kibana:kibana /var/log/kibana
sudo systemctl enable --now kibana
sudo systemctl status kibana
Create Elasticsearch index lifecycle policy
Configure ILM policy to automatically manage log indices based on age and size.
curl -X PUT "127.0.0.1:9200/_ilm/policy/logs-policy" \
-H "Content-Type: application/json" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "5GB",
"max_age": "7d",
"max_docs": 1000000
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"allocate": {
"number_of_replicas": 0
},
"shrink": {
"number_of_shards": 1
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"number_of_replicas": 0
}
}
},
"delete": {
"min_age": "90d"
}
}
}
}'
Create index template for automated log ingestion
Set up index template to apply ILM policy to all log indices automatically.
curl -X PUT "127.0.0.1:9200/_index_template/logs-template" \
-H "Content-Type: application/json" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"index.lifecycle.name": "logs-policy",
"index.lifecycle.rollover_alias": "logs"
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"level": {
"type": "keyword"
},
"message": {
"type": "text"
},
"service": {
"type": "keyword"
},
"host": {
"type": "keyword"
}
}
}
},
"priority": 200,
"version": 1
}'
Configure logrotate for application logs
Set up logrotate to manage application log files and integrate with Elasticsearch indexing.
/var/log/application/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 www-data www-data
sharedscripts
postrotate
# Send rotated logs to Elasticsearch
/usr/local/bin/send-logs-to-elasticsearch.sh "$1"
# Restart application if needed
systemctl reload nginx 2>/dev/null || true
endscript
}
Create log shipping script
Build script to automatically index rotated logs in Elasticsearch with proper formatting.
#!/bin/bash
Configuration
ELASTIC_HOST="127.0.0.1:9200"
ELASTIC_USER="elastic"
ELASTIC_PASS="YOUR_ELASTIC_PASSWORD"
INDEX_PREFIX="logs"
SERVICE_NAME="application"
HOSTNAME=$(hostname)
Function to send log entry to Elasticsearch
send_log_entry() {
local log_file="$1"
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
local index_name="${INDEX_PREFIX}-$(date +%Y.%m.%d)"
while IFS= read -r line; do
if [[ -n "$line" ]]; then
# Parse log level (INFO, ERROR, WARN, DEBUG)
local level="INFO"
if [[ "$line" =~ \[([A-Z]+)\] ]]; then
level="${BASH_REMATCH[1]}"
fi
# Create JSON document
local doc=$(jq -n \
--arg timestamp "$timestamp" \
--arg level "$level" \
--arg message "$line" \
--arg service "$SERVICE_NAME" \
--arg host "$HOSTNAME" \
'{
"@timestamp": $timestamp,
"level": $level,
"message": $message,
"service": $service,
"host": $host
}')
# Send to Elasticsearch
curl -s -X POST "${ELASTIC_HOST}/${index_name}/_doc" \
-H "Content-Type: application/json" \
-u "${ELASTIC_USER}:${ELASTIC_PASS}" \
-d "$doc" > /dev/null
fi
done < "$log_file"
}
Process log file if provided
if [[ -n "$1" && -f "$1" ]]; then
send_log_entry "$1"
fi
sudo chmod +x /usr/local/bin/send-logs-to-elasticsearch.sh
sudo mkdir -p /var/log/application
sudo chown www-data:www-data /var/log/application
Configure system log rotation
Extend logrotate configuration for system logs with Elasticsearch integration.
/var/log/syslog {
daily
rotate 14
compress
delaycompress
missingok
notifempty
postrotate
# Index system logs in Elasticsearch
/usr/local/bin/index-system-logs.sh
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
/var/log/auth.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
postrotate
/usr/local/bin/index-auth-logs.sh
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
Create system log indexing scripts
Build specialized scripts for different log types with appropriate field mapping.
#!/bin/bash
ELASTIC_HOST="127.0.0.1:9200"
ELASTIC_USER="elastic"
ELASTIC_PASS="YOUR_ELASTIC_PASSWORD"
LOG_FILE="/var/log/syslog.1"
INDEX_NAME="system-logs-$(date +%Y.%m.%d)"
if [[ -f "$LOG_FILE" ]]; then
# Process compressed or uncompressed log files
if [[ "$LOG_FILE" =~ \.gz$ ]]; then
zcat "$LOG_FILE" | while IFS= read -r line; do
process_syslog_entry "$line"
done
else
while IFS= read -r line; do
process_syslog_entry "$line"
done < "$LOG_FILE"
fi
fi
process_syslog_entry() {
local line="$1"
local timestamp=$(echo "$line" | awk '{print $1" "$2" "$3}')
local hostname=$(echo "$line" | awk '{print $4}')
local process=$(echo "$line" | awk '{print $5}' | sed 's/://')
local message=$(echo "$line" | cut -d' ' -f6-)
local doc=$(jq -n \
--arg timestamp "$timestamp" \
--arg hostname "$hostname" \
--arg process "$process" \
--arg message "$message" \
--arg type "system" \
'{
"@timestamp": $timestamp,
"host": $hostname,
"process": $process,
"message": $message,
"log_type": $type
}')
curl -s -X POST "${ELASTIC_HOST}/${INDEX_NAME}/_doc" \
-H "Content-Type: application/json" \
-u "${ELASTIC_USER}:${ELASTIC_PASS}" \
-d "$doc" > /dev/null
}
#!/bin/bash
ELASTIC_HOST="127.0.0.1:9200"
ELASTIC_USER="elastic"
ELASTIC_PASS="YOUR_ELASTIC_PASSWORD"
LOG_FILE="/var/log/auth.log.1"
INDEX_NAME="security-logs-$(date +%Y.%m.%d)"
if [[ -f "$LOG_FILE" ]]; then
while IFS= read -r line; do
# Parse authentication events
local event_type="unknown"
if [[ "$line" =~ "Accepted" ]]; then
event_type="login_success"
elif [[ "$line" =~ "Failed" ]]; then
event_type="login_failure"
elif [[ "$line" =~ "sudo" ]]; then
event_type="sudo_command"
fi
local timestamp=$(echo "$line" | awk '{print $1" "$2" "$3}')
local hostname=$(echo "$line" | awk '{print $4}')
local message=$(echo "$line" | cut -d' ' -f6-)
local doc=$(jq -n \
--arg timestamp "$timestamp" \
--arg hostname "$hostname" \
--arg message "$message" \
--arg event_type "$event_type" \
--arg log_type "security" \
'{
"@timestamp": $timestamp,
"host": $hostname,
"message": $message,
"event_type": $event_type,
"log_type": $log_type
}')
curl -s -X POST "${ELASTIC_HOST}/${INDEX_NAME}/_doc" \
-H "Content-Type: application/json" \
-u "${ELASTIC_USER}:${ELASTIC_PASS}" \
-d "$doc" > /dev/null
done < "$LOG_FILE"
fi
sudo chmod +x /usr/local/bin/index-system-logs.sh
sudo chmod +x /usr/local/bin/index-auth-logs.sh
Configure automated log rotation schedule
Set up cron jobs to ensure regular log rotation and Elasticsearch maintenance.
sudo crontab -e
# Run logrotate hourly for high-volume logs
0 /usr/sbin/logrotate -f /etc/logrotate.d/application-logs
Run system log rotation daily
0 2 * /usr/sbin/logrotate -f /etc/logrotate.d/elasticsearch-system
Clean up old Elasticsearch indices weekly
0 3 0 /usr/local/bin/cleanup-old-indices.sh
Monitor disk space and send alerts
/15 * /usr/local/bin/disk-space-monitor.sh
Create maintenance and monitoring scripts
Build scripts for automatic cleanup and monitoring of the log management system.
#!/bin/bash
ELASTIC_HOST="127.0.0.1:9200"
ELASTIC_USER="elastic"
ELASTIC_PASS="YOUR_ELASTIC_PASSWORD"
RETENTION_DAYS=90
Get indices older than retention period
old_indices=$(curl -s -u "${ELASTIC_USER}:${ELASTIC_PASS}" \
"${ELASTIC_HOST}/_cat/indices?h=index&s=index" | \
grep -E "logs-[0-9]{4}\.[0-9]{2}\.[0-9]{2}" | \
while read index; do
index_date=$(echo "$index" | grep -o '[0-9]\{4\}\.[0-9]\{2\}\.[0-9]\{2\}')
index_timestamp=$(date -d "$index_date" +%s)
cutoff_timestamp=$(date -d "$RETENTION_DAYS days ago" +%s)
if [[ $index_timestamp -lt $cutoff_timestamp ]]; then
echo "$index"
fi
done)
Delete old indices
for index in $old_indices; do
echo "Deleting index: $index"
curl -X DELETE -s -u "${ELASTIC_USER}:${ELASTIC_PASS}" \
"${ELASTIC_HOST}/${index}"
done
Force merge recent indices for better performance
recent_indices=$(curl -s -u "${ELASTIC_USER}:${ELASTIC_PASS}" \
"${ELASTIC_HOST}/_cat/indices?h=index&s=index" | \
grep -E "logs-[0-9]{4}\.[0-9]{2}\.[0-9]{2}" | \
tail -7)
for index in $recent_indices; do
curl -X POST -s -u "${ELASTIC_USER}:${ELASTIC_PASS}" \
"${ELASTIC_HOST}/${index}/_forcemerge?max_num_segments=1"
done
#!/bin/bash
THRESHOLD=85
EMAIL="admin@example.com"
Check disk usage
usage=$(df /var/log | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ $usage -gt $THRESHOLD ]]; then
message="Warning: Log disk usage is at ${usage}% on $(hostname)"
echo "$message" | mail -s "High Disk Usage Alert" "$EMAIL"
# Emergency log cleanup
find /var/log -name ".log.[0-9]" -mtime +7 -delete
find /var/log -name "*.gz" -mtime +14 -delete
fi
Check Elasticsearch cluster health
health=$(curl -s -u "${ELASTIC_USER}:${ELASTIC_PASS}" \
"127.0.0.1:9200/_cluster/health" | jq -r '.status')
if [[ "$health" != "green" ]]; then
echo "Elasticsearch cluster status: $health" | \
mail -s "Elasticsearch Health Alert" "$EMAIL"
fi
sudo chmod +x /usr/local/bin/cleanup-old-indices.sh
sudo chmod +x /usr/local/bin/disk-space-monitor.sh
Create Kibana dashboards
Access Kibana and create dashboards for log analysis and monitoring visualization.
# Access Kibana at http://127.0.0.1:5601
Login with elastic user and password
Create index pattern for logs
curl -X POST "127.0.0.1:5601/api/saved_objects/index-pattern/logs-*" \
-H "Content-Type: application/json" \
-H "kbn-xsrf: true" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"attributes": {
"title": "logs-*",
"timeFieldName": "@timestamp"
}
}'
Create dashboard configuration
curl -X POST "127.0.0.1:5601/api/saved_objects/dashboard/log-management-dashboard" \
-H "Content-Type: application/json" \
-H "kbn-xsrf: true" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"attributes": {
"title": "Log Management Dashboard",
"description": "Automated log rotation and analytics",
"panelsJSON": "[]",
"version": 1
}
}'
Configure monitoring and alerts
Set up Elasticsearch monitoring
Enable monitoring for cluster health and performance metrics.
# Enable monitoring collection
curl -X PUT "127.0.0.1:9200/_cluster/settings" \
-H "Content-Type: application/json" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"persistent": {
"xpack.monitoring.collection.enabled": true
}
}'
Create watcher for disk space alerts
curl -X PUT "127.0.0.1:9200/_watcher/watch/disk_space_alert" \
-H "Content-Type: application/json" \
-u elastic:YOUR_ELASTIC_PASSWORD \
-d '{
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"http": {
"request": {
"host": "127.0.0.1",
"port": 9200,
"path": "/_nodes/stats/fs"
}
}
},
"condition": {
"script": {
"source": "ctx.payload.nodes.values().stream().anyMatch(node -> node.fs.total.available_in_bytes < 1000000000)"
}
},
"actions": {
"send_email": {
"email": {
"to": ["admin@example.com"],
"subject": "Elasticsearch Low Disk Space",
"body": "Disk space is running low on Elasticsearch nodes"
}
}
}
}'
Verify your setup
# Check Elasticsearch cluster health
curl -u elastic:YOUR_ELASTIC_PASSWORD "127.0.0.1:9200/_cluster/health?pretty"
Verify ILM policy is active
curl -u elastic:YOUR_ELASTIC_PASSWORD "127.0.0.1:9200/_ilm/policy/logs-policy?pretty"
Test log rotation
sudo logrotate -d /etc/logrotate.d/application-logs
Check Kibana is accessible
curl -I "127.0.0.1:5601/status"
Verify index template
curl -u elastic:YOUR_ELASTIC_PASSWORD "127.0.0.1:9200/_index_template/logs-template?pretty"
Test log shipping script
echo "Test log entry" > /tmp/test.log
/usr/local/bin/send-logs-to-elasticsearch.sh /tmp/test.log
Check if logs appear in Elasticsearch
curl -u elastic:YOUR_ELASTIC_PASSWORD "127.0.0.1:9200/logs-$(date +%Y.%m.%d)/_search?pretty"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Elasticsearch won't start | Memory configuration too high | Reduce heap size in /etc/elasticsearch/jvm.options |
| Kibana connection refused | Wrong Elasticsearch credentials | Verify username/password in /etc/kibana/kibana.yml |
| Logrotate script fails | Missing execute permissions | sudo chmod +x /usr/local/bin/send-logs-to-elasticsearch.sh |
| Indices not rotating | ILM policy not applied | Check index template and policy assignment |
| Disk space alerts not working | Watcher not enabled | Enable watcher in Elasticsearch license settings |
| Log parsing errors | Invalid JSON in log entries | Add input validation to shipping scripts |
Next steps
- Configure ELK stack for centralized logging with Elasticsearch 8, Logstash 8, and Kibana 8
- Configure centralized logging with rsyslog and logrotate for system monitoring and log management
- Implement Grafana alerting with Prometheus and InfluxDB for comprehensive monitoring
- Configure Elasticsearch backup automation with snapshot lifecycle management
- Set up Kibana advanced security with LDAP authentication and RBAC
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Production Elasticsearch and Kibana Logrotate Setup Script
# Configures automated log management with Elasticsearch ILM
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Error cleanup function
cleanup() {
echo -e "${RED}Error occurred. Cleaning up...${NC}"
systemctl stop elasticsearch kibana 2>/dev/null || true
}
trap cleanup ERR
# Usage message
usage() {
echo "Usage: $0 [elastic_password] [kibana_password]"
echo " elastic_password: Password for elastic user (optional, will generate if not provided)"
echo " kibana_password: Password for kibana_system user (optional, will generate if not provided)"
exit 1
}
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
DISTRO_TYPE="debian"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
DISTRO_TYPE="rhel"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
DISTRO_TYPE="rhel"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
# Set passwords or use provided ones
ELASTIC_PASSWORD=${1:-"$(openssl rand -base64 32)"}
KIBANA_PASSWORD=${2:-"$(openssl rand -base64 32)"}
echo -e "${GREEN}Starting Elasticsearch and Kibana logrotate setup...${NC}"
# Step 1: Update system and install base packages
echo -e "${YELLOW}[1/8] Installing base packages...${NC}"
$PKG_UPDATE
$PKG_INSTALL logrotate curl jq
# Step 2: Add Elasticsearch repository and install
echo -e "${YELLOW}[2/8] Adding Elasticsearch repository...${NC}"
if [[ "$DISTRO_TYPE" == "debian" ]]; then
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list
$PKG_UPDATE
$PKG_INSTALL elasticsearch kibana
else
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.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
$PKG_INSTALL elasticsearch kibana
fi
# Step 3: Configure Elasticsearch
echo -e "${YELLOW}[3/8] Configuring Elasticsearch...${NC}"
cat > /etc/elasticsearch/elasticsearch.yml << EOF
cluster.name: log-management-cluster
node.name: node-1
network.host: 127.0.0.1
http.port: 9200
discovery.type: single-node
# Security settings
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
# Index lifecycle management
action.destructive_requires_name: true
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%
cluster.routing.allocation.disk.watermark.flood_stage: 95%
EOF
chown root:elasticsearch /etc/elasticsearch/elasticsearch.yml
chmod 660 /etc/elasticsearch/elasticsearch.yml
# Step 4: Start Elasticsearch and configure users
echo -e "${YELLOW}[4/8] Starting Elasticsearch and configuring users...${NC}"
systemctl daemon-reload
systemctl enable elasticsearch
systemctl start elasticsearch
# Wait for Elasticsearch to start
echo "Waiting for Elasticsearch to start..."
for i in {1..30}; do
if curl -s http://127.0.0.1:9200 >/dev/null 2>&1; then
break
fi
sleep 2
done
# Set up built-in user passwords
echo "Setting up user passwords..."
/usr/share/elasticsearch/bin/elasticsearch-users useradd elastic -p "$ELASTIC_PASSWORD" -r superuser
/usr/share/elasticsearch/bin/elasticsearch-users useradd kibana_system -p "$KIBANA_PASSWORD" -r kibana_system
# Step 5: Configure Kibana
echo -e "${YELLOW}[5/8] Configuring Kibana...${NC}"
mkdir -p /var/log/kibana
chown kibana:kibana /var/log/kibana
chmod 755 /var/log/kibana
cat > /etc/kibana/kibana.yml << EOF
server.port: 5601
server.host: "127.0.0.1"
server.name: log-management-kibana
elasticsearch.hosts: ["http://127.0.0.1:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "$KIBANA_PASSWORD"
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"]
logging.root.level: info
EOF
chown root:kibana /etc/kibana/kibana.yml
chmod 660 /etc/kibana/kibana.yml
systemctl enable kibana
systemctl start kibana
# Step 6: Create Elasticsearch ILM policy
echo -e "${YELLOW}[6/8] Creating Elasticsearch ILM policy...${NC}"
sleep 10 # Wait for services to fully start
curl -X PUT "127.0.0.1:9200/_ilm/policy/logs-policy" \
-H "Content-Type: application/json" \
-u elastic:$ELASTIC_PASSWORD \
-d '{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "5GB",
"max_age": "7d",
"max_docs": 1000000
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"allocate": {
"number_of_replicas": 0
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"number_of_replicas": 0
}
}
},
"delete": {
"min_age": "90d"
}
}
}
}'
# Step 7: Configure logrotate
echo -e "${YELLOW}[7/8] Configuring logrotate...${NC}"
cat > /etc/logrotate.d/elasticsearch << EOF
/var/log/elasticsearch/*.log {
daily
missingok
rotate 30
compress
delaycompress
copytruncate
notifempty
create 644 elasticsearch elasticsearch
}
EOF
cat > /etc/logrotate.d/kibana << EOF
/var/log/kibana/*.log {
daily
missingok
rotate 30
compress
delaycompress
copytruncate
notifempty
create 644 kibana kibana
}
EOF
# Step 8: Verify installation
echo -e "${YELLOW}[8/8] Verifying installation...${NC}"
sleep 5
# Check Elasticsearch
if curl -s -u elastic:$ELASTIC_PASSWORD http://127.0.0.1:9200/_cluster/health | jq -r .status | grep -E "(green|yellow)" > /dev/null; then
echo -e "${GREEN}✓ Elasticsearch is running and healthy${NC}"
else
echo -e "${RED}✗ Elasticsearch health check failed${NC}"
exit 1
fi
# Check Kibana
if curl -s http://127.0.0.1:5601/api/status | jq -r .status.overall.state | grep "green" > /dev/null; then
echo -e "${GREEN}✓ Kibana is running${NC}"
else
echo -e "${YELLOW}⚠ Kibana may still be starting up${NC}"
fi
# Check ILM policy
if curl -s -u elastic:$ELASTIC_PASSWORD http://127.0.0.1:9200/_ilm/policy/logs-policy | jq -r '.logs-policy.policy.phases.hot' > /dev/null; then
echo -e "${GREEN}✓ ILM policy created successfully${NC}"
else
echo -e "${RED}✗ ILM policy creation failed${NC}"
fi
echo -e "${GREEN}Installation completed successfully!${NC}"
echo -e "${YELLOW}Important: Save these credentials:${NC}"
echo "Elasticsearch URL: http://127.0.0.1:9200"
echo "Kibana URL: http://127.0.0.1:5601"
echo "Elastic user password: $ELASTIC_PASSWORD"
echo "Kibana system password: $KIBANA_PASSWORD"
Review the script before running. Execute with: bash install.sh