How to Configure syslog-ng for Centralised Syslog on RHEL 7
Every Linux system generates a continuous stream of log data from the kernel, system services, and applications. On a single host, rsyslog handles this adequately, but when you need to aggregate logs from dozens or hundreds of servers into a central repository, filter them intelligently, and apply consistent formatting, a more capable tool is required. syslog-ng is a high-performance, feature-rich syslog daemon that extends the traditional syslog model with structured logging support, TLS-encrypted transport, complex filter expressions, and flexible template-based formatting. This tutorial walks through installing syslog-ng on RHEL 7, replacing rsyslog, configuring a central log server that accepts remote syslog over both UDP and TLS-encrypted TCP, and applying practical filters and templates.
Prerequisites
- Two RHEL 7 servers: one acting as the central syslog server, one as a log-sending client
- Root or sudo access on both systems
- EPEL repository enabled on both hosts (
yum install epel-release) - Basic familiarity with syslog facilities and severity levels
- For TLS transport: OpenSSL and a CA certificate (self-signed is fine for internal use)
Step 1: Install syslog-ng from EPEL
The syslog-ng package is available in the EPEL repository. Install it on both the server and the client host:
sudo yum install -y epel-release
sudo yum install -y syslog-ng syslog-ng-libdbi
Check the installed version:
syslog-ng --version
The main configuration file is /etc/syslog-ng/syslog-ng.conf. Additional configuration snippets are loaded from /etc/syslog-ng/conf.d/. It is good practice to put custom configuration into separate files under conf.d/ and leave the main file as a clean include structure.
Step 2: Understand the syslog-ng Configuration Structure
A syslog-ng configuration is composed of four types of objects wired together:
- source — defines where log messages come from (local journal, UDP socket, TCP socket, file, etc.)
- filter — defines rules for selecting a subset of messages by facility, severity, host, program name, or message content using regex
- destination — defines where to send messages (local file, remote syslog server, database, AMQP broker, etc.)
- log — wires a source to an optional filter to a destination; this is the actual routing path
The minimal structure in syslog-ng.conf is:
@version: 3.26
@include "scl.conf"
options {
chain_hostnames(off);
flush_lines(0);
use_dns(no);
use_fqdn(no);
owner("root");
group("adm");
perm(0640);
stats_freq(0);
bad_hostname("^gconfd$");
};
source s_local {
system();
internal();
};
destination d_local_all {
file("/var/log/messages");
};
log { source(s_local); destination(d_local_all); };
Step 3: Stop rsyslog and Enable syslog-ng
The two daemons conflict because they both try to read the same kernel log socket. Stop and disable rsyslog before starting syslog-ng:
sudo systemctl stop rsyslog
sudo systemctl disable rsyslog
sudo systemctl enable syslog-ng
sudo systemctl start syslog-ng
sudo systemctl status syslog-ng
Confirm syslog-ng is writing local logs:
logger -t test "syslog-ng is working"
grep "syslog-ng is working" /var/log/messages
Step 4: Configure the Central Syslog Server to Receive Remote Logs
On the server host, add sources to listen for incoming syslog messages over UDP (port 514) and TCP (port 514). Create a new file in conf.d:
sudo tee /etc/syslog-ng/conf.d/remote-receive.conf <<'EOF'
# Remote sources
source s_udp {
network(
transport("udp")
ip("0.0.0.0")
port(514)
);
};
source s_tcp {
network(
transport("tcp")
ip("0.0.0.0")
port(514)
max_connections(100)
log_iw_size(10000)
);
};
# Template to separate logs by host and date
template t_remote {
template("${ISODATE} ${HOST} ${PROGRAM}[${PID}]: ${MSG}n");
template_escape(no);
};
# Destination: per-host log files
destination d_remote_hosts {
file(
"/var/log/remote/${HOST}/${YEAR}${MONTH}${DAY}.log"
template(t_remote)
dir_perm(0750)
perm(0640)
create_dirs(yes)
);
};
# Route remote UDP and TCP logs to per-host files
log { source(s_udp); destination(d_remote_hosts); };
log { source(s_tcp); destination(d_remote_hosts); };
EOF
Open the firewall port on the server:
sudo firewall-cmd --permanent --add-port=514/tcp
sudo firewall-cmd --permanent --add-port=514/udp
sudo firewall-cmd --reload
Reload syslog-ng to apply the new configuration:
sudo systemctl reload syslog-ng
Step 5: Configure a Client Host to Forward Logs
On the RHEL 7 client, after installing and starting syslog-ng (see Step 1–3), add a destination pointing to the central server and a log path to forward all local messages:
sudo tee /etc/syslog-ng/conf.d/forward-to-server.conf <<'EOF'
destination d_central_server {
network(
"192.168.1.200"
transport("tcp")
port(514)
);
};
# Forward all local messages to the central server
log {
source(s_local);
destination(d_central_server);
};
EOF
sudo systemctl reload syslog-ng
logger -t testforward "hello from client01"
On the server, check that the forwarded message arrived:
ls /var/log/remote/
grep "hello from client01" /var/log/remote/client01/$(date +%Y%m%d).log
Step 6: Configure TLS-Encrypted Log Transport
Plain-text syslog over TCP can expose sensitive log data on the network. Secure it with TLS. First, generate a self-signed CA and server certificate on the syslog server:
sudo mkdir -p /etc/syslog-ng/tls
cd /etc/syslog-ng/tls
# Generate CA key and certificate
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
-subj "/CN=SyslogCA/O=MyOrg/C=US"
# Generate server key and CSR
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr
-subj "/CN=logserver.example.com/O=MyOrg/C=US"
# Sign the server certificate with the CA
openssl x509 -req -days 3650 -in server.csr
-CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
sudo chmod 600 /etc/syslog-ng/tls/*.key
sudo chown syslog:syslog /etc/syslog-ng/tls/
Update the server’s receive configuration to use TLS on port 6514:
sudo tee /etc/syslog-ng/conf.d/tls-receive.conf <<'EOF'
source s_tls {
network(
transport("tls")
ip("0.0.0.0")
port(6514)
max_connections(100)
tls(
key_file("/etc/syslog-ng/tls/server.key")
cert_file("/etc/syslog-ng/tls/server.crt")
ca_dir("/etc/syslog-ng/tls/")
peer_verify(optional-untrusted)
)
);
};
log { source(s_tls); destination(d_remote_hosts); };
EOF
On the client, copy ca.crt from the server, then configure TLS transport:
sudo tee /etc/syslog-ng/conf.d/forward-tls.conf <<'EOF'
destination d_central_tls {
network(
"192.168.1.200"
transport("tls")
port(6514)
tls(
ca_file("/etc/syslog-ng/tls/ca.crt")
peer_verify(required-trusted)
)
);
};
log { source(s_local); destination(d_central_tls); };
EOF
sudo firewall-cmd --permanent --add-port=6514/tcp
sudo firewall-cmd --reload
sudo systemctl reload syslog-ng
Step 7: Filter Logs by Facility and Severity
syslog-ng filters allow you to route specific log types to different destinations. The following example separates authentication logs from all other messages and routes critical errors to a dedicated file:
sudo tee /etc/syslog-ng/conf.d/filters.conf <<'EOF'
filter f_auth { facility(auth, authpriv); };
filter f_critical { level(crit..emerg); };
filter f_not_debug { level(info..emerg); };
destination d_auth { file("/var/log/secure.syslog-ng"); };
destination d_critical { file("/var/log/critical.log"); };
log { source(s_local); filter(f_auth); destination(d_auth); };
log { source(s_local); filter(f_critical); destination(d_critical); };
EOF
Step 8: Log Formatting with Templates
Templates let you customise the format of log lines written to files or sent to remote destinations. The following template produces structured JSON output compatible with log analysis tools such as Elasticsearch:
template t_json {
template("{"time":"${ISODATE}","host":"${HOST}","program":"${PROGRAM}","pid":"${PID}","facility":"${FACILITY}","severity":"${LEVEL}","message":"${MSG}"}n");
template_escape(yes);
};
destination d_json_file {
file("/var/log/syslog-ng-json.log" template(t_json));
};
log { source(s_local); filter(f_not_debug); destination(d_json_file); };
Step 9: Log Rotation Compatibility
syslog-ng works with logrotate like any other daemon. Create a logrotate configuration for your centralised log directory:
sudo tee /etc/logrotate.d/syslog-ng-remote <<'EOF'
/var/log/remote/*/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
/usr/sbin/syslog-ng-ctl reload || true
endscript
}
EOF
Test the logrotate configuration without actually rotating:
sudo logrotate --debug /etc/logrotate.d/syslog-ng-remote
Replacing rsyslog with syslog-ng on RHEL 7 opens up a much richer set of log management capabilities while maintaining full compatibility with existing syslog clients across your infrastructure. The structured configuration model of sources, filters, destinations, and log paths makes even complex routing scenarios easy to reason about and maintain. With TLS transport securing your log data in transit, per-host directory organisation keeping logs navigable, and JSON templates enabling downstream analysis in Elasticsearch or Splunk, syslog-ng provides a solid foundation for centralised logging at any scale.