Syslog Integration
Collect logs from Proxmox, VMware ESXi, firewalls, routers, and any device that supports syslog. Perfect for home labs and infrastructure monitoring.
Home Lab Ready
This guide is based on real-world configurations tested with Proxmox, ESXi, UniFi, and various network devices. Works with both RFC 3164 (traditional) and RFC 5424 (modern) syslog formats.
Overview
LogTide can receive syslog messages via Fluent Bit, which acts as a syslog server listening on port 514 (UDP/TCP). This allows you to centralize logs from:
- • Proxmox VE
- • VMware ESXi
- • XCP-ng
- • Linux servers (rsyslog/syslog-ng)
- • TrueNAS / FreeNAS
- • UniFi (UDM, switches, APs)
- • pfSense / OPNsense
- • MikroTik routers
- • Cisco switches/routers
- • Synology NAS
Fluent Bit Configuration
Add syslog inputs to your Fluent Bit configuration. Create these files
in your LogTide directory alongside docker-compose.yml.
fluent-bit.conf
Complete configuration with Docker logs AND syslog support:
# Fluent Bit Configuration for LogTide
# Supports Docker container logs AND syslog from network devices
[SERVICE]
Flush 5
Daemon Off
Log_Level info
Parsers_File /fluent-bit/etc/parsers.conf
# =============================================================================
# INPUT - Docker Container Logs
# =============================================================================
[INPUT]
Name tail
Path /var/lib/docker/containers/*/*.log
Parser docker
Tag docker.*
Refresh_Interval 5
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Path_Key filepath
# =============================================================================
# INPUT - Syslog (UDP) - Port 514
# =============================================================================
# Receive syslog messages on UDP (Proxmox, ESXi, firewalls, etc.)
[INPUT]
Name syslog
Parser syslog-rfc3164
Listen 0.0.0.0
Port 514
Mode udp
Tag syslog.udp
# =============================================================================
# INPUT - Syslog (TCP) - Port 514
# =============================================================================
# TCP is more reliable for important logs
[INPUT]
Name syslog
Parser syslog-rfc3164
Listen 0.0.0.0
Port 514
Mode tcp
Tag syslog.tcp
# =============================================================================
# FILTER - Docker Logs Processing
# =============================================================================
[FILTER]
Name parser
Match docker.*
Key_Name log
Parser docker_json
Reserve_Data On
Preserve_Key On
[FILTER]
Name lua
Match docker.*
script /fluent-bit/etc/extract_container_id.lua
call extract_container_id
[FILTER]
Name modify
Match docker.*
Add level info
Rename log message
Copy container_name service
[FILTER]
Name record_modifier
Match docker.*
Remove_key stream
Remove_key filepath
Remove_key container_name
# =============================================================================
# FILTER - Syslog Processing
# =============================================================================
[FILTER]
Name modify
Match syslog.*
Copy ident service
Add level info
# Map syslog severity to log level
[FILTER]
Name lua
Match syslog.*
script /fluent-bit/etc/map_syslog_level.lua
call map_syslog_level
[FILTER]
Name record_modifier
Match syslog.*
Remove_key pri
Remove_key ident
Remove_key pid
# =============================================================================
# OUTPUT - Send to LogTide API
# =============================================================================
[OUTPUT]
Name http
Match docker.*
Host ${LOGTIDE_API_HOST}
Port 8080
URI /api/v1/ingest/single
Format json_lines
Header X-API-Key ${LOGTIDE_API_KEY}
Header Content-Type application/json
Json_date_key time
Json_date_format iso8601
Retry_Limit 3
tls Off
[OUTPUT]
Name http
Match syslog.*
Host ${LOGTIDE_API_HOST}
Port 8080
URI /api/v1/ingest/single
Format json_lines
Header X-API-Key ${LOGTIDE_API_KEY}
Header Content-Type application/json
Json_date_key time
Json_date_format iso8601
Retry_Limit 3
tls Off parsers.conf
Parser definitions for Docker and both syslog formats:
# Fluent Bit Parsers Configuration
# =============================================================================
# PARSERS - Docker
# =============================================================================
[PARSER]
Name docker_json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
# =============================================================================
# PARSERS - Syslog
# =============================================================================
# RFC 3164 - Traditional syslog format
# Used by: Proxmox, many Linux systems, older network devices
# IMPORTANT: RFC 3164 does NOT include timezone info in timestamps!
# Set Time_Offset to your local timezone offset (e.g., +0100 for CET, +0200 for CEST)
[PARSER]
Name syslog-rfc3164
Format regex
Regex /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
Time_Key time
Time_Format %b %d %H:%M:%S
Time_Offset +0100
Time_Keep On
# RFC 5424 - Modern syslog format
# Used by: Modern Linux systems, VMware ESXi, some firewalls
[PARSER]
Name syslog-rfc5424
Format regex
Regex /^\<(?<pri>[0-9]{1,5})\>1 (?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[.*]|-)) (?<message>.+)$/
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On map_syslog_level.lua
Lua script to convert syslog severity (0-7) to log levels. Note: LogTide automatically normalizes syslog levels server-side, so you can send levels like "notice", "emergency", "warning" etc. and they will be mapped to LogTide's 5 levels (debug, info, warn, error, critical).
-- Map syslog priority/severity to log level
-- Syslog severity levels (from RFC 3164/5424):
-- 0 = Emergency, 1 = Alert, 2 = Critical, 3 = Error
-- 4 = Warning, 5 = Notice, 6 = Informational, 7 = Debug
--
-- LogTide automatically maps these to its 5 levels:
-- emergency/alert/critical -> critical
-- error -> error
-- warning -> warn
-- notice/info -> info
-- debug -> debug
--
-- TIMEZONE FIX for RFC 3164:
-- RFC 3164 timestamps don't include timezone info.
-- Set SYSLOG_TZ_OFFSET env var to your timezone offset in hours.
-- Examples: SYSLOG_TZ_OFFSET=1 (CET), SYSLOG_TZ_OFFSET=2 (CEST), SYSLOG_TZ_OFFSET=-5 (EST)
-- Read timezone offset from environment (in hours, e.g., 1 for CET, 2 for CEST)
local tz_offset_hours = tonumber(os.getenv("SYSLOG_TZ_OFFSET")) or 0
local tz_offset_seconds = tz_offset_hours * 3600
function map_syslog_level(tag, timestamp, record)
local pri = tonumber(record["pri"])
if pri then
-- Extract severity from priority (severity = pri % 8)
local severity = pri % 8
-- Map severity number to log level string
-- LogTide will normalize these to its 5 levels
local level_map = {
[0] = "emergency",
[1] = "alert",
[2] = "critical",
[3] = "error",
[4] = "warning",
[5] = "notice",
[6] = "info",
[7] = "debug"
}
record["level"] = level_map[severity] or "info"
else
record["level"] = "info"
end
-- Apply timezone offset for RFC 3164 (which lacks timezone info)
-- The offset converts local time to UTC
local adjusted_timestamp = timestamp - tz_offset_seconds
-- Set 'time' field in ISO8601 format (UTC)
record["time"] = os.date("!%Y-%m-%dT%H:%M:%SZ", adjusted_timestamp)
-- Keep hostname from syslog
if record["host"] and record["host"] ~= "-" then
record["hostname"] = record["host"]
end
-- Use ident (program name) as service if available
if not record["service"] and record["ident"] and record["ident"] ~= "-" then
record["service"] = record["ident"]
elseif not record["service"] and record["hostname"] then
record["service"] = record["hostname"]
else
record["service"] = "syslog"
end
-- Clean up fields
record["pri"] = nil
record["ident"] = nil
record["host"] = nil
return 1, adjusted_timestamp, record
end extract_container_id.lua
Lua script to extract container ID from Docker log paths:
-- Extract container ID from Docker log filepath
-- Path format: /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
function extract_container_id(tag, timestamp, record)
local filepath = record["filepath"]
if filepath then
local container_id = filepath:match("/var/lib/docker/containers/([^/]+)/", 1)
if container_id then
record["container_id"] = container_id
record["container_short_id"] = container_id:sub(1, 12)
end
end
return 1, timestamp, record
end Docker Compose Setup
The default LogTide docker-compose.yml already includes
Fluent Bit with syslog support. It uses Docker Compose profiles, so it doesn't start by default.
Enable Fluent Bit with Docker Profiles
Fluent Bit is configured with profiles: [logging]
so it doesn't start by default. To enable it:
# Option 1: Start with profile flag
docker compose --profile logging up -d
# Option 2: Add to your .env file (recommended)
COMPOSE_PROFILES=logging Required: Set FLUENT_BIT_API_KEY
Fluent Bit needs an API key to send logs to LogTide. Before starting:
- Create a project in LogTide dashboard (or use an existing one)
- Go to Project Settings → API Keys → Generate new key
- Add to your
.envfile:
FLUENT_BIT_API_KEY=lp_your_api_key_here Fluent Bit Configuration in docker-compose.yml
Here's the Fluent Bit service configuration (already included in the default compose file):
fluent-bit:
image: fluent/fluent-bit:4.2.2 # For ARM64: cr.fluentbit.io/fluent/fluent-bit:4.2.2
container_name: logtide-fluent-bit
profiles:
- logging # Only starts with --profile logging or COMPOSE_PROFILES=logging
ports:
- "514:514/udp" # Syslog UDP
- "514:514/tcp" # Syslog TCP
volumes:
# Configuration files
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
- ./parsers.conf:/fluent-bit/etc/parsers.conf:ro
# Lua scripts
- ./extract_container_id.lua:/fluent-bit/etc/extract_container_id.lua:ro
- ./map_syslog_level.lua:/fluent-bit/etc/map_syslog_level.lua:ro
- ./wrap_logs.lua:/fluent-bit/etc/wrap_logs.lua:ro
# Docker logs access
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LOGTIDE_API_KEY: ${FLUENT_BIT_API_KEY}
LOGTIDE_API_HOST: backend
SYSLOG_TZ_OFFSET: ${SYSLOG_TZ_OFFSET:-0} # Timezone offset for RFC3164
depends_on:
- backend
restart: unless-stopped Port 514 Requires Root
Port 514 is a privileged port. If running Docker without root, use a higher port (e.g., 5514) and configure your devices to send to that port instead.
Proxmox VE Setup
Configure Proxmox to send syslog messages to LogTide via rsyslog:
1. Install rsyslog (if not installed)
apt install rsyslog -y 2. Create rsyslog configuration
Create /etc/rsyslog.d/50-logtide.conf:
# Replace with your LogTide server IP
*.* @@10.0.0.100:514
Use @@ for TCP (recommended) or @ for UDP.
3. Restart rsyslog
systemctl restart rsyslog
systemctl status rsyslog 4. Test the connection
logger -t proxmox-test "Test log from Proxmox to LogTide" Check LogTide - you should see the test message with service "proxmox-test".
VMware ESXi Setup
Configure ESXi to forward syslog to LogTide:
Via Web UI (vSphere Client)
- Navigate to Host → Manage → System → Advanced Settings
- Find
Syslog.global.logHost - Set value to:
udp://YOUR_LOGTIDE_IP:514ortcp://YOUR_LOGTIDE_IP:514 - Click Save
Via SSH/CLI
# Enable SSH on ESXi first, then:
esxcli system syslog config set --loghost='tcp://10.0.0.100:514'
esxcli system syslog reload ESXi Firewall
You may need to enable the syslog firewall rule:
esxcli network firewall ruleset set --ruleset-id=syslog --enabled=true
Other Devices
UniFi (UDM/USG)
- Go to Settings → System → Remote Logging
- Enable Remote Syslog Server
- Enter your LogTide server IP and port 514
- Select log level (Info recommended)
pfSense / OPNsense
- Go to Status → System Logs → Settings
- Check Enable Remote Logging
- Enter your LogTide server IP in Remote log servers
- Select which logs to send (firewall, system, etc.)
Linux Servers (rsyslog)
Same as Proxmox - create /etc/rsyslog.d/50-logtide.conf:
# Forward all logs to LogTide (TCP)
*.* @@YOUR_LOGTIDE_IP:514
# Or forward only specific facilities/severities:
# auth,authpriv.* @@YOUR_LOGTIDE_IP:514 # Auth logs only
# *.err @@YOUR_LOGTIDE_IP:514 # Errors and above only Synology NAS
- Go to Control Panel → Log Center → Log Sending
- Check Send logs to a syslog server
- Enter your LogTide server IP
- Select format: BSD (RFC 3164) or IETF (RFC 5424)
Multi-Server Setup
When collecting syslog from multiple servers, you may want to distinguish logs by source or apply different parsing rules per server.
Separating Logs by Server
By default, syslog logs use the ident field (program name) as the service name, with hostname as fallback. You have two options to separate servers:
Create a separate LogTide project for each server or server group:
- Create projects: "unraid-01", "proxmox-cluster", "network-devices", etc.
- Generate an API key for each project
- Run separate Fluent Bit instances with different API keys, or use routing rules
This provides full isolation with separate dashboards and alert rules per server.
Modify map_syslog_level.lua to use hostname as service:
-- Change the service assignment logic in map_syslog_level.lua:
if record["host"] and record["host"] ~= "-" then
record["service"] = record["host"] -- Use hostname as service
elseif record["ident"] and record["ident"] ~= "-" then
record["service"] = record["ident"]
else
record["service"] = "syslog"
end This way logs from unraid-01 will appear with service="unraid-01".
Per-Server Custom Parsing
Some devices (like Unraid) may not follow standard RFC3164 format exactly. You can route logs from different servers through different parsers.
Assign different ports to different servers and apply custom parsers:
# fluent-bit.conf - Unraid on port 5514
[INPUT]
Name syslog
Parser syslog-unraid # Custom parser
Listen 0.0.0.0
Port 5514
Mode udp
Tag syslog.unraid
# Proxmox on port 5515 (standard format)
[INPUT]
Name syslog
Parser syslog-rfc3164
Listen 0.0.0.0
Port 5515
Mode udp
Tag syslog.proxmox
Don't forget to expose additional ports in docker-compose.yml:
- "5514:5514/udp"
If all devices must use port 514, use Fluent Bit's rewrite_tag filter:
# Rewrite tag based on hostname pattern
[FILTER]
Name rewrite_tag
Match syslog.*
Rule $host ^unraid.* syslog.unraid false
Rule $host ^proxmox.* syslog.proxmox false
Rule $host ^pfsense.* syslog.firewall false
# Apply Unraid-specific processing
[FILTER]
Name lua
Match syslog.unraid
script /fluent-bit/etc/parse_unraid.lua
call parse_unraid
# Apply standard processing to Proxmox
[FILTER]
Name lua
Match syslog.proxmox
script /fluent-bit/etc/map_syslog_level.lua
call map_syslog_level Add to parsers.conf:
# Custom parser for Unraid syslog format
[PARSER]
Name syslog-unraid
Format regex
Regex ^(?<time>[A-Z][a-z]{2} [ ]?[0-9]{1,2} [0-9:]+) (?<host>[^ ]+) (?<ident>[^:]+): (?<message>.*)$
Time_Key time
Time_Format %b %d %H:%M:%S
Time_Keep On Rsyslog HTTP Forwarding (Advanced)
Known Limitation: omhttp Module
The rsyslog omhttp module (for sending logs directly via HTTP)
is not available in default rsyslog packages on many distributions,
including Debian 13 (Trixie), Ubuntu, and some RHEL-based systems. This is a
known upstream limitation, not a LogTide issue.
If you need to send syslog messages directly to LogTide's HTTP API without using Fluent Bit's syslog input, you have several options:
Option 1: Use Fluent Bit (Recommended)
The simplest solution is to use Fluent Bit as described in this guide. Fluent Bit receives syslog messages on port 514 and forwards them to LogTide's HTTP API. This is the recommended approach.
Option 2: Vector as HTTP Bridge
Vector is a high-performance observability data pipeline that can act as a syslog-to-HTTP bridge:
# Install Vector (Debian/Ubuntu)
curl --proto '=https' --tlsv1.2 -sSf https://sh.vector.dev | bash
# Or via apt
curl -1sLf 'https://repositories.timber.io/public/vector/cfg/setup/bash.deb.sh' | sudo bash
sudo apt install vector
Create /etc/vector/vector.toml:
# Vector configuration for rsyslog → LogTide
[sources.rsyslog]
type = "syslog"
address = "0.0.0.0:514"
mode = "tcp" # or "udp"
[transforms.format_logs]
type = "remap"
inputs = ["rsyslog"]
source = '''
# Transform syslog fields to LogTide format
.message = string!(.message)
.level = downcase(string(.severity) ?? "info")
.service = string(.appname) ?? string(.hostname) ?? "syslog"
.time = now()
# Add metadata
.metadata = {}
.metadata.hostname = string(.hostname) ?? null
.metadata.facility = string(.facility) ?? null
.metadata.procid = string(.procid) ?? null
# Remove original syslog fields
del(.severity)
del(.appname)
del(.hostname)
del(.facility)
del(.procid)
'''
[sinks.logtide]
type = "http"
inputs = ["format_logs"]
uri = "http://YOUR_LOGTIDE_HOST:8080/api/v1/ingest/single"
encoding.codec = "json"
[sinks.logtide.request]
headers.X-API-Key = "lp_your_api_key_here"
headers.Content-Type = "application/json" # Start Vector
sudo systemctl enable vector
sudo systemctl start vector
# Check status
sudo systemctl status vector
vector --version Option 3: Build rsyslog with omhttp
If you need native rsyslog HTTP support, you can compile rsyslog from source with the omhttp module enabled. This requires development libraries and is more complex to maintain:
# Install build dependencies (Debian/Ubuntu)
sudo apt install build-essential pkg-config libestr-dev libfastjson-dev zlib1g-dev libcurl4-openssl-dev uuid-dev libgcrypt20-dev
# Download and compile rsyslog
wget https://www.rsyslog.com/files/download/rsyslog/rsyslog-8.2312.0.tar.gz
tar xzf rsyslog-8.2312.0.tar.gz
cd rsyslog-8.2312.0
./configure --enable-omhttp
make
sudo make install Note: Building from source means you're responsible for security updates and compatibility. The Fluent Bit or Vector approaches are generally preferred.
Option 4: Use omfwd + Local HTTP Forwarder
Forward syslog to a local Fluent Bit or Vector instance using standard
rsyslog forwarding (omfwd), then let that service handle HTTP:
# /etc/rsyslog.d/50-logtide.conf
# Forward all logs to local Fluent Bit syslog input
*.* @@127.0.0.1:5514 This keeps your rsyslog configuration simple and delegates HTTP complexity to a dedicated tool.
Troubleshooting
Syslog messages not appearing?
-
Verify Fluent Bit is running:
docker compose ps fluent-bit -
Check Fluent Bit logs:
docker compose logs fluent-bit -
Test connectivity from source:
nc -zv YOUR_LOGTIDE_IP 514 - Check firewall allows port 514 (TCP/UDP)
-
Verify API key is set in
.env:FLUENT_BIT_API_KEY=lp_...
Test syslog manually
Send a test syslog message using netcat:
# UDP test
echo "<14>Test syslog message from terminal" | nc -u -w1 YOUR_LOGTIDE_IP 514
# TCP test
echo "<14>Test syslog message from terminal" | nc -w1 YOUR_LOGTIDE_IP 514 Service name shows as "syslog"?
The service name comes from the syslog "ident" field (program name). If your device doesn't send an ident, the hostname will be used. You can customize the Lua script to set service names based on hostname patterns.
RFC 3164 timestamps are wrong (off by hours)?
RFC 3164 syslog format does NOT include timezone information in timestamps.
If your logs show incorrect times, set the SYSLOG_TZ_OFFSET
environment variable on your Fluent Bit container.
Quick fix: Add this to your docker-compose.yml:
services:
fluent-bit:
environment:
- SYSLOG_TZ_OFFSET=1 # CET (Central European Time)
# - SYSLOG_TZ_OFFSET=2 # CEST (Summer time)
# - SYSLOG_TZ_OFFSET=-5 # EST (Eastern Standard Time) Alternative: You can also set Time_Offset directly
in the parser configuration (parsers.conf):
[PARSER]
Name syslog-rfc3164
...
Time_Format %b %d %H:%M:%S
Time_Offset +0100 # For CET
Time_Keep On Note: RFC 5424 includes timezone in the timestamp
(e.g., 2025-12-23T16:51:02+01:00) and doesn't need this fix.
Consider configuring your devices to use RFC 5424 format if possible.
Security Detection with Sigma Rules
Once syslog is flowing into LogTide, you can use Sigma rules to detect security threats. LogTide supports the industry-standard Sigma format for log detection rules.
title: SSH Authentication Failure
status: stable
logsource:
product: linux
service: sshd
detection:
selection:
message|contains:
- 'Failed password'
- 'authentication failure'
condition: selection
level: medium Learn more about Sigma rules in the API documentation.
You're All Set!
Your infrastructure logs are now flowing into LogTide. Use the search and filter features to explore your logs, set up alerts for important events, and enable Sigma rules for security monitoring.
This guide was inspired by Brandon Lee's excellent article "LogTide Is the Lightweight Syslog Server Every Home Lab Needs in 2025" on VirtualizationHowto.