Syslog forwarding (RFC 5424)
Operator runbook for piping IdentityMesh logs straight to an on-prem
syslog collector — Splunk Heavy/Universal Forwarders with a syslog
input, IBM QRadar, ArcSight ESM/SmartConnectors, Graylog, RSyslog,
Logstash with the syslog codec. This is an opt-in sibling to the
default Serilog file + Windows Event Log sinks; nothing is enabled
by default.
If your SIEM is happy reading log files or the Application Event
Log directly, prefer that — see siem-integration.md
for the full surface map. Use syslog when the collector is the
contract you have to meet (most on-prem SIEMs without OTLP support
treat syslog as the primary ingest channel).
Why a syslog sink
- Splunk — the syslog input on a Heavy Forwarder (or syslog-ng → UF) is the canonical pattern for hosts where you can’t run a UF but can route UDP/TCP traffic out.
- IBM QRadar — DSMs for “Microsoft Windows Security Event Log” expect either WinCollect or syslog-formatted feeds.
- ArcSight ESM / SmartConnectors — the Syslog Daemon SmartConnector is one of the most commonly deployed connectors; syslog is the path of least resistance.
- Graylog / RSyslog / syslog-ng — native ingest, no shim.
- OTLP gap — most on-prem SIEMs still don’t speak OTLP; for the metrics side you’d need a Collector hop. Syslog is the durable fallback for the log stream.
What gets shipped
Every Serilog event the Sync Engine emits — same lines that go to
the rolling file at <install dir>\logs\identitymesh-YYYYMMDD.log
— is forwarded to the syslog collector when the sink is enabled.
Enrichers (MachineName, ThreadId, RequestId, CycleId,
InstanceName) ride along as RFC 5424 structured-data fields.
The Admin API and Relay Agent each have their own Serilog
configuration. The pattern below applies to all three; copy the
fragment into the matching appsettings.json for whichever
component(s) you want to forward.
Enabling syslog forwarding
The Sync Engine ships with a sample at:
<install dir>\appsettings.Syslog.example.json
Copy the Serilog.Using array entry and a Serilog.WriteTo block
into the live appsettings.json (or, preferred for a host-specific
override, appsettings.Production.json which the host honours via
ASP.NET environment conventions). Restart the IdentityMesh service.
Minimal RFC 5424 / TCP recipe (recommended default)
{
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File",
"Serilog.Sinks.EventLog",
"Serilog.Sinks.Syslog"
],
"WriteTo": [
{
"Name": "TcpSyslog",
"Args": {
"host": "syslog.corp.example",
"port": 1468,
"appName": "IdentityMesh",
"framingType": "OCTET_COUNTING",
"format": "RFC5424",
"facility": "Local0"
}
}
]
}
}
Key knobs:
| Field | Meaning |
|---|---|
host / port | Target syslog collector. Default port 1468 is the IETF reserved TCP port. |
appName | RFC 5424 APP-NAME field. Pick a per-component value if you forward multiple — e.g. IdentityMesh, IdentityMesh.Admin.Api, IdentityMesh.Relay.Agent. |
format | RFC5424 (modern, structured-data, recommended) or RFC3164 (BSD legacy — only if your collector chokes on 5424). |
framingType | OCTET_COUNTING (RFC 6587 § 3.4.1, recommended for TCP) or NON_TRANSPARENT_FRAMING for \n-delimited. |
facility | RFC 5424 facility — Local0–Local7 are the conventional application-log slots. |
TLS variant (production)
For traffic that crosses host boundaries — and especially across
network segments — wrap the TCP connection in TLS. Replace host
/ port with the TLS endpoint and add the cert config:
{
"Name": "TcpSyslog",
"Args": {
"host": "syslog.corp.example",
"port": 6514,
"appName": "IdentityMesh",
"framingType": "OCTET_COUNTING",
"format": "RFC5424",
"facility": "Local0",
"secureProtocols": "Tls12, Tls13",
"certProvider": "Serilog.Sinks.Syslog.CertificateStoreProvider, Serilog.Sinks.Syslog"
}
}
Port 6514 is the registered RFC 5425 TLS-syslog port. The cert provider above resolves the client certificate from the local machine cert store; alternative providers ship with the package for file-based certs. Verify with your collector’s TLS docs.
UDP variant (trusted network only)
{
"Name": "UdpSyslog",
"Args": {
"host": "syslog.corp.example",
"port": 514,
"appName": "IdentityMesh",
"format": "RFC5424",
"facility": "Local0"
}
}
UDP is fire-and-forget. A dropped packet is a lost log line; there is no retransmit. Use only inside a trusted segment where loss is tolerable. Production deployments should prefer TCP/TLS.
Format choice — RFC 5424 vs RFC 3164
- RFC 5424 (default). Structured-data block lets the collector index Serilog enrichers as first-class fields. Modern Splunk, Graylog, RSyslog, syslog-ng all parse it. Choose this unless proven incompatible.
- RFC 3164 (BSD legacy). Free-text message body, no structured-data block. Some older ArcSight SmartConnectors and a handful of QRadar DSMs still pin to 3164. Only fall back if your collector explicitly refuses 5424.
Switch by changing the format arg in the WriteTo block — the
sink emits the chosen format, no other change required.
Collector-side examples
These are pointer-style recipes. Your collector docs are authoritative; verify ports / parser names against your install.
rsyslog (Linux relay → file or onward forward)
# /etc/rsyslog.d/30-identitymesh.conf
module(load="imtcp")
input(type="imtcp" port="1468")
template(name="ImTemplate" type="string"
string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag% %msg%\n")
if $programname startswith 'IdentityMesh' then {
action(type="omfile" file="/var/log/identitymesh.log" template="ImTemplate")
stop
}
Reload with systemctl restart rsyslog. Aim a tail -f at the
output file from a separate shell while you trigger a sync run to
confirm flow.
Splunk (Heavy Forwarder syslog input)
# inputs.conf on the Heavy Forwarder
[tcp://1468]
sourcetype = identitymesh:syslog
index = identitymesh
connection_host = ip
Add a props.conf stanza if you want to break events on the
RFC 5424 leading <PRI> token; Splunk’s default line-breaking
handles octet-counting framing without further tuning.
Failure modes
- Collector unreachable at boot.
Serilog.Sinks.Syslogdoes not block the application — it spins up the TCP connection asynchronously. Events written before the connection establishes are queued in-memory by the sink and flushed on connect. The in-memory queue is bounded; under sustained outages the sink drops the oldest events. - Collector unreachable mid-stream. Same pattern — events written during the outage are queued; on reconnect, the queued tail is flushed but there is no on-disk buffer and no backfill from the rolling file sink. Operators should treat the file sink as the durable record and syslog as the live tap.
- TLS handshake failure. Logged at
Errorlevel via Serilog’sSelfLog. To surface that channel, setSerilog.SelfLog.Enable(...)once at startup or temporarily pointSELF_LOGat a writable file while diagnosing. - Slow collector (TCP backpressure). The sink applies its own internal queue; once full, new events are dropped (oldest-first). Watch your collector’s ingest lag — if it drifts the syslog feed will go thin without alerting.
If the syslog collector is part of your compliance contract, pair
this sink with the audit-table feed
(audit-retention.md) so you have an
authoritative durable evidence channel that doesn’t depend on the
syslog hop being healthy.
Configurable fields cheat-sheet
| Concern | Where to set it |
|---|---|
| Severity floor | Serilog.MinimumLevel.Default / per-component overrides |
| Per-event fields | Serilog enrichers — already wired (MachineName, ThreadId, request scope) |
| App-name in syslog | appName arg on the TcpSyslog / UdpSyslog block |
| Facility | facility arg — Local0–Local7 recommended for app logs |
| Transport | TcpSyslog (recommended) / UdpSyslog (trusted network) / TLS via secureProtocols |
| Framing (TCP) | framingType — OCTET_COUNTING (default, RFC 6587) or NON_TRANSPARENT_FRAMING |
Related
siem-integration.md— the broader SIEM field map: file, Event Log, audit tables, OTLP.audit-retention.md—IM_AdminAudit/IM_ObjectAuditretention, the durable evidence channel that syslog complements.- Default Serilog config — see
appsettings.jsonshipped with each component for the file + Console + EventLog sinks that remain in effect alongside syslog.