Skip to main content
DevOpsbeginner

Where Are Nginx Logs Stored? Default Paths (Ubuntu, CentOS, Docker)

Find nginx access and error logs at /var/log/nginx/. Exact paths for Ubuntu, Debian, CentOS, Docker, and macOS, plus how to tail and rotate them.

8 min readUpdated June 2026

Want us to handle this for you?

Get expert help →

Nginx writes two logs by default: the access log at /var/log/nginx/access.log and the error log at /var/log/nginx/error.log. These paths are identical on Ubuntu, Debian, RHEL, CentOS, and Fedora when nginx is installed from the distro or official nginx package. The locations are controlled by the access_log and error_log directives in /etc/nginx/nginx.conf, and individual server {} blocks frequently override them with per-site files such as /var/log/nginx/example.com.access.log.

Quick Reference: Nginx Log File Paths

Platform / Install methodAccess logError log
Ubuntu / Debian (apt)/var/log/nginx/access.log/var/log/nginx/error.log
RHEL / CentOS / Fedora (yum/dnf)/var/log/nginx/access.log/var/log/nginx/error.log
nginx.org official repo/var/log/nginx/access.log/var/log/nginx/error.log
Source build (default prefix)/usr/local/nginx/logs/access.log/usr/local/nginx/logs/error.log
Homebrew (macOS, Intel)/usr/local/var/log/nginx/access.log/usr/local/var/log/nginx/error.log
Homebrew (macOS, Apple Silicon)/opt/homebrew/var/log/nginx/access.log/opt/homebrew/var/log/nginx/error.log
Docker (official image)stdout (docker logs)stderr (docker logs)
Per-site (common override)/var/log/nginx/<site>.access.log/var/log/nginx/<site>.error.log

The startup error log — written before nginx reads its config — is also compiled in at build time. Check it with nginx -V 2>&1 | tr ' ' '\n' | grep error-log.

How to View and Tail Nginx Logs

Follow the live access log:

sudo tail -f /var/log/nginx/access.log

Follow the error log and access log together:

sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log

Find the last 50 errors:

sudo tail -n 50 /var/log/nginx/error.log

Filter the access log for a specific status code (502 Bad Gateway here):

sudo grep ' 502 ' /var/log/nginx/access.log

Count requests per IP address (top 10 talkers):

sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

Inside Docker, logs go to the container's stdout/stderr:

docker logs -f <container>
docker logs --tail 100 <container>

Finding the Exact Path When It Varies

Never guess. Have nginx tell you the resolved paths:

sudo nginx -T 2>&1 | grep -E 'access_log|error_log'

nginx -T dumps the fully merged configuration including every included file, so you see every log directive across all server blocks. Lines reading access_log off; confirm logging is intentionally disabled for that scope.

Ubuntu / Debian Detail

The package ships a global error_log /var/log/nginx/error.log; and access_log /var/log/nginx/access.log; in /etc/nginx/nginx.conf. Site configs live in /etc/nginx/sites-available/ and typically add their own per-host log files. To change a path, edit the directive and reload:

sudo nano /etc/nginx/nginx.conf
sudo nginx -t && sudo systemctl reload nginx

RHEL / CentOS / Fedora Detail

Paths match Debian, but SELinux governs where nginx may write. If you move logs outside /var/log/nginx/, restore the correct context or nginx will be denied:

sudo semanage fcontext -a -t httpd_log_t "/data/logs(/.*)?"
sudo restorecon -Rv /data/logs

Config lives in /etc/nginx/nginx.conf with extra files under /etc/nginx/conf.d/.

Docker Detail

The Dockerfile for the official image contains ln -sf /dev/stdout /var/log/nginx/access.log and ln -sf /dev/stderr /var/log/nginx/error.log. That is why docker logs works out of the box and why there are no files to tail inside the container. To persist real files, mount a volume and replace the symlinks:

docker run -v /host/nginx-logs:/var/log/nginx mynginx

Confirm where a running container sends its logs:

docker inspect --format '{{.LogPath}}' <container>

Changing the Log Location and Format

Set a named log format and direct it to a custom file in nginx.conf or a server block:

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

access_log /var/log/nginx/custom.access.log main;
error_log  /var/log/nginx/custom.error.log warn;

The error log's second argument is the level: debug, info, notice, warn, error, crit, alert, or emerg. Lower levels produce more output.

Log Rotation

Logrotate handles nginx on package installs. The config is /etc/logrotate.d/nginx:

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
    endscript
}

The postrotate USR1 signal tells nginx to reopen its log files after rotation so it keeps writing to the fresh file rather than the renamed one. Test rotation without waiting a day:

sudo logrotate -f /etc/logrotate.d/nginx

Common Errors You'll Find in Nginx Logs

  • connect() failed (111: Connection refused) while connecting to upstream — the backend (PHP-FPM, app server) is down or listening on a different port; surfaces to clients as 502.
  • upstream timed out (110: Connection timed out) — backend took longer than proxy_read_timeout; raise the timeout or fix the slow backend, results in 504.
  • open() "/var/www/html/x" failed (13: Permission denied) — nginx's worker user (www-data or nginx) cannot read the file; fix ownership or permissions.
  • directory index of "/var/www/html/" is forbidden — no index file and autoindex off; serves a 403.
  • SSL_do_handshake() failed — TLS negotiation problem, often a client using an unsupported protocol or a bad certificate chain.
  • worker_connections are not enough — the worker hit its connection limit; raise worker_connections in the events {} block.

Troubleshooting: Logs Missing or Empty

  • Logging disabledaccess_log off; in a server or location block silences requests served there. Confirm with nginx -T.
  • Wrong file — the request is matched by a different server block that writes to its own per-site log. Match the server_name and listen to find the right file.
  • Permissions — your user cannot read /var/log/nginx/. Use sudo, or add yourself to the adm group on Debian.
  • Errors before config load — syntax errors and startup failures go to the compiled-in default log or to the systemd journal: journalctl -u nginx.
  • Docker — there are no files inside the official image; use docker logs. Files only exist if you removed the stdout/stderr symlinks.
  • Not reloaded — after editing a path, run sudo nginx -t && sudo systemctl reload nginx; without a reload nginx keeps writing to the old file.

Frequently Asked Questions

Find answers to common questions

On Debian and Ubuntu the default error log is /var/log/nginx/error.log. On RHEL, CentOS, and Fedora it is the same path, /var/log/nginx/error.log. The location is set by the error_log directive in /etc/nginx/nginx.conf and can be overridden per server block.

Run nginx -T to dump the full resolved configuration, then filter with nginx -T 2>&1 | grep -E 'access_log|error_log'. This shows every access_log and error_log directive across the main config and all included files, including paths defined inside individual server blocks.

The official nginx image symlinks /var/log/nginx/access.log to stdout and /var/log/nginx/error.log to stderr, so logs appear via docker logs rather than as files. To keep them as files, mount a volume to /var/log/nginx or remove the symlinks in a custom image.

An empty access.log usually means logging was disabled with access_log off; in the server or location block, requests are being served by a different server block with its own log file, or nginx was not reloaded after a config change. Run nginx -T to confirm which log file applies to the request you expect.

On Debian and Ubuntu, logrotate rotates nginx logs daily and keeps 14 compressed copies via /etc/logrotate.d/nginx. On RHEL the same file rotates daily with a shorter retention. Rotation sends nginx a USR1 signal so it reopens its log files without dropping connections.

Need help shipping something?

Productized MVP development for founders. 8 SaaS apps shipped — yours could be next, in 6 weeks.