Fluxtail
Log Management Guides

Syslog Forwarding: TLS Setup for rsyslog and syslog-ng

Configure syslog forwarding with rsyslog or syslog-ng using TLS verification, RFC 5424 messages, octet-counted framing, bounded queues, and tests.

By Fluxtail Engineering Updated

Syslog forwarding moves events from the host or device that produced them to a remote collector. The sender might be an application, router, firewall, or Linux service. A local daemon such as rsyslog or syslog-ng acts as the forwarder: it reads those events, applies routing rules, formats each message, and sends it to the receiver.

That separation matters during an incident. Local files can disappear with a failed host, while a central copy lets operators search across systems. Forwarding is still a pipeline: format, transport, framing, certificate validation, queues, network policy, and receiver health all affect what arrives.

Choose the message format, transport, and framing

Three choices must agree on both ends of the connection:

  1. Message format defines the fields inside each Syslog message.
  2. Transport defines how bytes move between sender and receiver.
  3. Framing defines where one message ends and the next begins on a stream transport.

Do not infer one from another. An RFC 5424 message can be sent over UDP, TCP, or TLS. TCP does not automatically mean TLS, and choosing TCP does not tell the receiver which framing method the sender uses.

RFC 3164 and RFC 5424

RFC 3164 describes the legacy BSD-style format commonly emitted by older appliances. Its timestamp has no year or timezone, and the application tag and process ID are embedded less consistently in the message header. There is no standard structured-data block.

RFC 5424 defines a versioned header with timestamp, hostname, application name, process ID, message ID, and structured data. A pair of simplified examples shows the difference:

# RFC 3164 style
<34>Sep 15 14:07:02 edge-01 sshd[1842]: Failed password for invalid user backup

# RFC 5424 style
<34>1 2026-09-15T14:07:02-04:00 edge-01 sshd 1842 AUTH01 - Failed password for invalid user backup

Use RFC 5424 when you control the forwarder and the receiver accepts it. It carries more explicit identity and time information. Accept RFC 3164 when a device cannot emit anything else, but test how the receiver interprets missing fields. Converting a legacy message to an RFC 5424 envelope cannot reconstruct a timezone, message ID, or structured data that the original event never supplied.

UDP, TCP, and TLS

UDP sends independent datagrams without a connection or delivery acknowledgement. It has low setup overhead, but a sender normally cannot retry a specific message after packet loss or receiver congestion. Use it only where that loss model is acceptable.

TCP provides an ordered byte stream and exposes connection failure to the forwarding daemon. It still needs message framing and a queue if events must wait through an outage. A successful TCP write also does not prove that the destination indexed the event.

TLS runs over TCP and adds encryption plus certificate-based server authentication. RFC 5425 specifies Syslog over TLS with octet-counted framing. Fluxtail's dedicated Syslog receiver accepts TLS TCP only; it does not accept UDP or plain TCP. Its port is assigned to the receiver, so do not assume the conventional port 6514.

Why TCP framing matters

TCP has no message boundaries. RFC 6587 documents two common approaches:

  • Octet counting: each message is prefixed with its byte length, such as 123 <34>1 ....
  • Non-transparent framing: a delimiter, usually a newline, terminates each message.

Octet counting safely carries messages containing newlines and is the appropriate choice for the Fluxtail examples below. A framing mismatch often appears as several events merged into one row, one event split across rows, or an apparently connected sender that produces no usable messages.

Configure a Fluxtail Syslog receiver first

Create a dedicated Syslog receiver before changing a sender. Add the sender's public IPv4 address or CIDR to its source rules, wait until the endpoint is active, and copy the exact assigned hostname and port. If the sender exits through NAT, allow the translated public address seen by Fluxtail, not its private interface address.

Use the assigned hostname everywhere. It is both the network destination and the name that must match the receiver's TLS certificate. The public Fluxtail Syslog setup guide is the source of truth for the receiver requirements.

Forward with rsyslog

The following rsyslog action emits RFC 5424, uses octet-counted framing, verifies the receiver hostname, retries connection failures, and enables a bounded disk-assisted queue. It matches Fluxtail's published receiver configuration. For deeper rsyslog routing examples, see the rsyslog centralized logging guide.

# /etc/rsyslog.d/98-fluxtail.conf
global(
  DefaultNetstreamDriverCAFile="YOUR_CA_BUNDLE_PATH"
  WorkDirectory="/var/spool/rsyslog"
)

action(
  type="omfwd"
  target="YOUR_POOL_HOSTNAME"
  port="YOUR_ASSIGNED_PORT"
  protocol="tcp"
  StreamDriver="gtls"
  StreamDriverMode="1"
  StreamDriverAuthMode="x509/name"
  StreamDriverPermittedPeers="YOUR_POOL_HOSTNAME"
  TCP_Framing="octet-counted"
  template="RSYSLOG_SyslogProtocol23Format"
  action.resumeRetryCount="-1"
  queue.type="LinkedList"
  queue.filename="fluxtail"
  queue.maxdiskspace="1g"
  queue.saveOnShutdown="on"
)

Replace every uppercase placeholder. Common CA bundle paths are /etc/ssl/certs/ca-certificates.crt on Debian-family systems and /etc/pki/tls/certs/ca-bundle.crt on RHEL-family systems. Confirm the actual file and ensure the rsyslog service can write to its work directory.

The queue.filename setting makes the linked-list action queue disk-assisted, not disk-first. Low-volume records can remain in memory until spillover. queue.saveOnShutdown saves queued records during an orderly shutdown; it does not protect in-memory records from SIGKILL, an out-of-memory termination, a host crash, or power loss. The 1 GiB limit is an example bound, not a universal capacity recommendation. Size it from measured event volume, available disk, and the outage window you intend to cover. When that bound is exhausted, the sender cannot buffer indefinitely; monitor queue and disk state instead of treating retries as loss prevention.

Validate before restarting:

sudo rsyslogd -N1
sudo systemctl restart rsyslog
sudo systemctl status rsyslog --no-pager
sudo journalctl -u rsyslog -n 100 --no-pager

Package and service names can vary outside common systemd distributions. The official rsyslog omfwd documentation covers the forwarding, TLS, framing, retry, and action-queue options.

Forward with syslog-ng

With syslog-ng, use the syslog() destination rather than the network() destination when you want an RFC 5424 message and its frame header. Keep the source already defined by the distribution package, then connect it to the new destination in a log path. The syslog-ng centralized logging guide covers its source, filter, destination, and log-block model in more detail.

This current-style example uses a trusted CA file, required certificate verification, SNI, flow control, and a reliable disk buffer:

# Adapt the source name and paths to the installed package.
destination d_fluxtail {
  syslog(
    "YOUR_POOL_HOSTNAME"
    port(YOUR_ASSIGNED_PORT)
    transport("tls")
    tls(
      ca-file("YOUR_CA_BUNDLE_PATH")
      peer-verify(required-trusted)
      sni(yes)
    )
    disk-buffer(
      reliable(yes)
      capacity-bytes(1073741824)
      flow-control-window-bytes(10485760)
      dir("/var/lib/syslog-ng")
    )
  );
};

log {
  source(s_src);
  destination(d_fluxtail);
  flags(flow-control);
};

Replace s_src with the package's existing local source name. Confirm that the buffer directory exists and is writable by syslog-ng. sni(yes) requires syslog-ng 3.24 or later; upgrade older installations or use a version-supported path that you have verified rather than silently omitting SNI. The buffer option names above match current syslog-ng documentation; version 4.2 and earlier use disk-buf-size() and mem-buf-size() instead of capacity-bytes() and flow-control-window-bytes(). Check syslog-ng --version and that version's manual before copying the buffer block.

The 1 GiB capacity is an example bound, not a sizing recommendation, and reliable(yes) does not provide exactly-once delivery. When the buffer fills, syslog-ng eventually applies backpressure where the source supports flow control; datagram and other non-flow-controlled sources can still lose messages. Changing reliable() or the buffer dir() while messages remain queued can also lose or orphan them, so drain or deliberately migrate the queue before changing those settings.

Do not add a client certificate or private key unless the receiver explicitly requires mutual TLS. Fluxtail authenticates this dedicated receiver path with the allowed source IPv4/CIDR while the sender validates the server certificate.

Validate the complete configuration before restarting:

sudo syslog-ng -s
sudo systemctl restart syslog-ng
sudo systemctl status syslog-ng --no-pager
sudo journalctl -u syslog-ng -n 100 --no-pager
sudo syslog-ng-ctl stats | grep -E 'd_fluxtail|queued|dropped'

The official syslog-ng documentation explains the syslog() destination, TLS options, and disk buffering.

Preserve useful fields across the relay

Before adding a large group of senders, forward one event and compare its local and received forms. Check these values:

  • event timestamp and timezone;
  • original host rather than the relay host;
  • facility and severity;
  • application name and process ID;
  • message ID and structured data when the source provides them;
  • complete message text, including any embedded newline.

An RFC 5424 template gives those fields standard positions, but it does not make an unstructured application message structured. Parsing also depends on the sender and receiver versions. In Fluxtail, confirm the received host, application, severity, and message fields before relying on them in filters. Use the public search and filters guide for the current filter behavior.

Be deliberate when a relay receives logs from other hosts. Options that replace the message hostname with the relay's hostname can erase the original source identity. Conversely, blindly trusting an unverified hostname from an untrusted network can misattribute an event. Preserve the original value and the transport peer identity separately when the tool and receiver expose both.

Verify the forwarding path safely

First test DNS, TCP reachability, SNI, and hostname verification without disabling certificate checks:

openssl s_client \
  -connect YOUR_POOL_HOSTNAME:YOUR_ASSIGNED_PORT \
  -servername YOUR_POOL_HOSTNAME \
  -verify_hostname YOUR_POOL_HOSTNAME \
  -verify_return_error

Then send a marker through the running local daemon:

logger -p user.notice -t fluxtail-forward-test \
  'marker=syslog-forward-20260915-01'

Open the receiver's stream in Live Tail and search for the exact marker. Confirm its host, application, severity, timestamp, and message. This test proves that one event traversed the current path; it does not prove that the queue is sized correctly or that every source format parses the same way.

Test buffering separately during an approved maintenance exercise. Record the queue depth, interrupt the receiver path for a short bounded interval, send known numbered markers, restore the path, and confirm which markers arrive. Watch disk use throughout. Do not test an unbounded outage on a production sender.

Troubleshoot missing or malformed messages

Work from the receiver back toward the source:

  1. Confirm the Fluxtail endpoint is active, the hostname and assigned port are exact, and the sender's translated public IPv4 matches a source rule.
  2. Run the daemon's syntax check and inspect its service journal for TLS, permission, suspension, or queue errors.
  3. Use openssl s_client with SNI and hostname verification. A TCP connection alone does not validate the certificate.
  4. Confirm outbound TCP to the assigned port is allowed by the host, network firewall, and egress policy.
  5. Search the correct Fluxtail stream without restrictive filters, then search for the exact marker.
  6. If rows are joined, split, or absent despite a healthy TLS session, compare the sender's framing and message format with the receiver configuration.
  7. If the host, app, or severity is wrong, compare the local raw event, the outbound template, and the received fields before adding parser rules.
  8. If an outage caused a gap, inspect queue depth, disk capacity, configured limits, dropped-message counters, and daemon restarts. Retries cannot recover an event that never entered the queue or was discarded after the queue filled.

Once the known marker arrives with useful fields, expand forwarding one source class at a time. Fluxtail's Syslog server overview explains the product-level receiver and search workflow; the daemon-specific use-case pages remain the better reference for complex rsyslog or syslog-ng routing.

Create a Fluxtail account, add a dedicated Syslog receiver, and verify one sender with an exact marker before widening the source CIDR or adding more hosts.