Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Put a logging policy in the broadest Nginx context that should share it, then override it in a server block only when a virtual host needs a different file, format, retention boundary, or owner. A shared http-level access_log is simplest for sites managed together. Per-server logs are clearer when domains have separate operators, customers, incident workflows, or retention requirements. error_log is a separate directive with different context rules, so configure and troubleshoot it independently.

How Nginx logging contexts are organized

Nginx configuration is hierarchical. Directives outside any named block are in the main context. The http and events blocks are inside that main context; a server block is inside http; and a location block is inside server. A setting at a higher level can provide a default for nested blocks, while a more specific block can change the effective setting for the requests it handles.

This hierarchy is the reason there is no universal “global versus server” answer. The right location is the narrowest scope that needs a different policy, not automatically the most specific scope available. Start with one policy for all virtual hosts when they have the same operational requirements. Add a server-level directive when one virtual host must be isolated or treated differently.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

access_log and error_log are different directives

Directive Module and valid contexts What it records Documented default
access_log HTTP log module; http, server, location, if in location, and limit_except Completed HTTP requests, using a selected log format logs/access.log combined
error_log Core directive; main, http, mail, stream, server, and location Errors and diagnostic messages at the configured severity The build prefix’s primary error log, normally prefix/logs/error.log, when no file is explicitly defined at main level

The two directives can use different scopes. For example, every HTTP server can write requests to one common access file while a particular server writes errors to a dedicated file. Do not assume that changing one directive changes the other.

When a shared http-level log is the better design

Place a common log_format and access_log in http when virtual hosts share a collector, rotation schedule, schema, and operational owner. Every server that does not define its own access_log then uses that policy.

http {
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "${http_user_agent}"';

    access_log /var/log/nginx/access.log main;

    server {
        server_name example.com;
        # Inherits the http-level access_log.
    }

    server {
        server_name api.example.net;
        # Also inherits the same file and format unless overridden.
    }
}

This arrangement gives operators one place to change the path or format and one stream to feed into a central log pipeline. It also avoids maintaining a long list of nearly identical directives. The trade-off is that a shared file mixes tenants and applications; filtering by host or another field must be reliable, and file ownership or retention cannot vary per virtual host.

When a per-server log is the better design

Define access_log and, when needed, error_log inside an individual server block if that virtual host needs separate ownership, retention, billing, incident response, customer isolation, or a distinct destination or format.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
http {
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "${http_user_agent}"';

    server {
        server_name example.com;
        access_log /var/log/nginx/example.access.log main;
        error_log  /var/log/nginx/example.error.log warn;
    }
}

The server-level directives apply only to requests handled by that server unless a more specific location changes the access-log behavior. Other virtual hosts continue using the http-level defaults.

Decision axis Shared http policy Per-server policy
Isolation Requests and often errors are collected together; host fields are needed for separation. Each virtual host has its own destination, making ownership boundaries explicit.
Operational overhead One path, format, and rotation policy to maintain. More files, directories, permissions, rotation rules, and configuration entries.
Retention and ownership Common retention and access controls. Retention, access, and archival can differ by site or customer.
Troubleshooting Cross-site traffic is visible in one stream but may require filtering. A site’s request and error history is easier to find, provided you know the correct file.
Centralized collection Simple when one collector expects a common schema. Still compatible, but every destination must be enrolled and monitored.

There is no published statistic establishing a performance, storage-cost, or incident-frequency winner between these designs. Choose based on isolation and administration rather than an assumed speed advantage.

How inheritance and overrides actually work

access_log inheritance

If an access_log directive is not defined at the current level, Nginx uses the setting inherited from the enclosing level. A server-level directive therefore replaces the inherited http-level access destination and format for that server. A location-level directive can replace the server’s setting for requests whose processing ends in that location.

The special form access_log off; disables request logging for the scope where it is placed. Use it deliberately: health checks or static assets may be intentionally silent, but disabling logs on an externally reachable server removes valuable request evidence.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

error_log inheritance and multiple destinations

error_log is valid in more contexts than access_log, including the main, mail, and stream contexts. Several error logs can be specified on the same configuration level; this has been supported since Nginx 1.5.2. If no file destination is explicitly defined at main level, Nginx uses its default error-log file. Consequently, inspect the complete effective configuration instead of assuming that the filename in one block is the only destination receiving a message.

The final argument on error_log is a severity threshold such as warn. A more verbose level can be useful while diagnosing a problem, but it can increase volume. Set the threshold that matches the purpose of the file and your retention capacity.

Why a request can appear in a different access log

Nginx logs a request in the context of the location where processing ends. That can differ from the original matching location after an internal redirect. A rewrite, an index lookup, an error-page handoff, or another internal routing step can therefore select the access-log setting of the final location.

When a request lands in an unexpected file, inspect every applicable location and look for internal redirects. Verify the final URI and the location that ultimately generated the response; changing only the original server block may not change the setting used at the end of processing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Useful logging patterns

One access log for all virtual hosts

http {
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "${http_user_agent}"';
    access_log /var/log/nginx/access.log main;

    server {
        server_name example.com;
    }
}

Use this when a central collector, common rotation policy, and shared schema are more important than per-site files. Include a field that identifies the host if downstream systems need to separate virtual hosts.

Separate access and error files for one server

server {
    server_name example.com;
    access_log /var/log/nginx/example.access.log main;
    error_log  /var/log/nginx/example.error.log warn;
}

This keeps normal request records and diagnostic messages distinct while giving the virtual host an explicit operational boundary.

Disable access logging for a deliberately quiet endpoint

server {
    server_name health.example.com;
    access_log off;
}

Apply this only when the loss of request visibility is acceptable. Error logging remains a separate decision.

Log only selected responses

The if= parameter on access_log enables conditional logging. The request is omitted when the condition evaluates to 0 or an empty string.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
http {
    map $status $loggable {
        ~^[23] 0;
        default 1;
    }

    access_log /var/log/nginx/access.log combined if=$loggable;
}

In this example, successful and redirect responses are omitted while other statuses are retained. Test a condition carefully before applying it to production traffic; a mistaken expression can hide the very requests needed for diagnosis.

Forwarding logs to a central collector

Nginx can send both error and access logs to syslog instead of, or in addition to, local files. Destinations may be network addresses or UNIX-domain sockets.

error_log  syslog:server=192.168.1.1 debug;
access_log syslog:server=unix:/var/log/nginx.sock,nohostname;

A centralized destination is useful when many Nginx hosts must follow one retention, alerting, and access-control policy. Plan the collector, transport, failure behavior, and local fallback deliberately. A network destination does not remove the need to monitor whether messages are being accepted, and a UNIX socket requires the correct filesystem permissions and a running receiver.

Configure a new per-virtual-host log safely

  1. Choose the scope. Keep the directive in http for a shared policy. Put it in the target server when that virtual host needs a distinct path, format, severity, or ownership boundary. Use a location only for a deliberate endpoint-specific exception.
  2. Declare or reuse a format. Define log_format in http; reference that format from the server’s access_log. The format name must exist in the loaded configuration.
  3. Prepare the destination. Create the parent directory and ensure the Nginx worker user can create or write the file. Apply permissions that allow the logging process to write without granting unnecessary access to unrelated users.
  4. Add the directives. For example: access_log /var/log/nginx/example.access.log main; and error_log /var/log/nginx/example.error.log warn;.
  5. Inspect the assembled configuration. Run nginx -T. Nginx tests the configuration and dumps the loaded files, letting you confirm that the intended server and location blocks are present and that an included file did not add an unexpected directive.
  6. Run the syntax and file test. Run nginx -t. It checks syntax and attempts to open files referenced by the configuration, exposing many path and permission errors before a reload.
  7. Reload gracefully. After a successful test, run nginx -s reload. New workers use the new configuration while old workers finish existing requests and shut down gracefully.
  8. Generate a controlled request. Send a request with the intended host name, then check the expected access and error files. Confirm that the request appears once, with the expected format, and that unrelated virtual hosts still use their intended destinations.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting checklist

The server still writes to the global access log

  • Use nginx -T to verify that the edited server block is actually loaded and that its server_name matches the request’s Host header.
  • Check for a more specific location containing its own access_log; logging follows the location where processing ends.
  • Confirm that the configuration was reloaded after editing. A file change alone does not change running workers.
  • Check whether the request reached a different server selected by the listen address, port, default-server status, or name matching.

The new file is empty

  • Make a request that actually reaches the configured server and location.
  • Check whether access_log off; or a conditional if= expression suppresses it.
  • Verify the worker user can write the directory and file, and inspect the result of nginx -t for file-opening errors.
  • Remember that buffered or asynchronous delivery and log rotation can affect when data becomes visible; validate with a fresh request rather than relying on an old entry.

Errors are missing or going to an unexpected file

  • Inspect all error_log directives at main, http, server, and location levels.
  • Check the severity threshold; a message below the configured level will not be written to that destination.
  • Look for multiple destinations on the same level and for an included configuration file that adds another one.
  • Confirm that the parent directory exists and that the worker process can write it.

Too many or too few records

log_not_found controls whether errors about files that were not found are written to error_log. log_subrequest controls whether subrequests are written to access_log. Both directives are available in http, server, and location contexts. Set them at the broad level that matches your policy, then override a server or location only when its diagnostic needs differ.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical decision framework

  1. Ask who owns the data. If every virtual host has the same operators and access controls, begin with a shared http-level policy. If customers or teams must not read one another’s logs, use separate destinations or a collector with enforced tenant separation.
  2. Ask whether retention differs. A shared file is convenient when all sites have the same retention. Different legal, contractual, or incident requirements favor per-server files or separate collector streams.
  3. Ask how incidents are investigated. One stream simplifies host-wide correlation. Per-server files reduce filtering during a site-specific incident. Either design works if the host identity and timestamps are consistent.
  4. Ask how rotation will be managed. Every additional file needs a tested rotation and permission strategy. Do not create per-server logs without accounting for directory ownership, archival, and disk monitoring.
  5. Ask whether central collection is mandatory. Syslog destinations can preserve a common pipeline even when local files are separated. Configure and test each destination explicitly.

Common mistakes to avoid

  • Putting access_log in a context where it is not valid, such as the main context outside http.
  • Expecting a server-level access_log to control a request that finishes in a location with its own logging directive.
  • Changing error_log and assuming the access log changed too; they are independent directives.
  • Assuming one named error file is the only destination when multiple logs or inherited settings are present.
  • Reloading without first running nginx -t, then troubleshooting a configuration that never loaded.
  • Using conditional logging or access_log off; without documenting the observability that is intentionally being removed.
  • Creating files under a directory the worker cannot write, or rotating them in a way that leaves Nginx writing to an unlinked inode.

Bottom line

Use http-level directives for defaults shared by virtual hosts, and override them in a server block when a site needs its own destination, format, severity, retention, or ownership boundary. Treat access_log and error_log separately, account for the final location after internal redirects, validate with nginx -T and nginx -t, then apply the change with nginx -s reload. This approach keeps the configuration predictable without giving up per-site isolation where it matters.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.