OPNsense Syslog Configuration
This role configures OPNsense firewall to forward system logs to a remote Graylog server via the REST API.
OPNsense Syslog Configuration Role
Overview
This role configures OPNsense firewall to forward system logs to a remote Graylog server via the REST API. It manages syslog destinations using an idempotent approach: searching for existing configurations, creating new destinations if needed, or updating existing ones. The role applies configuration changes to activate log forwarding immediately.
Purpose
- Centralized Logging: Forward OPNsense logs to Graylog for aggregation
- Security Monitoring: Enable SIEM capabilities for firewall logs
- Troubleshooting: Centralize logs for easier debugging
- Audit Trail: Maintain searchable log history
- API-Based: Reliable automation via OPNsense REST API
- Idempotent: Safe to run multiple times, updates existing config
Requirements
- Ansible 2.9 or higher
- OPNsense firewall with API access enabled
- API key and secret stored in Ansible Vault
- Network connectivity to OPNsense (VLAN10)
- OPNsense user with syslog configuration permissions
- Graylog server with syslog input configured
- Network connectivity from OPNsense to Graylog
What is Syslog Forwarding?
Syslog forwarding sends log messages from OPNsense to a remote log server:
Without forwarding:
OPNsense → Local logs only
(Limited storage, difficult to search/analyze)
With forwarding:
OPNsense → Graylog server
(Centralized storage, powerful search, long retention)
Benefits:
- Aggregate logs from multiple systems
- Long-term storage
- Advanced search and filtering
- Alerting on log events
- Compliance and auditing
Role Variables
Required Variables
| Variable | Required | Description |
|---|---|---|
vault_opnsense_bjoffrey_user_api_key | Yes | OPNsense API key (in vault) |
vault_opnsense_bjoffrey_user_api_secret | Yes | OPNsense API secret (in vault) |
Optional Variables
| Variable | Default | Description |
|---|---|---|
opnsense_syslog_configuration_server_ip | hostvars['graylog']['ip_vlan12'] | Graylog server IP |
opnsense_syslog_configuration_server_port | 514 | Syslog port (UDP/TCP) |
opnsense_syslog_configuration_transport | udp4 | Transport protocol |
opnsense_syslog_configuration_levels | alert,crit,emerg,err,info,notice,warn | Log severity levels |
opnsense_syslog_configuration_validate_certs | true | Validate SSL certificates |
Variable Details
opnsense_syslog_configuration_server_ip
IP address of the Graylog server to receive logs.
Default: "{{ hostvars['graylog']['ip_vlan12'] }}"
Example: "192.168.x.x"
opnsense_syslog_configuration_server_port
UDP or TCP port for syslog.
Default: 514 (standard syslog port)
Common values:
514: Standard syslog (UDP/TCP)1514: Alternative port6514: Syslog over TLS
opnsense_syslog_configuration_transport
Network transport protocol.
Default: udp4
Values:
udp4: UDP over IPv4 (most common)tcp4: TCP over IPv4 (reliable delivery)udp6: UDP over IPv6tcp6: TCP over IPv6
UDP vs TCP:
- UDP: Faster, lower overhead, may lose packets
- TCP: Reliable, guaranteed delivery, slightly slower
opnsense_syslog_configuration_levels
Which log severity levels to forward.
Default: "alert,crit,emerg,err,info,notice,warn"
Severity levels (most to least severe):
emerg: Emergency (system unusable)alert: Alert (immediate action required)crit: Criticalerr: Errorwarn: Warningnotice: Noticeinfo: Informationaldebug: Debug (very verbose)
Typical configurations:
# All except debug
levels: "alert,crit,emerg,err,info,notice,warn"
# Errors and above only
levels: "alert,crit,emerg,err"
# Everything including debug
levels: "alert,crit,debug,emerg,err,info,notice,warn"
Dependencies
This role has no dependencies on other Ansible roles, but requires:
- OPNsense firewall with API enabled
- Graylog server with syslog input configured
- Network connectivity between OPNsense and Graylog
- API key with syslog management permissions
- Ansible Vault for storing API credentials
Example Playbook
Basic Usage
---
- name: Configure OPNsense Syslog Forwarding
hosts: mint-vm
gather_facts: false
roles:
- opnsense_syslog_configuration
Custom Graylog Server
---
- name: Configure Syslog to Custom Server
hosts: mint-vm
gather_facts: false
vars:
opnsense_syslog_configuration_server_ip: "192.168.x.x"
opnsense_syslog_configuration_server_port: 1514
roles:
- opnsense_syslog_configuration
TCP Transport
---
- name: Configure Syslog with TCP
hosts: mint-vm
gather_facts: false
vars:
opnsense_syslog_configuration_transport: tcp4
roles:
- opnsense_syslog_configuration
Error-Level Logs Only
---
- name: Configure Syslog for Errors Only
hosts: mint-vm
gather_facts: false
vars:
opnsense_syslog_configuration_levels: "alert,crit,emerg,err"
roles:
- opnsense_syslog_configuration
What This Role Does
-
Search for existing syslog destination:
- Calls API:
/api/syslog/settings/searchDestinations - Filters by: Server IP and port
- Determines: Create new or update existing
- Calls API:
-
If no existing destination found:
- Creates new destination via
/api/syslog/settings/addDestination - Configures: IP, port, transport, log levels
- Creates new destination via
-
If existing destination found:
- Updates destination via
/api/syslog/settings/setDestination/{uuid} - Ensures: Configuration matches desired state
- Updates destination via
-
Apply configuration:
- Reconfigures service via
/api/syslog/service/reconfigure - Activates changes immediately
- Starts forwarding logs to Graylog
- Reconfigures service via
OPNsense API Endpoints
Search Syslog Destinations
POST /api/syslog/settings/searchDestinations
Authorization: Basic (API key:secret)
Content-Type: application/json
Request body:
{
"current": 1,
"rowCount": -1,
"searchPhrase": ""
}
Response:
{
"rows": [
{
"uuid": "12345678-1234-1234-1234-123456789abc",
"enabled": "1",
"transport": "udp4",
"hostname": "192.168.x.x",
"port": "514",
"level": "alert,crit,emerg,err,info,notice,warn"
}
],
"rowCount": 1,
"total": 1
}
Add Syslog Destination
POST /api/syslog/settings/addDestination
Authorization: Basic (API key:secret)
Content-Type: application/json
Request body:
{
"destination": {
"enabled": "1",
"transport": "udp4",
"hostname": "192.168.x.x",
"port": "514",
"level": "alert,crit,emerg,err,info,notice,warn",
"description": "Graylog Server"
}
}
Response:
{
"result": "saved",
"uuid": "12345678-1234-1234-1234-123456789abc"
}
Update Syslog Destination
POST /api/syslog/settings/setDestination/{uuid}
Authorization: Basic (API key:secret)
Content-Type: application/json
Request body: Same as addDestination
Apply Configuration
POST /api/syslog/service/reconfigure
Applies pending syslog configuration changes and restarts service.
Syslog Message Format
Standard syslog message:
<priority>timestamp hostname process[pid]: message
Example:
<30>Jan 08 10:30:45 opnsense filterlog[1234]: BLOCK eth0 IN TCP 192.168.x.x:50123 -> 192.168.x.x:22
Priority calculation:
priority = (facility * 8) + severity
OPNsense facilities:
local0-local7: Custom applicationsauth: Authenticationdaemon: System daemonskern: Kernel messages
Firewall Log Format
OPNsense filterlog format:
action,interface,direction,protocol,src_ip:src_port,dst_ip:dst_port,rule_num
Example:
BLOCK,vlan18,in,TCP,192.168.x.x:50123,192.168.x.x:22,rule:5
Graylog parsing: Use extractors to parse filterlog messages.
Idempotency
Role is fully idempotent:
- First run: Creates syslog destination, reports
changed - Subsequent runs:
- Finds existing destination (search by IP:port)
- Compares configuration
- Updates only if different
- Reports
okif no changes needed
Safe to run repeatedly without creating duplicate destinations.
How Idempotency Works
# Step 1: Search for existing destination
POST /api/syslog/settings/searchDestinations
# Step 2a: If not found, create new
POST /api/syslog/settings/addDestination
# Step 2b: If found, update existing
POST /api/syslog/settings/setDestination/{uuid}
# Step 3: Apply changes (only if changed)
POST /api/syslog/service/reconfigure
Key logic:
{% if destination_exists %}
Update existing (setDestination)
{% else %}
Create new (addDestination)
{% endif %}
Security Considerations
- API Credentials: Stored in Ansible Vault
- HTTPS: Uses SSL/TLS for API calls
- Basic Auth: API key/secret authentication
- Certificate Validation: Enabled by default
- Unencrypted Logs: Standard syslog (UDP/TCP) is unencrypted
- Consider syslog over TLS (port 6514) for sensitive environments
- Network Security: Ensure firewall rules allow OPNsense → Graylog
- Log Privacy: Logs may contain sensitive information
Network Requirements
Firewall rules needed:
# Allow OPNsense to reach Graylog on syslog port
- action: pass
interface: vlan12
source_net: opnsense_vlan12_ip
destination_net: graylog_server_ip
destination_port: "514"
protocol: udp
description: "Allow OPNsense syslog to Graylog"
Test connectivity:
# From OPNsense (Diagnostics → Ping)
ping 192.168.x.x
# Test UDP port (via nc)
nc -u 192.168.x.x 514
Graylog Configuration
Graylog must have syslog input configured:
-
Create syslog input:
- System → Inputs
- Select “Syslog UDP” or “Syslog TCP”
- Bind address:
0.0.0.0or specific IP - Port:
514 - Save
-
Configure extractors (optional):
- Parse filterlog messages
- Extract fields: action, interface, src_ip, dst_ip, etc.
- Enables better searching/dashboards
-
Test:
- Search → Last 5 minutes
- Filter:
source:opnsense
Tags
This role does not define any tags. Use playbook-level tags if needed:
- hosts: mint-vm
roles:
- opnsense_syslog_configuration
tags:
- opnsense
- syslog
- logging
- monitoring
Notes
become: falserecommended (no root needed)- Idempotent: Safe to run multiple times
- Searches for existing destination by IP:port combination
- Creates or updates as needed
- Only applies configuration if changes were made
- Logs start flowing immediately after reconfigure
Troubleshooting
”Authentication failed” errors
Cause: Invalid API key/secret
Solution: Verify credentials in vault.
ansible-vault view group_vars/all/vault.yml
Logs not appearing in Graylog
Check OPNsense syslog config:
- OPNsense UI → System → Settings → Logging / Targets
- Verify destination exists and is enabled
- Check IP, port, transport match Graylog
Check Graylog input:
- System → Inputs
- Verify input is running (green)
- Check “Show received messages”
Test connectivity:
# From OPNsense: Diagnostics → Ping
ping <graylog-ip>
# Check firewall rules allow traffic
# Firewall → Rules → VLAN12 (or OPNsense interface)
Check Graylog logs:
# On Graylog server
tail -f /var/log/graylog-server/server.log
“Connection refused” errors
Cause: Graylog not listening on syslog port
Solution:
# Check Graylog listening
netstat -uln | grep 514
# Restart Graylog input
# System → Inputs → [Restart input]
Duplicate log entries
Cause: Multiple syslog destinations configured
Solution:
- OPNsense → System → Settings → Logging / Targets
- Remove duplicate destinations
- Run role again to ensure single destination
Wrong log levels
Cause: Log level filter too restrictive
Solution: Update levels variable:
opnsense_syslog_configuration_levels: "alert,crit,debug,emerg,err,info,notice,warn"
Testing the Role
Verify Destination Created
Via OPNsense UI:
- Log into OPNsense
- System → Settings → Logging / Targets
- Should see Graylog destination
Via API:
curl -u "key:secret" -X POST \
https://opnsense-ip/api/syslog/settings/searchDestinations \
-H "Content-Type: application/json" \
-d '{"current":1,"rowCount":-1}' | jq
Test Log Forwarding
Generate test log:
# Via OPNsense SSH
logger -t test "Test message from OPNsense"
Check in Graylog:
- Search → Last 5 minutes
- Query:
source:opnsense AND test - Should see test message
Monitor Firewall Logs
Trigger firewall log event:
# From blocked network, try to connect to allowed network
# Should generate block log
Check Graylog:
# Search for filterlog messages
source:opnsense AND filterlog
Best Practices
- Use UDP for high-volume: TCP overhead can impact performance
- Filter log levels: Don’t forward debug unless needed
- Monitor Graylog disk: Firewall logs can be high volume
- Configure retention: Set appropriate retention policy in Graylog
- Create extractors: Parse filterlog messages for better analysis
- Set up alerts: Alert on critical firewall events
- Regular testing: Verify logs flowing after OPNsense updates
- Backup Graylog: Include Graylog in backup strategy
- Network isolation: Ensure Graylog on trusted network
- Document parsers: Document custom extractors/parsing rules
Log Volume Considerations
OPNsense can generate significant logs:
- Firewall blocks (especially from internet)
- DHCP events
- VPN connections
- System events
High-traffic networks: 1GB+ logs per day
Graylog sizing:
- Plan disk space for retention period
- Example: 1GB/day × 30 days = 30GB minimum
- Add 50% buffer for growth
Retention policy:
# Graylog index retention
System → Indices → [Default index set]
- Rotation strategy: Size-based (5GB)
- Retention strategy: Delete (30 indices)
Log Message Examples
Firewall block:
filterlog: 5,,,0,vlan18,match,block,in,4,0x0,,64,0,0,DF,6,tcp,60,192.168.x.x,192.168.x.x,50123,22,0,S,1234567890,,64240,,mss
VPN connection:
openvpn: peer connection initiated with [AF_INET]1.2.3.4:12345
DHCP lease:
dhcpd: DHCPACK on 192.168.x.x to aa:bb:cc:dd:ee:ff via vlan14
Related Roles
This role is often used with:
- opnsense_firewall: Configure firewall rules
- opnsense_aliases: Create firewall aliases
- opnsense_source_nat: Configure SNAT rules
- opnsense_destination_nat: Configure DNAT rules
License
MIT
Author
Created for homelab infrastructure management.