Configure rsyslog for centralized log collection across servers, implement advanced logrotate policies for automated retention, and set up remote log shipping with filtering for comprehensive system monitoring and audit compliance.
Prerequisites
- Root or sudo access
- Multiple Linux servers
- Basic networking knowledge
- Understanding of syslog facilities
What this solves
Centralized logging is essential for monitoring distributed systems, troubleshooting issues across servers, and maintaining audit compliance. This tutorial configures rsyslog for collecting logs from multiple sources, implements logrotate policies for automated retention management, and sets up remote log shipping with filtering to create a robust centralized monitoring system.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you have the latest versions of rsyslog and logrotate.
sudo apt update && sudo apt upgrade -yInstall rsyslog and logrotate
Install the required packages for centralized logging and log rotation management.
sudo apt install -y rsyslog logrotateConfigure rsyslog server for centralized logging
Configure the rsyslog server to receive logs from remote clients. This creates a centralized collection point for all your servers.
# Enable UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
$UDPServerAddress 0.0.0.0
Enable TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
Create log directories based on hostname
$template DynFile,"/var/log/centralized/%HOSTNAME%/%PROGRAMNAME%.log"
$template LogFormat,"%TIMESTAMP% %HOSTNAME% %syslogtag% %msg%\n"
Store remote logs in separate files by hostname
. ?DynFile;LogFormat
Stop processing after writing to dynamic file
& stopCreate log directory structure
Create the directory structure for centralized logs and set proper ownership for the syslog user.
sudo mkdir -p /var/log/centralized
sudo chown syslog:adm /var/log/centralized
sudo chmod 750 /var/log/centralizedConfigure client log forwarding
Set up client servers to forward their logs to the central rsyslog server. Add this configuration to each client server.
# Forward all logs to central server
. @@203.0.113.10:514
Forward specific facilities with different priorities
auth,authpriv.* @@203.0.113.10:514
mail.* @@203.0.113.10:514
cron.* @@203.0.113.10:514
Local logging with filtering
local0.info /var/log/application.log
local1.warn /var/log/security.log
Stop processing forwarded messages locally
& stopConfigure advanced log filtering
Implement filtering rules to process different log types and reduce noise in your centralized system.
# Filter by program name
:programname, isequal, "sshd" /var/log/centralized/ssh.log
:programname, isequal, "nginx" /var/log/centralized/nginx.log
:programname, isequal, "mysql" /var/log/centralized/mysql.log
Filter by facility and severity
kern.crit /var/log/centralized/kernel-critical.log
auth.info /var/log/centralized/auth.log
mail.* /var/log/centralized/mail.log
Filter messages containing specific strings
:msg, contains, "Failed password" /var/log/centralized/failed-logins.log
:msg, contains, "connection refused" /var/log/centralized/connection-errors.log
:msg, contains, "Out of memory" /var/log/centralized/memory-issues.log
Discard debug messages to reduce log volume
kern.debug ~
*.debug ~Configure firewall for log reception
Open the required ports for rsyslog communication between servers.
sudo ufw allow 514/udp comment 'rsyslog UDP'
sudo ufw allow 514/tcp comment 'rsyslog TCP'
sudo ufw reloadConfigure logrotate for centralized logs
Set up comprehensive logrotate policies to manage disk space and retention for your centralized logging system.
/var/log/centralized//.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 syslog adm
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
/var/log/centralized/ssh.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
create 644 syslog adm
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
/var/log/centralized/auth.log {
weekly
rotate 52
compress
delaycompress
missingok
notifempty
create 640 syslog adm
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}Configure application-specific logrotate policies
Create specialized rotation policies for high-volume applications with different retention requirements.
/var/log/application.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 app-user app-group
copytruncate
postrotate
systemctl reload application-service || true
endscript
}
/var/log/security.log {
daily
rotate 365
compress
delaycompress
missingok
notifempty
create 600 root root
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
systemctl reload rsyslog || true
endscript
}Set up log monitoring and alerting
Create monitoring scripts to watch for critical log events and send alerts when thresholds are exceeded.
#!/bin/bash
Log monitoring script for centralized logging
LOG_DIR="/var/log/centralized"
ALERT_EMAIL="admin@example.com"
TMP_DIR="/tmp/log-monitor"
mkdir -p "$TMP_DIR"
Check for failed login attempts
fail_count=$(grep -c "Failed password" "$LOG_DIR/failed-logins.log" 2>/dev/null || echo 0)
if [ "$fail_count" -gt 50 ]; then
echo "High number of failed login attempts: $fail_count" | \
mail -s "Security Alert: Failed Logins" "$ALERT_EMAIL"
fi
Check for disk space issues
df -h "$LOG_DIR" | awk 'NR==2 {if(int($5) > 85) print "Log partition usage: " $5}' | \
while read alert; do
echo "$alert" | mail -s "Disk Space Alert" "$ALERT_EMAIL"
done
Check for service errors
grep -i "error\|critical\|emergency" "$LOG_DIR"//.log | \
head -20 > "$TMP_DIR/recent-errors.log"
if [ -s "$TMP_DIR/recent-errors.log" ]; then
mail -s "System Errors Detected" "$ALERT_EMAIL" < "$TMP_DIR/recent-errors.log"
fisudo chmod +x /usr/local/bin/log-monitor.shCreate systemd timer for log monitoring
Set up automated monitoring that runs every 15 minutes to check for critical events in your centralized logs.
[Unit]
Description=Log Monitoring Service
After=rsyslog.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/log-monitor.sh
StandardOutput=journal
StandardError=journal[Unit]
Description=Run Log Monitor every 15 minutes
Requires=log-monitor.service
[Timer]
OnCalendar=*:0/15
Persistent=true
[Install]
WantedBy=timers.targetEnable and start services
Enable rsyslog and the monitoring timer to start automatically on boot and begin collecting logs immediately.
sudo systemctl enable --now rsyslog
sudo systemctl enable --now log-monitor.timer
sudo systemctl daemon-reload
sudo systemctl restart rsyslogTest logrotate configuration
Verify that your logrotate policies work correctly before putting them into production use.
sudo logrotate -d /etc/logrotate.d/centralized-logs
sudo logrotate -d /etc/logrotate.d/application-logs
sudo logrotate -f /etc/logrotate.d/centralized-logsVerify your setup
Test your centralized logging configuration to ensure logs are being collected, filtered, and rotated properly.
# Check rsyslog status
sudo systemctl status rsyslog
Verify log reception
echo "Test log message" | logger -p local0.info
tail -f /var/log/centralized/*/application.log
Test remote logging from client
ssh client-server "echo 'Remote test message' | logger -p auth.info"
Check log rotation
sudo logrotate -v /etc/logrotate.d/centralized-logs
Monitor log monitoring timer
sudo systemctl status log-monitor.timer
journalctl -u log-monitor.service -fCommon issues
| Symptom | Cause | Fix |
|---|---|---|
| Logs not arriving from clients | Firewall blocking port 514 | Open UDP/TCP 514 on server firewall |
| Permission denied creating log files | Incorrect directory ownership | sudo chown syslog:adm /var/log/centralized |
| Logrotate not working | Invalid configuration syntax | sudo logrotate -d /etc/logrotate.conf to check |
| Disk space filling up quickly | No log rotation or compression | Enable compress and adjust rotate count |
| Lost log messages | UDP packet loss | Switch to TCP: . @@server:514 |
| Monitoring alerts not working | Missing mail configuration | Install and configure postfix or sendmail |
Next steps
- Configure ELK stack for centralized logging with Elasticsearch 8, Logstash 8, and Kibana 8
- Implement log-based monitoring and alerting with Grafana and Loki
- Setup rsyslog TLS encryption for secure remote logging
- Configure advanced log analysis with awk, sed and grep
- Implement log retention policies for compliance and audit requirements
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default values
CENTRAL_SERVER_IP=""
MODE="server"
# Usage function
usage() {
echo "Usage: $0 [server|client] [central_server_ip]"
echo " server: Configure as centralized log server"
echo " client: Configure as log forwarding client"
echo " central_server_ip: IP address of central server (required for client mode)"
exit 1
}
# Logging functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Cleanup function
cleanup() {
log_error "Installation failed. Cleaning up..."
systemctl stop rsyslog 2>/dev/null || true
exit 1
}
trap cleanup ERR
# Parse arguments
if [ $# -eq 0 ]; then
usage
fi
MODE="$1"
if [ "$MODE" = "client" ] && [ $# -lt 2 ]; then
log_error "Central server IP required for client mode"
usage
fi
if [ "$MODE" = "client" ]; then
CENTRAL_SERVER_IP="$2"
fi
if [ "$MODE" != "server" ] && [ "$MODE" != "client" ]; then
log_error "Invalid mode: $MODE"
usage
fi
# Check if running as root
if [ "$EUID" -ne 0 ]; then
log_error "Please run as root or with sudo"
exit 1
fi
echo "[1/8] Detecting distribution and package manager..."
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
FIREWALL_CMD="ufw"
RSYSLOG_USER="syslog"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
FIREWALL_CMD="firewall-cmd"
RSYSLOG_USER="syslog"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
FIREWALL_CMD="firewall-cmd"
RSYSLOG_USER="syslog"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution"
exit 1
fi
log_info "Detected: $PRETTY_NAME using $PKG_MGR"
echo "[2/8] Updating system packages..."
$PKG_UPDATE
echo "[3/8] Installing rsyslog and logrotate..."
$PKG_INSTALL rsyslog logrotate
echo "[4/8] Configuring rsyslog..."
if [ "$MODE" = "server" ]; then
# Configure rsyslog server
cat > /etc/rsyslog.d/10-centralized-server.conf << 'EOF'
# Enable UDP syslog reception
module(load="imudp")
input(type="imudp" port="514" address="0.0.0.0")
# Enable TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514" address="0.0.0.0")
# Create log directories based on hostname
$template DynFile,"/var/log/centralized/%HOSTNAME%/%PROGRAMNAME%.log"
$template LogFormat,"%TIMESTAMP% %HOSTNAME% %syslogtag% %msg%\n"
# Store remote logs in separate files by hostname
*.* ?DynFile;LogFormat
# Filter by program name
:programname, isequal, "sshd" /var/log/centralized/ssh.log
:programname, isequal, "nginx" /var/log/centralized/nginx.log
:programname, isequal, "mysql" /var/log/centralized/mysql.log
# Filter by facility and severity
kern.crit /var/log/centralized/kernel-critical.log
auth.info /var/log/centralized/auth.log
mail.* /var/log/centralized/mail.log
# Filter messages containing specific strings
:msg, contains, "Failed password" /var/log/centralized/failed-logins.log
:msg, contains, "connection refused" /var/log/centralized/connection-errors.log
:msg, contains, "Out of memory" /var/log/centralized/memory-issues.log
# Discard debug messages to reduce log volume
kern.debug stop
*.debug stop
# Stop processing after writing to dynamic file
& stop
EOF
# Create log directory structure
mkdir -p /var/log/centralized
chown $RSYSLOG_USER:adm /var/log/centralized
chmod 755 /var/log/centralized
else
# Configure rsyslog client
cat > /etc/rsyslog.d/10-centralized-client.conf << EOF
# Forward all logs to central server
*.* @@${CENTRAL_SERVER_IP}:514
# Forward specific facilities with different priorities
auth,authpriv.* @@${CENTRAL_SERVER_IP}:514
mail.* @@${CENTRAL_SERVER_IP}:514
cron.* @@${CENTRAL_SERVER_IP}:514
# Local logging with filtering
local0.info /var/log/application.log
local1.warn /var/log/security.log
# Stop processing forwarded messages locally
& stop
EOF
fi
echo "[5/8] Configuring firewall..."
if [ "$MODE" = "server" ]; then
case "$FIREWALL_CMD" in
"ufw")
ufw --force enable
ufw allow 514/udp comment 'rsyslog UDP'
ufw allow 514/tcp comment 'rsyslog TCP'
ufw reload
;;
"firewall-cmd")
systemctl enable firewalld
systemctl start firewalld
firewall-cmd --permanent --add-port=514/udp --add-port=514/tcp
firewall-cmd --reload
;;
esac
fi
echo "[6/8] Configuring logrotate..."
if [ "$MODE" = "server" ]; then
cat > /etc/logrotate.d/centralized-logs << 'EOF'
/var/log/centralized/*/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 syslog adm
postrotate
systemctl reload rsyslog
endscript
}
/var/log/centralized/ssh.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
create 644 syslog adm
postrotate
systemctl reload rsyslog
endscript
}
/var/log/centralized/failed-logins.log {
daily
rotate 180
compress
delaycompress
missingok
notifempty
create 644 syslog adm
postrotate
systemctl reload rsyslog
endscript
}
EOF
fi
echo "[7/8] Starting and enabling services..."
systemctl enable rsyslog
systemctl restart rsyslog
systemctl enable logrotate.timer
systemctl start logrotate.timer
echo "[8/8] Verifying installation..."
# Check if rsyslog is running
if systemctl is-active --quiet rsyslog; then
log_info "rsyslog service is running"
else
log_error "rsyslog service failed to start"
exit 1
fi
# Check configuration syntax
if rsyslogd -N1 &>/dev/null; then
log_info "rsyslog configuration syntax is valid"
else
log_error "rsyslog configuration has syntax errors"
exit 1
fi
# Test log generation
logger "Test log entry from rsyslog setup script"
if [ "$MODE" = "server" ]; then
# Check if listening on ports
if ss -tulpn | grep -q ':514'; then
log_info "rsyslog is listening on port 514"
else
log_warn "rsyslog may not be listening on port 514"
fi
log_info "Server configuration complete!"
log_info "Centralized logs will be stored in /var/log/centralized/"
log_info "Configure clients to forward logs to this server's IP address"
else
log_info "Client configuration complete!"
log_info "Logs are being forwarded to $CENTRAL_SERVER_IP"
fi
log_info "Installation completed successfully!"
Review the script before running. Execute with: bash install.sh