Set up a centralized logging system using rsyslog server to collect logs from multiple clients, implement TLS encryption for secure transmission, and configure logrotate for automated log rotation and management.
Prerequisites
- Root or sudo access
- Multiple Linux servers for testing
- Basic understanding of system logs
- Email server for monitoring alerts
What this solves
Centralized logging consolidates system and application logs from multiple servers into a single location for easier monitoring, troubleshooting, and compliance. This tutorial shows you how to configure a rsyslog server to receive logs from client machines, secure the transmission with TLS encryption, and manage log rotation with logrotate to prevent disk space issues.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you get the latest versions of rsyslog and related tools.
sudo apt update && sudo apt upgrade -y
Install rsyslog and TLS support
Install rsyslog with TLS modules for secure log transmission and additional utilities for certificate management.
sudo apt install -y rsyslog rsyslog-gnutls gnutls-bin logrotate
Create certificate authority for TLS
Generate a certificate authority and server certificates for encrypted log transmission. This ensures logs cannot be intercepted or tampered with during transmission.
sudo mkdir -p /etc/rsyslog-certs
cd /etc/rsyslog-certs
sudo openssl genrsa -out ca-key.pem 4096
sudo openssl req -new -x509 -key ca-key.pem -out ca.pem -days 365 \
-subj "/C=US/ST=State/L=City/O=Organization/CN=rsyslog-ca"
Generate server certificates
Create server certificates signed by your CA for the rsyslog server. Replace example.com with your actual server hostname or IP address.
sudo openssl genrsa -out server-key.pem 4096
sudo openssl req -new -key server-key.pem -out server.csr \
-subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"
sudo openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -days 365
Set certificate permissions
Configure proper ownership and permissions for the certificates. The syslog user needs read access to certificates but private keys should be restricted.
sudo chown -R syslog:syslog /etc/rsyslog-certs
sudo chmod 755 /etc/rsyslog-certs
sudo chmod 644 /etc/rsyslog-certs/.pem /etc/rsyslog-certs/.csr
sudo chmod 600 /etc/rsyslog-certs/*-key.pem
Configure rsyslog server
Configure the rsyslog server to accept incoming logs over TCP with TLS encryption. This creates a secure centralized logging hub.
# Enable modules for TLS and TCP reception
$ModLoad imtcp
$DefaultNetstreamDriver gtls
$DefaultNetstreamDriverCAFile /etc/rsyslog-certs/ca.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog-certs/server-cert.pem
$DefaultNetstreamDriverKeyFile /etc/rsyslog-certs/server-key.pem
TLS settings
$InputTCPServerStreamDriverAuthMode x509/name
$InputTCPServerStreamDriverPermittedPeer *.example.com
$InputTCPServerStreamDriverMode 1
$InputTCPServerRun 6514
Template for remote logs with hostname
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
. ?RemoteLogs
& stop
Local system logs
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* /var/log/maillog
cron.* /var/log/cron
.emerg :omusrmsg:
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
Create remote log directory
Create the directory structure where remote logs will be stored, organized by hostname for easy identification.
sudo mkdir -p /var/log/remote
sudo chown syslog:syslog /var/log/remote
sudo chmod 755 /var/log/remote
Configure firewall for log server
Open port 6514 for secure rsyslog communication. This port is used for TLS-encrypted syslog transmission.
sudo ufw allow 6514/tcp
sudo ufw reload
Generate client certificates
Create certificates for each client that will send logs to the server. Run this on the server for each client machine.
cd /etc/rsyslog-certs
sudo openssl genrsa -out client-key.pem 4096
sudo openssl req -new -key client-key.pem -out client.csr \
-subj "/C=US/ST=State/L=City/O=Organization/CN=client.example.com"
sudo openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out client-cert.pem -days 365
Configure rsyslog clients
On each client machine, configure rsyslog to forward logs to the central server. Copy the client certificates and CA to each client machine first.
sudo mkdir -p /etc/rsyslog-certs
sudo scp server:/etc/rsyslog-certs/ca.pem /etc/rsyslog-certs/
sudo scp server:/etc/rsyslog-certs/client-cert.pem /etc/rsyslog-certs/
sudo scp server:/etc/rsyslog-certs/client-key.pem /etc/rsyslog-certs/
# TLS configuration for client
$DefaultNetstreamDriver gtls
$DefaultNetstreamDriverCAFile /etc/rsyslog-certs/ca.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog-certs/client-cert.pem
$DefaultNetstreamDriverKeyFile /etc/rsyslog-certs/client-key.pem
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer example.com
$ActionSendStreamDriverMode 1
Forward all logs to central server
. @@example.com:6514
Also keep local copies
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* /var/log/maillog
cron.* /var/log/cron
Configure log filtering rules
Add custom filtering rules to separate different types of logs into specific files for easier analysis.
# Separate SSH logs
if $programname == 'sshd' then /var/log/remote/%HOSTNAME%/ssh.log
& stop
Separate web server logs
if $programname == 'nginx' or $programname == 'apache2' then /var/log/remote/%HOSTNAME%/web.log
& stop
Separate database logs
if $programname startswith 'mysql' or $programname startswith 'postgres' then /var/log/remote/%HOSTNAME%/database.log
& stop
Filter by severity - errors only
if $syslogseverity <= 3 then /var/log/remote/%HOSTNAME%/errors.log
Filter by facility - mail logs
if $syslogfacility-text == 'mail' then /var/log/remote/%HOSTNAME%/mail.log
& stop
Configure logrotate for remote logs
Set up automatic log rotation to prevent remote logs from filling up disk space. This configuration rotates logs weekly and compresses old files.
/var/log/remote//.log {
weekly
missingok
rotate 8
compress
delaycompress
notifempty
create 640 syslog syslog
postrotate
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
/var/log/remote/*/errors.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 syslog syslog
postrotate
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
Configure standard log rotation
Update the standard rsyslog logrotate configuration to handle increased log volume from centralized logging.
/var/log/syslog {
daily
missingok
rotate 15
compress
delaycompress
notifempty
create 640 syslog adm
postrotate
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages {
weekly
missingok
rotate 8
compress
delaycompress
notifempty
create 640 syslog adm
postrotate
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
Set up log monitoring script
Create a monitoring script that checks for log anomalies and sends alerts when error rates exceed thresholds.
#!/bin/bash
Configuration
LOG_DIR="/var/log/remote"
ERROR_THRESHOLD=10
EMAIL_ALERT="admin@example.com"
TMP_FILE="/tmp/log-errors.tmp"
Check for errors in the last hour
find $LOG_DIR -name "errors.log" -type f | while read logfile; do
hostname=$(echo $logfile | cut -d'/' -f5)
error_count=$(grep "$(date -d '1 hour ago' '+%b %d %H')" $logfile 2>/dev/null | wc -l)
if [ $error_count -gt $ERROR_THRESHOLD ]; then
echo "High error rate on $hostname: $error_count errors in last hour" >> $TMP_FILE
fi
done
Send alert if errors found
if [ -s $TMP_FILE ]; then
mail -s "Log Alert: High Error Rates Detected" $EMAIL_ALERT < $TMP_FILE
rm -f $TMP_FILE
fi
Check disk usage
DISK_USAGE=$(df /var/log | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
echo "Warning: Log disk usage at ${DISK_USAGE}%" | mail -s "Log Alert: High Disk Usage" $EMAIL_ALERT
fi
sudo chmod +x /usr/local/bin/log-monitor.sh
Create monitoring cron job
Schedule the monitoring script to run every hour and check for issues automatically.
sudo crontab -e
# Run log monitoring every hour
0 /usr/local/bin/log-monitor.sh
Test logrotate daily
0 2 * /usr/sbin/logrotate -f /etc/logrotate.d/rsyslog-remote
Start and enable services
Enable rsyslog to start automatically and restart it to load the new configuration.
sudo systemctl enable rsyslog
sudo systemctl restart rsyslog
sudo systemctl status rsyslog
Verify your setup
Test that the centralized logging system is working correctly by generating test logs and checking they arrive at the server.
# Check rsyslog is listening on port 6514
sudo netstat -tlnp | grep 6514
Generate test log from client
logger -p local0.info "Test message from $(hostname)"
Check log arrived on server
sudo tail -f /var/log/remote/*/messages.log
Test log rotation
sudo logrotate -d /etc/logrotate.d/rsyslog-remote
Verify TLS connection
sudo rsyslog -N1 -f /etc/rsyslog.conf
Check certificate validity
openssl x509 -in /etc/rsyslog-certs/server-cert.pem -text -noout
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Logs not arriving at server | Firewall blocking port 6514 | Check firewall rules: sudo ufw status or sudo firewall-cmd --list-ports |
| TLS handshake failed | Certificate name mismatch | Ensure certificate CN matches server hostname in client config |
| Permission denied writing logs | Incorrect directory permissions | sudo chown -R syslog:syslog /var/log/remote |
| Logrotate not working | Invalid configuration syntax | Test with sudo logrotate -d /etc/logrotate.d/rsyslog-remote |
| High CPU usage | Too many regex rules | Optimize filtering rules, use property-based filters instead of regex |
| Client logs duplicated | Both local and remote logging enabled | Add & stop after remote forwarding rules |
Next steps
- Configure Loki and Promtail for centralized Docker log aggregation for containerized environments
- Setup centralized log aggregation with ELK Stack for advanced log analysis
- Integrate rsyslog with Elasticsearch for scalable log storage
- Set up log-based alerting with Prometheus Alertmanager
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
DOMAIN=${1:-"example.com"}
ORG=${2:-"MyOrganization"}
# Usage message
usage() {
echo "Usage: $0 [domain] [organization]"
echo " domain: Server domain/hostname (default: example.com)"
echo " organization: Certificate organization (default: MyOrganization)"
exit 1
}
# Error handling and cleanup
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop rsyslog 2>/dev/null || true
rm -rf /etc/rsyslog-certs 2>/dev/null || true
}
trap cleanup ERR
# Check prerequisites
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
if [[ $# -gt 2 ]]; then
usage
fi
# Detect distribution
if [ ! -f /etc/os-release ]; then
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
. /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_CONF="/etc/rsyslog.conf"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
FIREWALL_CMD="firewall-cmd"
RSYSLOG_CONF="/etc/rsyslog.conf"
;;
fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
FIREWALL_CMD="firewall-cmd"
RSYSLOG_CONF="/etc/rsyslog.conf"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
FIREWALL_CMD="firewall-cmd"
RSYSLOG_CONF="/etc/rsyslog.conf"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Configuring centralized logging with rsyslog for $ID${NC}"
echo -e "${YELLOW}Domain: $DOMAIN${NC}"
echo -e "${YELLOW}Organization: $ORG${NC}"
# Step 1: Update system packages
echo -e "${GREEN}[1/9] Updating system packages...${NC}"
$PKG_UPDATE
# Step 2: Install rsyslog and dependencies
echo -e "${GREEN}[2/9] Installing rsyslog and TLS support...${NC}"
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
$PKG_INSTALL rsyslog rsyslog-gnutls gnutls-bin logrotate openssl
else
$PKG_INSTALL rsyslog rsyslog-gnutls gnutls-utils logrotate openssl
fi
# Step 3: Create certificate directory and CA
echo -e "${GREEN}[3/9] Creating certificate authority...${NC}"
mkdir -p /etc/rsyslog-certs
cd /etc/rsyslog-certs
# Generate CA private key
openssl genrsa -out ca-key.pem 4096
# Generate CA certificate
openssl req -new -x509 -key ca-key.pem -out ca.pem -days 365 \
-subj "/C=US/ST=State/L=City/O=$ORG/CN=rsyslog-ca"
# Step 4: Generate server certificates
echo -e "${GREEN}[4/9] Generating server certificates...${NC}"
# Generate server private key
openssl genrsa -out server-key.pem 4096
# Generate server certificate signing request
openssl req -new -key server-key.pem -out server.csr \
-subj "/C=US/ST=State/L=City/O=$ORG/CN=$DOMAIN"
# Sign server certificate with CA
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -days 365
# Step 5: Set certificate permissions
echo -e "${GREEN}[5/9] Setting certificate permissions...${NC}"
chown -R syslog:syslog /etc/rsyslog-certs
chmod 755 /etc/rsyslog-certs
chmod 644 /etc/rsyslog-certs/*.pem /etc/rsyslog-certs/*.csr
chmod 600 /etc/rsyslog-certs/*-key.pem
# Step 6: Configure rsyslog server
echo -e "${GREEN}[6/9] Configuring rsyslog server...${NC}"
cat > "$RSYSLOG_CONF" << EOF
# Enable modules for TLS and TCP reception
\$ModLoad imtcp
\$DefaultNetstreamDriver gtls
\$DefaultNetstreamDriverCAFile /etc/rsyslog-certs/ca.pem
\$DefaultNetstreamDriverCertFile /etc/rsyslog-certs/server-cert.pem
\$DefaultNetstreamDriverKeyFile /etc/rsyslog-certs/server-key.pem
# TLS settings
\$InputTCPServerStreamDriverAuthMode x509/name
\$InputTCPServerStreamDriverPermittedPeer *.$DOMAIN
\$InputTCPServerStreamDriverMode 1
\$InputTCPServerRun 6514
# Template for remote logs with hostname
\$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteLogs
& stop
# Local system logs
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* /var/log/maillog
cron.* /var/log/cron
*.emerg :omusrmsg:*
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
EOF
# Step 7: Create remote log directory
echo -e "${GREEN}[7/9] Creating remote log directory...${NC}"
mkdir -p /var/log/remote
chown syslog:syslog /var/log/remote
chmod 755 /var/log/remote
# Step 8: Configure firewall
echo -e "${GREEN}[8/9] Configuring firewall...${NC}"
if [[ "$FIREWALL_CMD" == "ufw" ]]; then
ufw allow 6514/tcp || echo -e "${YELLOW}UFW not active or available${NC}"
else
if command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-port=6514/tcp || echo -e "${YELLOW}Firewalld not active${NC}"
firewall-cmd --reload || true
fi
fi
# Configure logrotate
echo -e "${GREEN}[9/9] Configuring log rotation...${NC}"
cat > /etc/logrotate.d/rsyslog-remote << EOF
/var/log/remote/*/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 640 syslog syslog
postrotate
systemctl reload rsyslog
endscript
}
EOF
# Start and enable rsyslog
systemctl enable rsyslog
systemctl restart rsyslog
# Verification
echo -e "${GREEN}Verifying installation...${NC}"
if systemctl is-active --quiet rsyslog; then
echo -e "${GREEN}✓ rsyslog service is running${NC}"
else
echo -e "${RED}✗ rsyslog service is not running${NC}"
exit 1
fi
if netstat -tlnp 2>/dev/null | grep -q ":6514 "; then
echo -e "${GREEN}✓ rsyslog listening on port 6514${NC}"
else
echo -e "${YELLOW}! rsyslog may not be listening on port 6514${NC}"
fi
if [[ -d /var/log/remote ]]; then
echo -e "${GREEN}✓ Remote log directory created${NC}"
else
echo -e "${RED}✗ Remote log directory not found${NC}"
fi
echo -e "${GREEN}Centralized logging setup complete!${NC}"
echo -e "${YELLOW}Next steps:${NC}"
echo -e "1. Distribute /etc/rsyslog-certs/ca.pem to client machines"
echo -e "2. Configure client machines to send logs to this server"
echo -e "3. Monitor logs in /var/log/remote/"
Review the script before running. Execute with: bash install.sh