Nginx tutorial: configure request logging
Configure Nginx access logs to capture POST data, GET parameters, and custom log formats using the log_format and access_log directives in nginx.conf.
This tutorial walks through configuring Nginx access logs to capture POST data, GET request parameters, and custom log formats. By the end, you will understand how the
log_formatandaccess_logdirectives work and have working log configurations for debugging HTTP traffic.
What You Will Need
- Root or sudo access to a Linux server running Nginx.
- SSH access to edit the nginx.conf configuration file at
/etc/nginx/nginx.conf. - The
ngx_http_echo_moduleinstalled (required for POST body logging). This module is not included in the default Nginx package on most distributions.
Step 1: Understand Nginx Log Directives
Nginx provides two directives that control access logging:
log_format and
access_log. The
log_format directive defines a named template that specifies which request variables Nginx writes to the log file. The
access_log directive assigns a log file path and a format name.
Both directives must appear inside the
http { } context in nginx.conf. Nginx does not allow
log_format inside server or location blocks. The
access_log directive can appear in http, server, or location contexts.
Nginx writes one line to the access log for every HTTP request it processes. The default combined log format records the client IP, timestamp, request method, URI, status code, response size, referrer, and user agent.
Step 2: Configure Nginx to Log POST Request Bodies
Nginx does not log POST request bodies in the default log format. The
$request_body variable captures the POST data, but Nginx only populates this variable when the request body has been read by a handler.
Add a custom
log_format in the
http { } block and reference it in an
access_log directive. The
echo_read_request_body directive from the
ngx_http_echo_module forces Nginx to read the request body so the
$request_body variable contains data.
http {
log_format post_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status '
'"$http_referer" "$http_user_agent" '
'body: $request_body';
access_log /var/log/nginx/post_access.log post_log;
server {
location / {
echo_read_request_body;
default_type text/html;
}
}
}Nginx writes POST data to
/var/log/nginx/post_access.log in this configuration. Without
echo_read_request_body, the
$request_body variable remains empty because Nginx does not buffer the request body by default.
Step 3: Configure Nginx to Log GET Request Parameters
Nginx includes GET request parameters in the
$request variable by default. The default combined log format already captures the full request line, which includes the query string. A custom log format provides finer control over the output.
Define a custom
log_format that includes the variables relevant to GET request analysis:
http {
log_format get_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status '
'"$http_host" '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log get_log;
}Nginx writes every GET request to
/var/log/nginx/access.log using this custom format. The
$http_host variable captures the domain name from the
Host header, which is useful when Nginx serves multiple domains.
Step 4: Customize the Nginx Log Format
Nginx exposes many variables that can appear in a
log_format template. Choose the variables that match the debugging or analytics needs.
| Variable | Description |
|---|---|
$remote_addr | Client IP address |
$remote_user | Authenticated username (if using HTTP basic auth) |
$time_local | Local time in common log format |
$request | Full request line (method, URI, protocol) |
$status | HTTP response status code |
$body_bytes_sent | Number of bytes sent to the client (excluding headers) |
$http_referer | Referrer URL from the request header |
$http_user_agent | User-Agent string from the request header |
$request_time | Total request processing time in seconds |
$upstream_response_time | Time spent waiting for the upstream server response |
$upstream_connect_time | Time to establish a connection to the upstream server |
$ssl_protocol | SSL/TLS protocol version used for the connection |
$ssl_cipher | SSL/TLS cipher suite used for the connection |
$gzip_ratio | Compression ratio achieved by gzip |
Combine these variables into a format string that suits the use case. Enclose variable references in single quotes within the
log_format directive.
Step 5: Test and Reload the Nginx Configuration
Nginx validates the configuration when the
-t flag runs. Test after every change to catch syntax errors before they affect the running server.
sudo nginx -tReload Nginx to apply the new logging configuration. A reload applies changes without dropping active connections.
sudo systemctl reload nginxSend a test request and verify that the log file captures the expected data:
curl -X POST -d "username=testuser&action=login" http://example.com/
tail -5 /var/log/nginx/post_access.logWhat You Learned
Nginx uses the
log_format directive to define custom log templates and the
access_log directive to assign a log file and format. The
$request_body variable captures POST data only when a handler reads the request body. GET parameters appear in the
$request variable by default. Nginx log variables such as
$upstream_response_time and
$ssl_protocol provide performance and security insights.
What to Do Next
For a quick-reference version of logging configuration, see the nginx.conf snippetspage. To secure the Nginx web server and protect log files from unauthorized access, see Nginx tutorial: secure a web server.