Central Logging does not listen on port 514.
That is a problem, because your firewall and your NAS only know how to send syslog. You cannot install an agent on them. The firmware sends syslog or it sends nothing.
The fix is a relay. One Linux box you already own runs rsyslog, accepts syslog from the appliances, and forwards it upstream over HTTP. Twenty lines of config, and it can live on the same machine that runs Central Logging.
This guide covers OPNsense, Synology DSM and TrueNAS. Anything else that can send syslog — a switch, a UPS, a printer, a UniFi controller — works the same way once the relay is up.
OPNsense ─┐
Synology ─┼─→ rsyslog relay ─→ HTTPS ─→ Central Logging
TrueNAS ─┘ (port 514) (ingest endpoint)
The relay does two jobs. It speaks syslog to the appliances. And it decides which log source each device lands in, so your firewall logs are not tangled up with your NAS logs.
Pick any Linux box that stays on. Install rsyslog and the HTTP output module:
sudo apt install rsyslog rsyslog-omhttp
Create a log source in Central Logging for each appliance. Three appliances, three tokens. You can still search across all of them at once, and keeping them apart means one noisy device does not bury the others.
Now write /etc/rsyslog.d/60-appliances.conf:
module(load="imudp")
module(load="imtcp")
module(load="omhttp")
template(name="cl_json" type="list") {
constant(value="{")
constant(value="\"timestamp\":\"") property(name="timereported" dateFormat="rfc3339")
constant(value="\",\"host\":\"") property(name="hostname" format="json")
constant(value="\",\"from_ip\":\"") property(name="fromhost-ip")
constant(value="\",\"severity\":\"") property(name="syslogseverity-text")
constant(value="\",\"facility\":\"") property(name="syslogfacility-text")
constant(value="\",\"tag\":\"") property(name="programname" format="json")
constant(value="\",\"message\":\"") property(name="msg" format="json")
constant(value="\"}")
}
ruleset(name="appliances") {
if $fromhost-ip == "192.168.1.1" then {
action(type="omhttp"
server="logs.example.com" serverport="443" usehttps="on"
restpath="api/v1/ingest_logs/OPNSENSE-SOURCE-TOKEN"
template="cl_json"
batch="on" batch.format="newline" batch.maxsize="500"
queue.type="LinkedList" queue.filename="cl_opnsense"
queue.maxdiskspace="1g" queue.saveonshutdown="on"
action.resumeRetryCount="-1")
stop
}
if $fromhost-ip == "192.168.1.20" then {
action(type="omhttp"
server="logs.example.com" serverport="443" usehttps="on"
restpath="api/v1/ingest_logs/SYNOLOGY-SOURCE-TOKEN"
template="cl_json"
batch="on" batch.format="newline" batch.maxsize="500"
queue.type="LinkedList" queue.filename="cl_synology"
queue.maxdiskspace="1g" queue.saveonshutdown="on"
action.resumeRetryCount="-1")
stop
}
if $fromhost-ip == "192.168.1.30" then {
action(type="omhttp"
server="logs.example.com" serverport="443" usehttps="on"
restpath="api/v1/ingest_logs/TRUENAS-SOURCE-TOKEN"
template="cl_json"
batch="on" batch.format="newline" batch.maxsize="500"
queue.type="LinkedList" queue.filename="cl_truenas"
queue.maxdiskspace="1g" queue.saveonshutdown="on"
action.resumeRetryCount="-1")
stop
}
}
input(type="imudp" port="514" ruleset="appliances")
input(type="imtcp" port="514" ruleset="appliances")
Validate and restart:
sudo rsyslogd -N1
sudo systemctl restart rsyslog
Binding the inputs to a ruleset keeps appliance logs out of /var/log/syslog. Without ruleset="appliances", every message from every device also lands in the relay’s own log files. Your firewall then fills the relay’s disk while you are not looking.
The disk-assisted queue is what makes this reliable. queue.filename spools to disk, and action.resumeRetryCount="-1" retries forever. Restart Central Logging and the relay holds everything, then delivers it. Drop those two lines and rsyslog gives up after a few attempts and throws the messages away.
stop matters. It ends processing for that message. Leave it out and a message matching two rules gets sent twice.
The rsyslog guide explains the template, the batching and the queue options in more depth. Read it if you plan to tune any of this.
sudo ufw allow from 192.168.1.0/24 to any port 514
Do not expose 514 to the internet. Syslog has no authentication. Anyone who can reach that port can write anything they like into your logs.
Go to System → Settings → Logging / Targets and add a target:
| Field | Value |
|---|---|
| Transport | TCP (or UDP) |
| Applications | leave empty for everything, or pick filterlog for firewall only |
| Levels | leave empty for everything |
| Hostname | the relay’s IP |
| Port | 514 |
Prefer TCP. UDP syslog drops messages under load without telling anyone, and load spikes during exactly the incidents you care about.
Firewall log lines arrive with the tag filterlog. They are comma-separated fields, not JSON, so the whole line lands in message. Search them with full-text search or LIKE.
One warning before you enable everything. A firewall that logs every blocked packet on a WAN interface produces an enormous amount of noise — internet background scanning alone will generate thousands of lines an hour. Start with filterlog off, confirm the pipeline works, then turn on logging per rule for the rules you actually want to watch.
Install Log Center from Package Center if it is not there already. Then open Log Center → Log Sending:
Synology sends its system log, which covers DSM logins, package events, SMB connections and disk warnings. That last one is why this is worth doing — a DSM notification email you filtered out two years ago is not disk monitoring.
In TrueNAS SCALE, go to System Settings → Advanced → Syslog and edit it:
| Field | Value |
|---|---|
| Syslog Server | 192.168.1.10:514 |
| Syslog Transport | TCP |
| Syslog Level | Notice |
Start at Notice. Info and Debug will bury you.
TrueNAS reports ZFS scrub results, pool state changes and SMART warnings through syslog. Those three are the reason a NAS ends up in a log server.
The template gives every message the same shape, so the same query works across all three devices. Central Logging stores logs in SQLite, so json_extract reaches any field.
Everything at error level or worse, newest first:
SELECT
"timestamp",
json_extract(msg, '$.host') AS device,
json_extract(msg, '$.tag') AS program,
json_extract(msg, '$.message') AS message
FROM logs
WHERE json_valid(msg)
AND json_extract(msg, '$.severity') IN ('err', 'crit', 'alert', 'emerg')
ORDER BY "timestamp" DESC
LIMIT 200;
What your firewall is blocking most:
SELECT
json_extract(msg, '$.message') AS line,
COUNT(*) AS hits
FROM logs
WHERE json_valid(msg)
AND json_extract(msg, '$.tag') = 'filterlog'
GROUP BY line
ORDER BY hits DESC
LIMIT 50;
Failed logins against the NAS:
SELECT
"timestamp",
json_extract(msg, '$.message') AS message
FROM logs
WHERE json_valid(msg)
AND (json_extract(msg, '$.message') LIKE '%failed to log in%'
OR json_extract(msg, '$.message') LIKE '%authentication failure%')
ORDER BY "timestamp" DESC
LIMIT 100;
Which device is generating your volume, which is the query you run when you wonder why storage is growing:
SELECT
json_extract(msg, '$.from_ip') AS device,
COUNT(*) AS lines
FROM logs
WHERE json_valid(msg)
GROUP BY device
ORDER BY lines DESC;
A NAS with a failing disk tells you once, in a log line, at 4am. Make it come to you instead. Create an alert rule using full-text search:
+("pool degraded" OR "SMART error" OR "device removed")
And a second one for repeated failed logins on the Synology source:
SELECT COUNT(*) AS attempts
FROM logs
WHERE json_valid(msg)
AND json_extract(msg, '$.message') LIKE '%failed to log in%'
HAVING attempts > 20;
Central Logging evaluates rules every five minutes and notifies through Slack or Telegram. Set a max frequency on both. A degraded pool stays degraded, and you do not need reminding every five minutes for two days.
Two cases, honestly.
You want to keep raw packet-level firewall logs forever. Central Logging is built for small teams under roughly 10GB a day. A busy firewall logging every connection can exceed that on its own. Filter at the appliance, or send only the rules you care about.
You already run a syslog collector you are happy with. If Graylog or an ELK stack is already receiving these devices and you are not paying for it in time or money, adding a relay hop gains you nothing. The reason to move is cost, complexity or per-GB pricing — not the syslog part.
Appliances speak syslog and nothing else. Put an rsyslog relay in front, bind the inputs to their own ruleset, route each device to its own log source, and give every action a disk-backed queue.
Then the firewall, the NAS and the servers all end up in one search box.
Central Logging is a single binary you install on a server you already own. No JVM, no Docker, no per-GB bill — $187 once. See Deploy, or start with setting up a self-hosted logging server.
💌 Get notified on new features and updates