Rsyslog Basics

Page 11 — Local log handling and remote forwarding.

What Rsyslog is

Rsyslog handles logging. It can:

Logs are often the first place you look when something breaks. Rsyslog is what collects and routes them.

Main config locations

/etc/rsyslog.conf
/etc/rsyslog.d/

The main config is in rsyslog.conf. Drop-in files go in rsyslog.d/ — useful for keeping custom forwarding rules separate.

Facilities and severities

Every log message has a facility (the source/category) and a severity (how serious it is).

Common facilities

authpriv · mail · daemon · kern · local0local7

Severity levels (high to low)

emerg · alert · crit · err · warning · notice · info · debug

Forwarding example

# Forward everything via TCP
*.* @@logserver.example.com:514

# Forward everything via UDP
*.* @logserver.example.com:514

@@ (double at) = TCP. @ (single at) = UDP. TCP is more reliable. Port 514 is the standard syslog port.

The *.* selector means all facilities and all severities. You can be more specific:

authpriv.*  @@logserver.example.com:514
mail.err    @@logserver.example.com:514

Service checks

systemctl status rsyslog
systemctl restart rsyslog
journalctl -u rsyslog -n 50

What to check

Config validation (rsyslogd -N1)

Before reloading rsyslog after any config change, validate the config without actually starting the daemon. This prevents a bad config from breaking logging system-wide.

# Validate the full rsyslog config (level 1 = config check only)
rsyslogd -N1

# Validate and show all loaded config files
rsyslogd -N1 -f /etc/rsyslog.conf

# If valid, output ends with:
# rsyslogd: End of config validation run. Bye.

# If invalid, you get a specific error:
# rsyslogd: error: invalid input module 'imtcp': No such file or directory

Always run rsyslogd -N1 before systemctl restart rsyslog. A bad config silently stops all local logging, which you may only notice much later during an incident investigation.

logger smoke test

The logger command writes a syslog message from the command line — the fastest way to verify that log routing works end-to-end after a config change.

# Send a test message with a specific facility and severity
logger -p mail.info "Test message from logger"

# Then verify it appeared in the expected log file
grep "Test message" /var/log/maillog   # RHEL/CentOS
grep "Test message" /var/log/mail.log  # Debian/Ubuntu

# Send a test to verify remote forwarding (check on the remote server)
logger -p local0.info "Remote log routing test from $(hostname)"

# Custom tag (appears in log as "mytag: message")
logger -t mytag -p daemon.warning "Something happened on $(hostname)"

# Use logger to test a full facility → file routing rule
logger -p auth.info "SSH auth test message"
tail -5 /var/log/secure   # or /var/log/auth.log

Receiving logs (imtcp)

To set up rsyslog as a central log receiver (log aggregator), load the TCP input module and define a listener. All sending hosts forward to this server.

On the receiving server

# /etc/rsyslog.conf or /etc/rsyslog.d/receiver.conf

# Load the TCP input module
module(load="imtcp")

# Open the TCP listener on port 514
input(type="imtcp" port="514")

# Optional: also load UDP (legacy senders)
module(load="imudp")
input(type="imudp" port="514")

# Store logs per sending host in separate files
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteLogs
& ~    # stop processing here (don't also log to local files)
# Open firewall port on the receiver
firewall-cmd --permanent --add-port=514/tcp
firewall-cmd --permanent --add-port=514/udp
firewall-cmd --reload

# Validate and restart
rsyslogd -N1
systemctl restart rsyslog

# Verify listener is open
ss -tlnp | grep :514

On each sending host

# /etc/rsyslog.d/forward.conf
# Forward all logs to the central syslog server via TCP
*.* @@logserver.internal.example.com:514   # @@ = TCP, @ = UDP

# Or with the newer RainerScript syntax
action(type="omfwd"
  target="logserver.internal.example.com"
  port="514"
  protocol="tcp"
  action.resumeRetryCount="10"
  queue.type="LinkedList"
  queue.size="10000")

The newer RainerScript syntax with queue settings is preferred — it buffers messages in memory if the central server is temporarily unreachable and retries automatically.