October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Add and Enable NGINX Logging on a Linux Server

A practical Linux guide to enabling NGINX access logging, checking whether the module is already present, choosing formats and destinations, and verifying writes safely.
Length12 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

NGINX request logging is provided by the ngx_http_log_module. On a normal Linux package installation you usually do not install a separate module: define a log_format, point access_log at a writable file (or a syslog destination), test the configuration, reload NGINX, and generate a request to verify the result.

The exact configuration and log paths depend on how your binary was built. Start with nginx -V instead of assuming that every distribution uses /etc/nginx/nginx.conf and /var/log/nginx/access.log. The build arguments and the active include files are the authority for the server you are changing.

As an Amazon Associate I earn from qualifying purchases.

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.

What the NGINX log module does

The ngx_http_log_module writes HTTP request logs in a format you specify. Its two directives do different jobs:

  • log_format defines the fields and layout of each record.
  • access_log selects the destination and the format, and can also control buffering, compression, flushing, and conditional logging.

Logging is separate from NGINX’s error log. The access log records requests such as method, URI, response status, bytes sent, referrer, and user agent. The error log records startup failures, upstream errors, permission problems, and other diagnostics. Enabling one does not automatically change the other.

access_log is valid in the http, server, location, if in location, and limit_except contexts. A setting in a more specific context can override an inherited setting, including access_log off;.

Find the configuration and log paths used by your binary

Package layouts vary between distributions, containers, source builds, and manually installed binaries. Run this command as the same user or shell environment that normally starts NGINX:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
nginx -V 2>&1 | awk -F: '/configure arguments/ {print $2}' | xargs -n1

The output lists configure arguments. Pay particular attention to:

  • --conf-path: the primary nginx.conf path.
  • --error-log-path: the compiled-in default error-log path.
  • --http-log-path: the compiled-in primary request-log path.
  • Module and prefix arguments that indicate where an installation keeps includes, modules, and runtime files.

An official package example uses /etc/nginx/nginx.conf and places access and error logs below /var/log/nginx/, but those are examples, not universal paths. Use the paths reported by your installed build and inspect the include statements in the active configuration.

If the command fails because the executable is not in your shell’s PATH, locate the service’s binary first (for example, with your distribution’s package information or the command shown in the service unit), then run that binary with -V. Do not edit a similarly named configuration file for a different NGINX installation.

Inspect the effective configuration and includes

The main file commonly includes a directory of virtual-host files. A setting in an included file is part of the same configuration tree. To print the complete configuration that NGINX would load, use:

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

Review the output for the active http block, every log_format, each access_log, and any access_log off;. This also helps when a distribution’s visible template differs from the file actually loaded by the service.

Do you need to install or compile a module?

For ordinary request logging, usually not. NGINX’s package documentation distinguishes modules compiled into the main binary from selected modules delivered as dynamic packages. The main package is built with modules that do not require additional libraries, while some optional features are shipped separately. Request logging is normally available in a standard HTTP build; confirm by testing the directives rather than downloading an unrelated module package.

A dynamic module must be loaded with a top-level load_module directive before its directives can be used. Do not add load_module for a module that is already compiled into the binary, and do not guess a module filename. If NGINX reports an unknown log_format or access_log directive, check that the service is using the binary you inspected, that the configuration is not from another installation, and that the build includes HTTP support. Only after those checks should you consider replacing the package or building from source.

When a source build is appropriate

Compile NGINX only when you have a concrete requirement that the available package cannot meet, such as a controlled custom build, a required third-party feature, or a distribution policy that does not provide the needed module. Preserve the existing configure arguments where possible; changing them can silently remove features used by current virtual hosts.

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

The source-build documentation identifies --http-log-path=path as the build-time primary request-log path. That value establishes the initial filename, but it is not a permanent restriction: after installation, you can change the filename in nginx.conf with access_log. A source build still needs a writable destination and a service account with permission to create or append the file.

Configure a basic access log

Put log_format in the http context. Put access_log in http for a default that applies to servers, or in a particular server or location when only that traffic should be recorded.

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 {
        listen 80;
        # server settings...
    }
}

This format is a conventional combined-style record. It captures the client address, authenticated user (when present), local time, request line, status, response size, referrer, and user agent. Replace /var/log/nginx/access.log with the path appropriate to your build and operating system.

Choose where the directive belongs

Context Effect Typical use
http Default for all applicable virtual servers unless overridden. One common format and destination for the whole installation.
server Applies to one virtual server and its locations unless overridden. Separate files for different sites or applications.
location Applies only to matching requests. Different detail or retention for an API, static files, or an administrative path.
if in location or limit_except Allows the directive in the specific contexts documented by NGINX. Narrow, conditional policies; use only when you understand inheritance.

Define a named format once in http; do not duplicate the same log_format in each virtual host. If a virtual server inherits an access_log and you want it silent, explicitly use access_log off; in that server or location.

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

Design a useful log format

Start with the fields needed to answer operational questions. Common variables include:

  • $remote_addr for the peer address seen by NGINX.
  • $remote_user for the authenticated username, if authentication supplied one.
  • $time_local for the local timestamp.
  • $request for the request line.
  • $status for the final HTTP status.
  • $body_bytes_sent for response bytes excluding the response header.
  • $http_referer and $http_user_agent for the corresponding request headers.

Application-specific variables can be added when they are available in the request or response context. Every extra field increases line length and may contain personal or confidential data. Decide what operators actually need before logging headers wholesale.

JSON-like records for ingestion

If a log collector parses structured records, define a consistent delimiter and escape strategy. NGINX’s variables can be empty, and unescaped user-controlled values can contain characters that confuse a downstream parser. Keep the format documented alongside the service configuration and test it with representative requests, including missing referrers and unusual user-agent strings.

Set the destination, buffering, and compression

The basic syntax is:

access_log path format [buffer=size] [gzip[=level]] [flush=time] [if=condition];

The path may be a file or a syslog destination as supported by the installed NGINX version. The format name must match a log_format defined in an enclosing http context.

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

File permissions and variable paths

Ensure the directory exists before reloading. The worker process must be able to open the file for append, and the service account may need permission to create the file after rotation or restart. A static path is easiest to operate. Variable-based paths add flexibility but have file-opening and permission constraints documented by NGINX; they can also create many files and complicate rotation. Use them only with a deliberate directory layout and tested ownership and modes.

Check both directory and file permissions, not just the filename:

sudo ls -ld /var/log/nginx
sudo ls -l /var/log/nginx/access.log

If the target does not exist, create the directory with the ownership and mode used by your distribution’s NGINX package. Avoid making a log directory world-writable simply to bypass a permission error.

Buffered writes

A buffer groups records before writing them. This can reduce the frequency of disk writes, but records remain in memory until the buffer fills or a flush occurs. Do not choose a buffer so large that a crash would discard an unacceptable amount of recent logging.

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

Compression

The gzip parameter compresses buffered records before writing. Compression requires NGINX to have been built with zlib. It can reduce storage and I/O, at the cost of CPU and additional operational complexity. Verify the build and benchmark the effect under your workload before enabling it on a busy server.

Flush intervals

flush=time sets a maximum interval for flushing a non-empty buffer. Short intervals make records visible sooner; longer intervals generally reduce write activity. Choose based on how quickly operators must see a request and how much write overhead the host can absorb.

Exclude low-value requests with conditional logging

High-volume health checks or successful static responses can dominate an access log. Conditional logging uses a variable produced by map and the if parameter on access_log. The map belongs in http:

http {
    map $status $skip_access_log {
        200     1;
        204     1;
        default 0;
    }

    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 if=$skip_access_log;
}

That example illustrates the syntax but would skip successful responses and retain other statuses. Before using it, decide whether losing successful records is acceptable for incident investigation, capacity analysis, compliance, or billing. A safer policy is often to exclude only a narrowly identified health endpoint, or to keep a separate low-retention file for routine probes.

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

Forward logs to a centralized collector

Local files are useful for immediate troubleshooting, but centralized collection helps when you have multiple servers, short-lived instances, or a need to search requests across hosts. NGINX’s logging guidance covers forwarding records to syslog. A centralized design should define:

  • Transport and destination, including whether the channel is local or remote.
  • Field format and hostname or instance identity.
  • Retention, access control, and deletion requirements.
  • Back-pressure behavior when the collector is unavailable.
  • Whether sensitive headers or addresses must be redacted before forwarding.

Keep a local fallback during rollout so a collector outage does not remove your only copy of diagnostic data. Test both normal delivery and the failure mode, then document who owns retention and alerting.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Validate, reload, and prove that logging works

Make a backup or use version control for the configuration file you are about to edit. Then follow this sequence:

  1. Edit the active file. Add log_format under http and access_log in the chosen context. Confirm that any included file is actually loaded by the main configuration.
  2. Check the destination. Create the directory if necessary and verify that the NGINX worker identity can write there. Check mandatory access-control policy if your operating system enforces one.
  3. Test syntax and references. Run sudo nginx -t. A successful result reports that the syntax is okay and the test is successful. Do not reload after a failed test.
  4. Reload the service. Use the service manager used by your installation, commonly sudo systemctl reload nginx. A reload asks the master process to validate and apply the new workers without unnecessarily dropping existing connections.
  5. Generate a request. Send a request to the correct address and virtual-host name, for example curl -i http://127.0.0.1/. If the server selects hosts by name, add the appropriate Host header or use the production hostname.
  6. Read the configured file. Follow it with sudo tail -f /var/log/nginx/access.log, replacing the path with the configured destination. Confirm that the new line contains the expected status, request, and client fields.
  7. Test an error and an excluded case. Request a known missing resource to produce a 404, and exercise any health-check or conditional rule. This verifies both that records are being written and that the policy behaves as intended.

The exact service command and path are deployment-specific. If your installation is managed by another init system, container supervisor, or orchestration platform, use that platform’s reload operation after nginx -t succeeds.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Troubleshoot missing or incorrect access logs

nginx -t says the directive is unknown

  • Run nginx -V on the exact binary used by the service, not merely the first executable in your interactive PATH.
  • Use nginx -T to confirm that the file containing log_format is included.
  • Check that log_format is under http and that access_log is in an allowed context.
  • Confirm that you did not add a dynamic-module directive for a module that is already static, or omit a required load_module for a genuinely dynamic module.
  • If the binary lacks the required HTTP functionality, install a vendor package that includes it or rebuild deliberately while preserving needed configure arguments.

The test passes but no file appears

  • Inspect nginx -T for a more specific access_log off; or another access_log that overrides the one you edited.
  • Verify the request reached the intended virtual server and location. A different server_name, port, or protocol may use another log.
  • Check the directory and file ownership, modes, and mandatory access-control denials.
  • Look at the error log for “open() … failed” messages and other permission or path errors.
  • If buffering is enabled, generate more traffic or wait for the flush interval before concluding that writes are absent.
  • If logging is conditional, inspect the map variable and test a request that should produce a record.

The file exists but fields are empty or wrong

  • Confirm that each variable is valid for the request phase in which it is logged.
  • Remember that $remote_addr is the address seen by NGINX; a proxy or load balancer may require a separately configured real-IP policy if you need the original client address.
  • Check quoting and delimiters in custom formats with requests that have no referrer, no authenticated user, or unusual header characters.
  • Ensure that the collector’s parser matches the exact deployed format and that no second configuration writes a different format to the same destination.

Logs stop after rotation

Rotation changes or renames files while workers may still hold open file descriptors. Use the rotation procedure supplied by your distribution or service manager, and verify ownership and permissions on the newly created file. After rotation, send a test request and confirm that the current file receives it.

Operational and privacy decisions

Access logs can contain IP addresses, URLs, query strings, account identifiers, referrers, and user-agent data. Treat them as operational data with an explicit retention period and access policy. Avoid logging credentials, authorization headers, session tokens, or unnecessary personal information. If a query string can contain secrets, remove or rewrite it before it reaches a long-lived log destination.

Balance diagnostic value against resource cost:

Choice Benefit Trade-off
Default combined-style format Fast setup and familiar troubleshooting fields. Limited application context and potentially noisy volume.
Custom fields Better correlation with application events and response outcomes. Larger records, parser maintenance, and possible sensitive data exposure.
Conditional logging Less storage and I/O for predictable, low-value traffic. Removed records cannot be recovered during an incident.
Buffered or compressed writes Lower write frequency or storage consumption. Delayed visibility, CPU cost, and more complex failure behavior.
Centralized collection Cross-host search, retention controls, and shared alerting. Network dependency, transport security, and collector capacity planning.

Quick verification checklist

  • Record --conf-path, --http-log-path, and relevant configure arguments from nginx -V.
  • Use nginx -T to confirm the effective include tree.
  • Define log_format in http and place access_log in the intended context.
  • Confirm the destination directory exists and is writable by the NGINX worker identity.
  • Run sudo nginx -t before every reload.
  • Reload with the service manager that owns the installation.
  • Generate a known request with curl and read the configured destination.
  • Test a status that should be logged and one that a conditional rule should omit.
  • Review rotation, retention, privacy, and centralized-forwarding behavior before putting the configuration into long-term production use.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.