rsyslog Architecture
Every Linux server produces log messages, and every message has to go somewhere. rsyslog is the daemon that receives these messages, decides what to do with them, and delivers them. This guide explains how that pipeline is built and what rsyslog does better than the alternatives.
What Is the rsyslog Daemon?
The rsyslog daemon is a background program (not something users interact with directly) that receives log messages from applications and from the network and routes each message to a useful destination. On a modern Linux server it usually plays two distinct roles at once:
- Local log collection: it captures everything the operating system and applications write, categorizes it by facility and severity, and writes it to files such as
/var/log/messagesand/var/log/secure. - Log forwarding: it receives messages from other servers and delivers them to a central server.
In plain terms: rsyslog is like a post office for log lines. The sorting center is the filter engine, and the delivery routes are the output actions.
The term syslog refers both to a network protocol and to a family of daemons that understand that protocol. rsyslog is the dominant implementation on Linux and is effectively the reference implementation of the protocol.
Why Is It Installed Almost Everywhere?
The rsyslog package exists in every major Linux distribution, and the daemon on many appliances is the same one. This ubiquity has a reason beyond convenience: a device you have never configured still sends logs whose format rsyslog already understands.
If you are replacing the legacy syslog daemon on Solaris, AIX, or an older appliance, rsyslog retains partial compatibility with classic BSD configuration. Migration usually means translating the old $-prefixed directives, not redesigning the pipeline.
Pipeline Architecture
Every message in rsyslog travels a fixed, well-defined path. The stages are deliberately generic; that is why a single daemon can write to a local file and send to Elasticsearch at the same time, without changing how messages are received.
Input Modules
An input module (prefixed with im) is a plugin that knows how to read messages from a specific source. Nothing enters the rsyslog engine without passing through an input module.
| Input module | Source it reads |
|---|---|
imjournal | The systemd journal, so rsyslog and journalctl see the same events |
imtcp | Messages arriving over TCP from other hosts |
imudp | Messages arriving over UDP from other hosts |
imuxsock | The traditional Unix socket /dev/log |
imkmsg | The kernel ring buffer via /dev/kmsg |
imfile | Arbitrary log files, for tailing existing logs |
imrelp | The RELP protocol, which acknowledges every message |
In current rsyslog versions, imtcp is the supported TCP input for production. The older imptcp module still exists but is no longer the recommended choice.
The Main Message Queue
Every message that enters the engine is first placed in a main message queue. A queue is a waiting area that decouples a fast producer from a slow consumer, and this idea underpins most of rsyslog's durability features.
Once the ruleset has processed a message, the message leaves the main queue, enters a downstream queue, and is removed from the main queue at that moment. This hand-off matters because it guarantees that a slow output never stops message reception.
Rulesets and Filters
A ruleset is a named block of rules that both filters and acts. Inside each rule, conditions are evaluated against the message's structured fields rather than raw text, so matching on severity or program name is exact and independent of formatting.
rsyslog keeps structured fields for timestamp, hostname, program name, process ID, message ID, facility, severity, and structured data. Modern parsing follows RFC 5424, the current syslog standard, while the older RFC 3164 format is still accepted for legacy senders.
Actions and Queues
An action (prefixed with om) does something with a message: writes it to a file, sends it to another host, or delivers it to a database. Each action can have its own dedicated queue, and these queues are configured independently.
Why it matters: these per-output queues are what let a single rsyslog instance survive a slow Elasticsearch cluster while still writing local files at full speed. The slow destination fills its own queue and eventually drops messages, while the other paths keep running uninterrupted.
Queues and Flow Control
Queue behavior is the most important design decision in an rsyslog deployment, because it determines what survives the 3 a.m. network outage.
| Queue type | Storage | Survives restart | Typical use |
|---|---|---|---|
Direct | No buffering | No | Local file writes, where latency matters more |
LinkedList / FixedArray | Memory | No | High-traffic paths where dropping messages is acceptable |
Disk-Assisted | Memory with disk overflow | Yes | Forwarding to a central server, the common production choice |
Disk | Disk only | Yes | Audit and archive paths where no message may be lost |
Queue parameters are written in RainerScript syntax inside the object that owns the queue, so main_queue(), ruleset(), and action() each take their own independent queue.* settings.
main_queue(
queue.type="LinkedList"
queue.size="500000"
queue.filename="mainq"
queue.saveOnShutdown="on"
queue.maxDiskSpace="2g"
)
High and Low Watermarks
Flow control uses two thresholds called watermarks. When the queue reaches the high watermark, the producer slows down or stops; processing resumes once the queue drains below the low watermark.
The gap between the two thresholds is intentional. Without it, a queue hovering near the threshold would oscillate between full and empty and repeatedly stall processing.
A full queue does not fail loudly. Depending on configuration, rsyslog silently drops messages and shows nothing in the output. Monitor queue fill rates and never assume delivery.
The RainerScript Language
RainerScript is rsyslog's configuration language, designed specifically for event stream processing. It replaced the legacy $-prefixed syntax, although the old form still works and appears in many existing configurations.
The main objects you write are global(), module(), input(), action(), template(), and ruleset(). Flow control uses the familiar if and then statements, so the syntax stays readable for anyone who has written a shell script.
global(
workDirectory="/var/spool/rsyslog"
maxMessageSize="64k"
defaultNetstreamDriver="gtls"
)
module(load="imtcp" port="6514")
module(load="imjournal" StateFile="imjournal.state")
template(name="ForwardFormat" type="string"
string="<%pri%>1 %TIMESTAMP:::date-rfc3339% %hostname% %app-name% %procid% %msgid% %structured-data% %msg%\n")
if ($syslogfacility-text == "authpriv") then {
action(type="omfile" file="/var/log/secure" template="RSYSLOG_TraditionalFileFormat")
stop
}
The workDirectory parameter specifies where disk and disk-assisted queues write their spool files. Put it on a partition with real free space, because a queue that cannot write its overflow file has nowhere to hold incoming messages.
Practical Use Cases
rsyslog has earned its place in the modern stack for a few specific reasons. Knowing which one applies to you determines whether you need it at all.
Surviving Network Outages
This is the strongest reason to choose rsyslog. syslog over plain TCP has no acknowledgement, so a sender whose buffer fills during a network outage silently drops messages. A disk-assisted queue absorbs the outage on disk and drains once the link returns.
| Scenario | Plain TCP with imtcp | RELP with imrelp | Disk-assisted queue |
|---|---|---|---|
| Acknowledged delivery without loss | ❌ | ✅ | ✅ |
| Buffering messages during an outage | ❌ | Partly | ✅ |
| Message survival after restart | ❌ | ❌ | ✅ |
The RELP protocol (short for Reliable Event Logging Protocol) adds per-message acknowledgement to syslog. The receiver acknowledges each message before the sender discards it, which turns best-effort delivery into confirmed delivery.
Centralizing Logs Across a Fleet
Centralized logging is the reason most organizations run rsyslog. When logs stay only on the machine that produced them, a failed machine takes its own witness with it.
Routing to Multiple Destinations
The output module list is unusually broad for a system daemon. A single instance can, from one stream of messages, write a local file, forward to another rsyslog, and ship structured events to a search cluster.
| Output module | Destination |
|---|---|
omfile | Local file with rotation |
omfwd | Another syslog server over UDP, TCP, or RELP |
omelasticsearch | An Elasticsearch or OpenSearch cluster |
omkafka | A topic in Apache Kafka |
omhiredis | A list or stream in Redis |
ommongodb / ompgsql / ommysql | A document or relational database |
omsnmp | SNMP traps for network equipment |
Filtering Before Storage
Because the ruleset tests structured fields rather than text, routing rules stay correct even when an application changes its message format. Separating authentication events into /var/log/secure is a one-line condition, not a fragile regular expression.
Log messages routinely contain data you would not want published: source IP addresses, usernames, query strings with tokens, and full URLs. Treat every log destination as sensitive storage and restrict write access on the log server.
Limitations of rsyslog
An honest assessment matters more than any marketing copy, because choosing rsyslog for the wrong reason produces a system that is hard to maintain.
- It is not an observability platform. rsyslog moves log lines. It does not store metrics, capture request traces, or build dashboards, so it sits alongside tools like Prometheus rather than replacing them.
- Configuration complexity grows quickly. A simple forwarding line is easy. Once queues, a TLS trust chain, rate limiting, and per-application routing are involved, the configuration becomes a real program that needs review.
- UDP is unreliable by design. The protocol offers no delivery guarantee, and the default port 514 on UDP drops messages whenever a burst exceeds the receive buffer.
- The legacy syntax remains tempting. Old directives such as
$ActionQueueTypeand$AllowedSenderstill work, which lets two configuration styles mix in one file and makes it unclear which one is actually active. - It can hide message repetition. rsyslog can rate-limit identical messages, which is good for a noisy service but means a real attack sending the same malformed packet a thousand times may appear as a single line.
On a single machine, journalctl is usually the better tool for interactive investigation because it is indexed out of the box and needs no separate daemon. rsyslog earns its keep when the question is no longer about one host but about a fleet.
How rsyslog Relates to the systemd Journal
The two systems overlap, and understanding the boundary prevents duplicated work. rsyslog can read the journal through imjournal, meaning both views are fed from a single source of truth.
| Question | Better tool |
|---|---|
| What happened on this host in the last hour? | journalctl |
| What did all 200 hosts do last night? | rsyslog |
| How do I ship journal events to a SIEM? | rsyslog with imjournal |
| How do I forward logs over an unreliable link? | rsyslog with a disk-assisted queue |
Because imjournal replays the journal from the last read position, no events are lost when rsyslog restarts, provided the state file lives on persistent storage. Deleting that file causes a replay from the beginning of the journal.
Summary
- The
rsyslogdaemon is the program that receives, filters, buffers, and delivers log messages on Linux. - The pipeline path is fixed: input modules feed the main queue, the ruleset filters, and per-action queues feed output modules.
- The disk-assisted queue is its most decisive feature, because it absorbs network outages and drains later without losing messages.
- For centralizing logs across a fleet, multi-destination routing and structured-field filtering, rsyslog outperforms competing options.
- It is not an observability platform, and once TLS, rate limiting, and multiple queues are involved, its configuration needs serious review.
- On a single host, prefer
journalctlfor investigation and leave fleet-scale work to rsyslog.
For the commands that make these logs readable in daily work, see Linux logging commands, and for a problem-driven approach to finding them, read the logging mental model guide.