Syslog Integration
Ingest BSD and IETF syslog messages from Linux, Mac, and network devices directly into AnyLog — prerequisites, node configuration, and running/validating the pipeline.
Syslog is a standardized protocol for sending and receiving log messages across a network. AnyLog can act as a syslog receiver, accepting messages from any host that supports TCP syslog output and storing them as queryable time-series data alongside all other data in the network — letting you monitor and troubleshoot the status of many machines from a single point rather than checking each one separately.
Prefer automation? Everything below — the rsyslog forwarding rule and the AnyLog-side message rule — can be set up automatically via the dotenv-driven
syslog.shscript, wired intomake setup SERVICE=syslog. It readsSYSLOG_MONITORINGandANYLOG_BROKER_PORTfrom your node’snode_configs.envand is idempotent (safe to re-run, and a no-op ifSYSLOG_MONITORING != "true"). See the Docker & K8s Commands doc for the exact command. The manual walkthrough below is for understanding what that automation is doing, or for setting things up by hand.
1. Prerequisites
On the physical machine — install and start rsyslog
sudo apt-get -y update
sudo apt -y install rsyslog
sudo service rsyslog start
The same steps apply to syslog-ng if preferred over rsyslog.
Validate rsyslog is running:
tail -f /var/log/syslog
Expected output:
Feb 25 02:55:47 localhost systemd[1]: Started User Manager for UID 0.
Feb 25 02:55:47 localhost systemd[1]: Started Session 197 of User root.
Feb 25 02:55:52 localhost systemd-udevd[400]: Network interface NamePolicy= disabled on kernel command line, ignoring.
Feb 25 02:55:53 localhost dbus-daemon[31261]: AppArmor D-Bus mediation is enabled
...
2. Configure the Node
Understand the syslog formats
Syslog is delivered from each machine in one of two formats — knowing which one you’re receiving determines how you’ll
set the syslog / format options on the rule below.
| Format | Standard | Timestamp | Key fields |
|---|---|---|---|
| BSD | RFC 3164 | MMM dd hh:mm:ss |
Priority, Timestamp, Hostname, Tag (process + PID), Message |
| IETF | RFC 5424 | ISO 8601 | Priority, Version, Timestamp, Hostname, Application, PID, Message ID, Structured Data, Message |
Field-by-field breakdown</summary>
BSD format fields
- Priority — enclosed in angle brackets (
< and >); a numeric value combining facility and severity (e.g. <34>).
- Timestamp — immediately follows the priority, typically
MMM dd hh:mm:ss (e.g. Jan 12 23:34:56).
- Hostname or IP address — the name or IP of the device that sent the message.
- Tag — often a process name or application identifier, potentially followed by a process ID in square brackets (e.g.
sshd[3268]).
- Message — the actual log message text, following the tag.
IETF format fields
- Priority — same as BSD, enclosed in angle brackets.
- Version — a single digit indicating the syslog protocol version (e.g.
1).
- Timestamp — more precise than BSD, typically ISO 8601.
- Hostname — as in BSD format.
- Application — the name of the application or process generating the message.
- Process ID (PID) — the PID of the process.
- Message ID — a unique identifier for the type of message.
- Structured data — enclosed in square brackets, key-value pairs for additional data.
- Message — the actual log message text.
</details>
Start the message broker
The message broker is the TCP listener that receives syslog traffic. AnyLog’s regular TCP service is dedicated to
communication between AnyLog nodes and cannot be used for external data ingestion — the message broker is the
correct service for receiving data from outside the network. Start it on the operator or publisher node:
<run message broker where
external_ip = !external_ip and external_port = !anylog_broker_port and
internal_ip = !ip and internal_port = !anylog_broker_port and
bind = !broker_bind and threads = !broker_threads>
Check which IP/port to direct syslog output to:
get connections
Point rsyslog at AnyLog
Add the following to the bottom of /etc/rsyslog.conf, replacing DESTINATION_IP and DESTINATION_PORT with the
AnyLog operator/publisher IP and message broker port found above:
$template remote-incoming-logs, "/var/log/remote/%HOSTNAME%.log"
*.* ?remote-incoming-logs
*.* action(type="omfwd" target="{DESTINATION_IP}" port="{DESTINATION_PORT}" protocol="tcp")
Restart rsyslog to apply:
sudo service rsyslog restart
This is exactly the step syslog.sh setup automates on Linux (via an rsyslog drop-in) and on macOS (via
/etc/syslog.conf) — see the automation callout above.
Set a syslog rule
Rules tell AnyLog how to route and parse incoming syslog messages:
set msg rule [rule name] if ip = [source IP] and port = [port] and header = [header text] then dbms = [dbms] and table = [table] and syslog = [true/false] and extend = ip and format = [format] and topic = [topic]
Option
Required
Description
rule name
✅
Unique name for this rule
ip
—
Source IP to match — omit to match all IPs
port
—
Source port to match — omit to match all ports
header
—
Match messages with a specific prefix string (see Example 2 below)
dbms
✅
Target logical database
table
✅
Target table
syslog
—
true — parse as BSD syslog. Set format = IETF for RFC 5424
extend
—
Add extra fields — extend = ip adds the source IP
format
—
Override the default format: IETF for RFC 5424
topic
—
Route through the msg-client mapping layer (like MQTT)
structure
—
included — first message event defines the column schema (see Example 3 below)
When syslog = true, column names are pre-determined by the format (BSD by default, or format = IETF).
When syslog is not set, use structure = included so the first event defines the schema instead.
Basic example — accept BSD syslog from this node’s own default database/table:
set msg rule syslog_rule if ip = !ip then dbms = new_company and table = syslog and syslog = true
Partition & clean up (recommended)
Syslog volume adds up quickly — partition the table and schedule automatic cleanup so it doesn’t grow unbounded:
connect dbms new_company where type=sqlite
partition new_company syslog using insert_timestamp by 12 hours
schedule time = 12 hours and name = "Drop Partition Sync - Syslog" task drop partition where dbms = new_company and table = syslog and keep = 3
More configuration examples
Example — Linux journalctl via netcat, with a header prefix
Pipe journalctl output to AnyLog, prefixing each line with a custom header so the rule below can match on it:
journalctl --since "${NOW}" | awk '{print "al.sl.header.new_company.syslog", $0}' | nc -w 1 10.0.0.78 7850
set msg rule my_rule if ip = 10.0.0.50 and header = al.sl.header.new_company.syslog then dbms = new_company and table = syslog and syslog = true
Example — Mac syslog with dynamic structure from the first event
(log show --info --start '2024-01-01 16:50:00' --end '2024-12-01 16:51:00' | awk '{print "al.sl", $0}') | nc -w 1 10.0.0.78 7850
The first event contains the column headers, which structure = included uses to define the schema:
al.sl Timestamp Thread Type Activity PID TTL
al.sl 2024-01-01 17:51:35.253053-0800 0x4d0c71 Default 0x39223d 482 3 ...
set msg rule my_rule if ip = 10.0.0.251 and header = al.sl then dbms = new_company and table = syslog_mac and structure = included
3. Run & Validate
Trigger test data
On the monitored machine, run an update/upgrade (or anything else that generates log activity):
sudo apt-get -y update
sudo apt-get -y upgrade
Confirm the rule is active and receiving data
get msg rules
Expected output:
Name IF IF IF THEN THEN THEN THEN THEN Batches Events Errors Error Msg
Source IP Port Header DBMS Table SysLog Topic Structure
-----------|-------------|-----|-------|-----------|------|-------|------|----------|-------|------|------|---------|
syslog_rule|10.0.0.78 |* | |new_company|syslog|True | | | 18| 32| 0| |
Query the data
From a query node:
-- row count
run client () sql new_company format=table "select count(*) from syslog"
-- sample rows
run client () sql new_company "select * from syslog limit 10"
Sample output (note the tsd_name / tsd_id partition-metadata columns AnyLog adds automatically):
{"Query":[
{"row_id":1,
"insert_timestamp":"2024-02-25 03:18:35.023262",
"tsd_name":"131",
"tsd_id":4610,
"priority":38,
"timestamp":"2024-02-25 03:17:27.000000",
"hostname":"localhost",
"tag":"sshd[32839]:",
"message":"Invalid user lighthouse from 10.0.0.100 port 45126"},
{"row_id":2,
"insert_timestamp":"2024-02-25 03:18:35.023262",
"tsd_name":"131",
"tsd_id":4610,
"priority":85,
"timestamp":"2024-02-25 03:17:27.000000",
"hostname":"localhost",
"tag":"sshd[32839]:",
"message":"pam_unix(sshd:auth): check pass; user unknown"}
],
"Statistics":[{"Count": 10, "Time":"00:00:00", "Nodes": 1}]}
Manage & debug
get msg rules -- list all active rules and their event counts
reset msg rule [rule name] -- remove a rule
Enable trace to see the source IP, port, and first 100 bytes of each incoming message:
trace level = 2 run message broker
Example trace output:
[Message Broker Received 1650 Bytes] [Source: 10.0.0.78:1468] [Data: <134>Jan 26 17:30:10 DESKTOP sshd[3268] User login...]
A single message may contain multiple events — trace only shows the first 100 bytes of each. Use get msg rules to
see the actual number of events processed.
< and >); a numeric value combining facility and severity (e.g. <34>).MMM dd hh:mm:ss (e.g. Jan 12 23:34:56).sshd[3268]).1).<run message broker where
external_ip = !external_ip and external_port = !anylog_broker_port and
internal_ip = !ip and internal_port = !anylog_broker_port and
bind = !broker_bind and threads = !broker_threads>
get connections
/etc/rsyslog.conf, replacing DESTINATION_IP and DESTINATION_PORT with the
AnyLog operator/publisher IP and message broker port found above:$template remote-incoming-logs, "/var/log/remote/%HOSTNAME%.log"
*.* ?remote-incoming-logs
*.* action(type="omfwd" target="{DESTINATION_IP}" port="{DESTINATION_PORT}" protocol="tcp")
sudo service rsyslog restart
This is exactly the step syslog.sh setup automates on Linux (via an rsyslog drop-in) and on macOS (via
/etc/syslog.conf) — see the automation callout above.
set msg rule [rule name] if ip = [source IP] and port = [port] and header = [header text] then dbms = [dbms] and table = [table] and syslog = [true/false] and extend = ip and format = [format] and topic = [topic]
rule nameipportheaderdbmstablesyslogtrue — parse as BSD syslog. Set format = IETF for RFC 5424extendextend = ip adds the source IPformatIETF for RFC 5424topicstructureincluded — first message event defines the column schema (see Example 3 below)When syslog = true, column names are pre-determined by the format (BSD by default, or format = IETF).
When syslog is not set, use structure = included so the first event defines the schema instead.
set msg rule syslog_rule if ip = !ip then dbms = new_company and table = syslog and syslog = true
connect dbms new_company where type=sqlite
partition new_company syslog using insert_timestamp by 12 hours
schedule time = 12 hours and name = "Drop Partition Sync - Syslog" task drop partition where dbms = new_company and table = syslog and keep = 3
journalctl via netcat, with a header prefixjournalctl output to AnyLog, prefixing each line with a custom header so the rule below can match on it:journalctl --since "${NOW}" | awk '{print "al.sl.header.new_company.syslog", $0}' | nc -w 1 10.0.0.78 7850
set msg rule my_rule if ip = 10.0.0.50 and header = al.sl.header.new_company.syslog then dbms = new_company and table = syslog and syslog = true
(log show --info --start '2024-01-01 16:50:00' --end '2024-12-01 16:51:00' | awk '{print "al.sl", $0}') | nc -w 1 10.0.0.78 7850
structure = included uses to define the schema:al.sl Timestamp Thread Type Activity PID TTL
al.sl 2024-01-01 17:51:35.253053-0800 0x4d0c71 Default 0x39223d 482 3 ...
set msg rule my_rule if ip = 10.0.0.251 and header = al.sl then dbms = new_company and table = syslog_mac and structure = included
sudo apt-get -y update
sudo apt-get -y upgrade
get msg rules
Name IF IF IF THEN THEN THEN THEN THEN Batches Events Errors Error Msg
Source IP Port Header DBMS Table SysLog Topic Structure
-----------|-------------|-----|-------|-----------|------|-------|------|----------|-------|------|------|---------|
syslog_rule|10.0.0.78 |* | |new_company|syslog|True | | | 18| 32| 0| |
-- row count
run client () sql new_company format=table "select count(*) from syslog"
-- sample rows
run client () sql new_company "select * from syslog limit 10"
tsd_name / tsd_id partition-metadata columns AnyLog adds automatically):{"Query":[
{"row_id":1,
"insert_timestamp":"2024-02-25 03:18:35.023262",
"tsd_name":"131",
"tsd_id":4610,
"priority":38,
"timestamp":"2024-02-25 03:17:27.000000",
"hostname":"localhost",
"tag":"sshd[32839]:",
"message":"Invalid user lighthouse from 10.0.0.100 port 45126"},
{"row_id":2,
"insert_timestamp":"2024-02-25 03:18:35.023262",
"tsd_name":"131",
"tsd_id":4610,
"priority":85,
"timestamp":"2024-02-25 03:17:27.000000",
"hostname":"localhost",
"tag":"sshd[32839]:",
"message":"pam_unix(sshd:auth): check pass; user unknown"}
],
"Statistics":[{"Count": 10, "Time":"00:00:00", "Nodes": 1}]}
get msg rules -- list all active rules and their event counts
reset msg rule [rule name] -- remove a rule
trace level = 2 run message broker
[Message Broker Received 1650 Bytes] [Source: 10.0.0.78:1468] [Data: <134>Jan 26 17:30:10 DESKTOP sshd[3268] User login...]
get msg rules to
see the actual number of events processed.