yum upgrades for production use, this is the repository for you.
Active subscription is required.
📅 Updated: March 19, 2026 (Originally published: February 10, 2026)
The NGINX pipelog module allows you to send HTTP access logs to external programs via Unix pipes. This module enables workflows that standard NGINX logging cannot achieve: piping logs to custom scripts, real-time log processors, or any command-line tool.
When to Use Pipelog vs Native NGINX Logging
NGINX already supports several logging methods natively:
- File logging:
access_log /var/log/nginx/access.log; - Syslog:
access_log syslog:server=127.0.0.1:514,tag=nginx; - Multiple destinations: You can specify multiple
access_logdirectives
So when should you use the NGINX pipelog module instead?
Use pipelog when you need to:
– Pipe logs to custom scripts that process each entry in real-time
– Send real-time alerts (Slack, email) on specific access patterns
– Send logs to programs that don’t support syslog protocol
– Use shell commands or pipelines for log processing
– Have the module automatically restart crashed log consumers
Use native access_log when you need to:
– Write logs to files (native is simpler)
– Send to syslog servers (native syslog: prefix works well)
– Basic logging without external dependencies
How the NGINX Pipelog Module Works
When you configure the pipelog directive, NGINX spawns the specified command as a child process. It connects the command’s stdin to a Unix pipe. Every log entry goes to this pipe instead of a file. The external command reads from stdin and processes the log data.
This architecture offers several advantages:
- Pipe to any command: Send logs to scripts, log shippers, or custom processors.
- Real-time processing: The external command receives logs as requests complete.
- Automatic restart: If the pipe command crashes, the module restarts it automatically.
- Non-blocking option: Write operations can be non-blocking to prevent slowdowns.
Installation
RHEL, CentOS, AlmaLinux, Rocky Linux
Install the GetPageSpeed repository and the module:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-pipelog
Load the module in your NGINX configuration by adding to the top of /etc/nginx/nginx.conf:
load_module modules/ngx_http_pipelog_module.so;
Debian and Ubuntu
First, set up the GetPageSpeed APT repository, then install:
sudo apt-get update
sudo apt-get install nginx-module-pipelog
On Debian/Ubuntu, the package handles module loading automatically. No
load_moduledirective is needed.
For more details, see the module pages:
– RPM packages: nginx-extras.getpagespeed.com/modules/pipelog
– APT packages: apt-nginx-extras.getpagespeed.com/modules/pipelog
Configuration Directives
The NGINX pipelog module provides two directives. Use pipelog_format for defining log formats. Use pipelog for enabling pipe-based logging.
pipelog_format
Defines a named log format for use with the pipelog directive.
Syntax:
pipelog_format name [escape=default|json|none] string ...;
Context: http, server, location
Parameters:
– name: A unique identifier for this format
– escape: How to escape special characters (default: default)
– default: Escape characters as \xXX
– json: JSON-compatible escaping for structured logging
– none: No escaping (use with caution)
– string: The format string using NGINX variables
Example:
pipelog_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
pipelog_format json escape=json '{"time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"request": "$request", '
'"status": $status, '
'"body_bytes_sent": $body_bytes_sent}';
pipelog
Enables pipe-based logging to an external command.
Syntax:
pipelog command [format [nonblocking] [if=condition]];
pipelog off;
Context: http, server, location, if in location, limit_except
Default: off
Parameters:
– command: The shell command to pipe logs to (no | prefix needed)
– format: Name of a pipelog_format (defaults to combined format)
– nonblocking: Enable non-blocking writes to prevent slow commands from blocking NGINX
– if=condition: Conditional logging based on a variable
Practical Use Cases
Real-time Slack Alerts for Sensitive Endpoints
This is where the NGINX pipelog module truly shines. Send instant Slack notifications when someone accesses admin panels, API keys, or other sensitive endpoints:
http {
pipelog_format alert escape=json
'{"uri":"$uri","client":"$remote_addr","time":"$time_iso8601"}';
server {
listen 80;
# Alert on sensitive endpoint access
location /admin {
pipelog "/usr/local/bin/slack-alert.sh" alert;
proxy_pass http://backend;
}
location /wp-login.php {
pipelog "/usr/local/bin/slack-alert.sh" alert;
proxy_pass http://backend;
}
location /.env {
pipelog "/usr/local/bin/slack-alert.sh" alert;
return 404;
}
}
}
Create the alert script at /usr/local/bin/slack-alert.sh:
#!/bin/bash
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
while read -r line; do
curl -s -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"text\": \"⚠️ Sensitive endpoint accessed: $line\"}" &
done
Make it executable: chmod +x /usr/local/bin/slack-alert.sh
Now every access to /admin, /wp-login.php, or /.env triggers an instant Slack notification. This is impossible with native NGINX logging alone.
Custom Log Processing Script
Send logs to a script that filters, transforms, or forwards them:
http {
pipelog_format json escape=json
'{"timestamp":"$time_iso8601",'
'"client":"$remote_addr",'
'"method":"$request_method",'
'"uri":"$uri",'
'"status":$status,'
'"size":$body_bytes_sent,'
'"request_time":$request_time}';
server {
listen 80;
server_name example.com;
pipelog "/usr/local/bin/log-processor.py" json;
location / {
root /var/www/html;
}
}
}
Your log-processor.py could send alerts on errors, update real-time metrics, filter sensitive data, or forward logs to multiple destinations.
Real-time Log Shipping
Send logs directly to a log shipper or aggregation tool that reads from stdin:
pipelog "/usr/bin/vector --config /etc/vector/nginx.toml" json;
Or pipe to nc for simple TCP forwarding to a log server:
pipelog "/usr/bin/nc logserver.example.com 5140" main;
Using logger for Syslog (Simple Demo)
While NGINX has native syslog support, using logger via pipelog demonstrates the module’s flexibility. This approach works well with journalctl for LEMP stack troubleshooting:
pipelog "/usr/bin/logger -t nginx -p local0.info" main;
Note: For simple syslog needs, native
access_log syslog:server=...is simpler. Use pipelog withloggerwhen you need additional shell processing or when combining with other commands in a pipeline.
Conditional Logging
Skip logging for specific requests using the if parameter. This technique is similar to disabling logging for Varnish backend probes:
http {
map $uri $loggable {
~^/health 0;
~^/metrics 0;
default 1;
}
pipelog_format main '$remote_addr - [$time_local] "$request" $status';
server {
pipelog "/usr/local/bin/log-processor.sh" main if=$loggable;
location / {
root /var/www/html;
}
}
}
This skips logging for /health and /metrics endpoints. For Magento sites, you might also want to disable logging of security probes.
Non-blocking Mode for High Traffic
On high-traffic sites, a slow log consumer could cause NGINX worker processes to block:
pipelog "/usr/local/bin/slow-processor.sh" main nonblocking;
With nonblocking enabled, log entries may be dropped if the pipe buffer fills up. Use this when log delivery is less critical than request handling performance.
Performance Considerations
The NGINX pipelog module adds minimal overhead compared to file-based logging:
- Pipe writes vs file writes: Writing to a pipe is typically faster than writing to disk.
- Memory buffering: The kernel buffers pipe data, reducing syscall overhead.
- External process overhead: The spawned command runs independently from NGINX workers.
However, consider these factors:
- Pipe buffer size: The kernel pipe buffer (typically 64KB on Linux) limits queued data.
- Consumer speed: Your external command must process logs fast enough to keep up with traffic.
- Non-blocking tradeoffs: Using
nonblockingprevents blocking but may lose logs under heavy load.
Best Practices
Follow these recommendations for reliable pipelog deployments:
- Always use absolute paths: Specify
/usr/bin/loggerinstead of justlogger. This prevents PATH manipulation issues. -
Test consumer throughput: Before production deployment, verify your log processor can handle peak traffic.
-
Use nonblocking sparingly: Only enable
nonblockingif you’ve observed actual blocking issues. -
Monitor the error log: The module logs pipe failures to NGINX error log. Set up monitoring for these messages.
-
Background slow operations: In alert scripts, use
&to background curl calls so they don’t block log processing.
Troubleshooting
Logs Not Appearing
-
Check if module is loaded:
nginx -V 2>&1 | grep -o pipelog - Verify configuration syntax:
nginx -t - Check if the pipe command is running:
ps aux | grep -E "log-processor|slack-alert" - Test the command manually:
echo '{"test":"data"}' | /usr/local/bin/slack-alert.sh
Command Crashes or Restarts
The NGINX pipelog module automatically restarts crashed commands. Check your error log:
tail -f /var/log/nginx/error.log | grep -i pipe
Security Considerations
When using the NGINX pipelog module:
- Validate command paths: Use absolute paths for commands to prevent PATH manipulation.
- Limit permissions: Run log processing commands with minimal privileges.
- Sanitize log data: If your command executes log content, ensure proper escaping.
- Protect webhook URLs: Store Slack webhook URLs in environment variables, not in scripts.
Comparison with Native access_log
| Feature | access_log (file) | access_log (syslog:) | pipelog |
|---|---|---|---|
| Writes to files | Yes | No | No |
| Syslog support | No | Yes (native) | Via logger command |
| Pipe to any command | No | No | Yes |
| Real-time Slack/alerts | No | No | Yes |
| Auto-restart consumer | N/A | N/A | Yes |
| Non-blocking mode | No | No | Yes |
| Conditional logging | Yes (if=) | Yes (if=) | Yes (if=) |
Bottom line: Use native access_log for files or syslog. Use the NGINX pipelog module when you need real-time alerts, custom scripts, or tools that read from stdin. For structured distributed tracing across microservices, consider the NGINX OpenTelemetry module which exports spans in OpenTelemetry format to collectors like Jaeger or Zipkin.
Conclusion
The NGINX pipelog module fills a specific gap: piping access logs to arbitrary commands in real-time. The Slack alerting example shows its true power – instant notifications when sensitive endpoints are accessed.
For sysadmins who need real-time log processing or security alerting, the pipelog module offers automatic command restart and non-blocking mode. These features make it reliable for production environments.
Install the module from the GetPageSpeed repository and explore the source code on GitHub to learn more.
