In Nginx, you can define access and error logs both globally in the http block and per server block, with the server block settings overriding the global ones. This article explains how both levels work, how to choose between them, and common pitfalls to avoid.
Background: How Nginx Logging Works
Nginx logs two types of events: access logs record every request the server receives, and error logs record problems such as configuration errors, connection failures, and upstream timeouts. Both are controlled by two directives: access_log and error_log. These directives can appear in the http, server, and (for access logs) location contexts. When a directive is placed in the http block, it applies to all server blocks that do not have their own version. When placed in a server block, it overrides the global setting for that specific virtual host. This inheritance model is similar to other Nginx directives and is essential for managing multiple sites on one server.
Global http Block Configuration
Putting logging directives in the http block is the simplest approach. For example:
http {
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
...
}
This configuration sends all access logs to a single file and all error logs to another, with a severity level of warn (meaning warnings and above are recorded). The main advantage is centralization: you have one place to check for all traffic and errors. This is ideal for small servers with one or two sites, or when you do not need to separate logs by domain. However, if you host multiple sites with different traffic levels, a single file can become huge and hard to search. Also, if one site generates an error, it is mixed with others, making debugging more difficult.
Per Server Block Configuration
To separate logs by site, you can override the global settings inside a server block:
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
...
}
Now all requests for example.com are logged to their own files. This is the recommended practice for production servers hosting multiple domains or applications, because it simplifies log analysis, rotation, and debugging. You can also set different log levels per site; for instance, you might want debug for a development site but error for a busy production site. The per-server configuration completely replaces the global one for that server, so if you only specify an access_log in the server block, the error log still inherits from the global block.
How to Choose Between Global and Per-Server
Deciding where to put logging directives depends on your needs. Consider these factors:
- Number of sites: One or two sites → global is fine. More than that → per-server is clearer.
- Traffic volume: High traffic generates large logs; splitting them prevents one site from drowning out others.
- Debugging needs: If you often debug a specific site, having its own error log with a lower severity (like
info) is helpful. - Log rotation: Per-server logs are easier to rotate independently (e.g., daily for a busy API, weekly for a small blog).
- Compliance or analysis: If you need to provide logs for a specific domain, separate files make that straightforward.
A common hybrid approach is to set a sensible default in the http block (e.g., error_log at warn level) and then override only where needed. This ensures that any server block that forgets to specify a log still has a working configuration.
Common Problems and Misconceptions
One frequent mistake is assuming that the access_log directive in a location block overrides the server-level log. In fact, it adds a second log for that location, unless you use the off parameter. For example:
location /images/ {
access_log off;
}
This disables access logging for that location, which can be useful for static assets. Another misconception is that error_log can be set in a location block—it cannot; it is only valid in http, server, and stream contexts. Also, remember that the error_log directive in a server block replaces the global one entirely, so if you set a lower severity in the server, you will not see the global level’s messages for that server. Finally, ensure the directory where you write logs exists and is writable by the Nginx worker process; otherwise, Nginx will fail to start or log errors to the system log.
Comparing Global vs Per-Server: Pros and Cons
Here is a quick comparison to help you decide:
- Global: Pros – simple, fewer lines of config, easy for small setups. Cons – logs are mixed, can become large, harder to isolate issues.
- Per-server: Pros – clear separation, easier analysis and rotation, can tailor log levels. Cons – more configuration, risk of forgetting to set logs for a new server block (though it inherits global defaults).
In practice, most multi-site servers use per-server logging for access logs and keep a global error log as a safety net. This balances detail with simplicity.
Best Practices for Log Management
Regardless of where you define your logs, follow these practices:
- Use
logrotateto rotate logs daily or weekly, keeping a reasonable number of old files. - Set appropriate log levels:
warnorerrorfor production,infoordebugfor troubleshooting. - Consider using JSON log format for easier parsing by tools like Elasticsearch or Splunk.
- Monitor disk space; a busy site can generate gigabytes of logs per day.
- Test configuration changes with
nginx -tbefore reloading.
For error logs, remember that the error_log directive also accepts the syslog: prefix to send logs to a remote syslog server, which is useful for centralized monitoring.
Frequently Asked Questions
Can I use both global and per-server logs at the same time?
Yes, and it is common. The global settings act as defaults, and per-server settings override them. For example, you can have a global access log for all sites and a separate access log for a specific site that also logs to the global one—but to do that, you need to specify both paths in the server block (Nginx does not automatically log to both).
What is the default log location if I do not set anything?
If you do not specify any access_log or error_log directives, Nginx uses the compiled-in default: logs/access.log and logs/error.log relative to the Nginx prefix directory (often /usr/local/nginx/logs or /var/log/nginx). Most distributions set a global default in the http block.
How do I disable access logging for a specific server?
Set access_log off; inside the server block. This completely disables access logging for that server, overriding any global setting. Error logs cannot be turned off with off; you can only set a very high level like crit to minimize output.
Does the log level in the server block affect the global error log?
No. The server block’s error_log directive creates a separate log file (or syslog destination) with its own level. The global error log continues to log messages according to its own level, but only for servers that do not have their own error_log directive. Once you define an error_log in a server block, that server’s errors go only there, not to the global file.
Can I use variables in the log file path?
Yes, for access_log you can use variables like $server_name to create per-domain files automatically. For example: access_log /var/log/nginx/$server_name.access.log;. However, this is not recommended for high-traffic sites because it can cause file descriptor exhaustion, and Nginx does not create directories automatically. It is safer to explicitly define paths per server block.