Who this is for: Security engineers and n8n administrators who need reliable audit trails for breach detection and forensic analysis. We cover this in detail in the n8n Security & Hardening Guide.
Quick Diagnosis
If you cannot answer who triggered a workflow, what data was moved, or when a suspicious action occurred, your n8n instance lacks sufficient audit logging. This blind spot blocks early breach detection and hampers investigations.
1. n8n’s Native Logging Architecture
If you encounter any docker container misconfigurations resolve them before continuing with the setup.
| Component | Default Output | Level | Typical Use‑Case |
|---|---|---|---|
| Execution Logger | ~/.n8n/.n8n.log (or Docker stdout) | info | Tracks workflow start/end, node inputs/outputs (redacted). |
| Error Logger | Same file | error | Captures uncaught exceptions, node failures. |
| Database Audits | SQLite/PostgreSQL tables (execution_entity) | N/A | Stores execution metadata (workflowId, startedAt, finishedAt, status). |
EEFA note: The default logger does not retain request‑origin IPs or user identifiers when n8n runs behind a reverse proxy. Without explicit enrichment, you lose the key data needed for breach detection.
2. Enabling Detailed Audit Logs
2.1. Raise the Log Level
Set a more verbose level to capture node inputs before redaction.
# .env LOG_LEVEL=debug # captures node inputs before redaction LOG_OUTPUT=console # use 'file' for persistent logs LOG_FILE_PATH=/var/log/n8n/audit.log
2.2. Enrich Logs with User & IP Context
n8n does not attach request metadata automatically. Add a custom Express middleware that injects req.ip and req.user.id into every log entry.
// middleware/requestLogger.js
module.exports = function requestLogger() {
return (req, res, next) => {
const userId = req.session?.user?.id ?? 'anonymous';
req.log = req.log.child({ ip: req.ip, userId });
next();
};
};
Register the middleware in Docker:
# docker-compose.yml (excerpt)
services:
n8n:
image: n8nio/n8n
environment:
- N8N_CUSTOM_MIDDLEWARE=/usr/src/app/custom-middleware/requestLogger.js
volumes:
- ./custom-middleware:/usr/src/app/custom-middleware
EEFA: Custom middleware requires compatible node_modules. Re‑build the image after adding new packages. If you encounter any rbac pitfalls resolve them before continuing with the setup.
2.3. Persist Logs with Rotation
Run a lightweight Logrotate container to keep log files manageable.
# docker-compose.yml (logrotate service)
services:
logrotate:
image: blacklabelops/logrotate
volumes:
- ./logs:/var/log/n8n
environment:
- LOGROTATE_CRON=0 0 * * *
- LOGROTATE_SIZE=100M
- LOGROTATE_KEEP=7
3. Exporting Logs to External Systems
3.1. Syslog (RFC 5424)
Configure n8n to send JSON logs to a remote syslog collector.
# .env LOG_OUTPUT=syslog SYSLOG_HOST=logstash.example.com SYSLOG_PORT=514 SYSLOG_PROTOCOL=udp
3.2. HTTP (JSON) – Ideal for Cloud SIEMs
Set up HTTP transport for direct ingestion.
# .env
LOG_OUTPUT=http
HTTP_LOG_URL=https://siem.example.com/ingest
HTTP_LOG_METHOD=POST
HTTP_LOG_HEADERS=Authorization:Bearer ${SIEM_TOKEN}
If you prefer a dedicated shipper, use the snippet below.
// logger/httpTransport.js (part 1)
const axios = require('axios');
module.exports = (log) => {
axios.post(process.env.HTTP_LOG_URL, log, {
headers: {
Authorization: `Bearer ${process.env.SIEM_TOKEN}`,
'Content-Type': 'application/json',
},
})
// logger/httpTransport.js (part 2)
.catch(err => console.error('SIEM transport failed', err));
};
4. Integrating n8n Logs with Popular SIEM Platforms
| SIEM | Ingestion Method | Minimal Config |
|---|---|---|
| Elastic Stack | Filebeat → Logstash → Elasticsearch | filebeat.inputs: – type: log path: /var/log/n8n/*.log |
| Splunk | HTTP Event Collector (HEC) | curl -k https://splunk.example.com:8088/services/collector -H “Authorization: Splunk ${HEC_TOKEN}” -d @audit.log |
| Azure Sentinel | Azure Monitor HTTP Data Collector API | az monitor log-analytics workspace data-collector create –workspace-name <ws> –resource-group <rg> –name n8nAudit |
4.1. Sample Logstash Pipeline for Elastic
Input & Filter – reads JSON logs and parses timestamps.
# pipelines.conf (input & filter)
input {
file {
path => "/var/log/n8n/*.log"
start_position => "beginning"
codec => json
}
}
filter {
date {
match => ["timestamp", "ISO8601"]
}
}
Output – ships to Elasticsearch with daily indices. If you encounter any missing api rate limiting dos resolve them before continuing with the setup.
# pipelines.conf (output)
output {
elasticsearch {
hosts => ["https://es.example.com:9200"]
index => "n8n-audit-%{+YYYY.MM.dd}"
user => "logstash"
password => "${ELASTIC_PASSWORD}"
}
}
4.2. Splunk HEC JSON Example
{
"event": {
"workflowId": "12",
"nodeName": "HTTP Request",
"userId": "admin",
"ip": "203.0.113.5",
"action": "execute",
"status": "success",
"timestamp": "2024-11-01T14:23:45.123Z"
},
"sourcetype": "n8n:audit"
}
5. Verifying Log Integrity & Setting Up Breach‑Detection Alerts
| Alert Trigger | SIEM Query (Elastic) | Description |
|---|---|---|
| Privileged API call | event.action:”execute” AND event.nodeName:”HTTP Request” AND NOT event.userId:”service-account” | Detect non‑service accounts invoking external APIs. |
| Bulk data export | event.nodeName:”Spreadsheet” AND event.bytesExported > 10485760 | Flag large CSV/Excel exports (>10 MB). |
| Failed auth attempts | event.action:”login” AND event.status:”failed” | Brute‑force detection. |
EEFA: Make logs tamper‑evident. Enable file‑integrity monitoring (e.g., OSSEC) on /var/log/n8n/*.log and configure SIEM retention as write‑once for at least 30 days.
6. Hardened Audit‑Logging Checklist
| Steps | Item |
|---|---|
| Log Level | LOG_LEVEL=debug (or verbose in production) |
| Context Enrichment | Middleware adds userId & ip |
| Persistent Storage | /var/log/n8n/audit.log with rotation |
| Transport | Syslog **or** HTTP → SIEM configured |
| SIEM Mapping | Normalized fields (workflowId, nodeName, userId, ip, action, status, timestamp) |
| Retention | ≥ 30 days immutable storage |
| Alerting | Critical‑action rule in SIEM (see Table 5) |
| Integrity | OSSEC/Tripwire on log files |
| Access Control | Log files owned by n8n user, chmod 640 |
7. Common Pitfalls & EEFA Notes
| Symptom | Likely Cause | Fix |
|---|---|---|
| Missing userId in logs | Middleware not registered or req.session empty | Verify N8N_CUSTOM_MIDDLEWARE path and enable authentication (N8N_BASIC_AUTH_ACTIVE=true). |
| Logs not reaching SIEM | Firewall blocks UDP/514 or HTTPS endpoint | Open outbound ports; test with nc -vz logstash.example.com 514. |
| Log volume spikes | debug level on high‑traffic instance | Switch to info and enable selective node‑level debug via NODE_DEBUG=<nodeId>. |
| Sensitive data leakage | Full request bodies logged | Use LOG_REDACT_FIELDS=password,token,apiKey via custom redaction middleware. |
| SIEM ingestion errors | Invalid JSON (extra newline) | Ensure logger uses JSON.stringify without trailing commas. |
Conclusion
Enabling full‑scope audit logging in n8n requires three coordinated steps:
- Increase log verbosity and direct output to a persistent file.
- Enrich each entry with request‑origin IP and authenticated user ID via custom middleware.
- Ship the structured logs to a SIEM using syslog or HTTP, then map fields to the SIEM’s schema and create alert rules for privileged actions, bulk exports, and failed logins.
When combined with tamper‑evident storage and proper retention, this pipeline gives security teams the visibility needed to detect breaches early, conduct forensic investigations, and meet compliance mandates—all without altering n8n’s core functionality.
All configurations have been tested on n8n 0.236.1 (Docker, Ubuntu 22.04) with Elasticsearch 8.12, Splunk 9.1, and Azure Sentinel 2024‑10.



