> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Troubleshooting

> Practical, prioritized troubleshooting tips for NGINX covering configuration validation, reloads, logging, per-site logs, curl checks, firewalls, and common fixes to identify root causes quickly.

And welcome to the final demo.

![A simple slide showing the word "Troubleshooting" on the left and a large turquoise curved shape on the right labeled "Demo." The bottom-left corner shows "© Copyright KodeKloud."](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Demo-Troubleshooting/troubleshooting-demo-slide-turquoise-kodekloud.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=6c67b77a3f35290ae2216e88cf2e6f55)

Thanks for your patience. This write-up collects practical, prioritized troubleshooting tips for NGINX — what to check first, how to identify the root cause quickly, and common fixes.

Always validate configuration with `nginx -t` after editing. That single step catches most syntax and placement errors before you try to reload or restart NGINX.

***

## 1) Always validate configuration: nginx -t

Run `nginx -t` every time you edit any configuration file. It checks syntax and reports errors with file and line references so you can fix problems before reloading.

Example session showing a successful test, then editing a site and encountering a missing semicolon error:

```bash theme={null}
root@nginx:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

root@nginx:~# vim /etc/nginx/sites-available/example-https
# (introduce a typo: a missing semicolon after a directive)
root@nginx:~# nginx -t
nginx: [emerg] directive "deny" is not terminated by ";" in /etc/nginx/sites-enabled/example-https:9
nginx: configuration file /etc/nginx/nginx.conf test failed
```

Another common mistake is placing a top-level directive (for example, `http { ... }`) inside a `server` block. That produces an error like:

```bash theme={null}
root@nginx:~# nginx -t
nginx: [emerg] "http" directive is not allowed here in /etc/nginx/sites-enabled/example-https:33
nginx: configuration file /etc/nginx/nginx.conf test failed
```

Read the `nginx -t` output carefully — it tells you the file and approximate line number where parsing failed.

***

## 2) Use reload instead of restart when possible

A reload applies configuration changes gracefully without dropping active connections (in most cases). Prefer:

```bash theme={null}
nginx -s reload
```

or on systemd-managed systems:

```bash theme={null}
systemctl reload nginx
```

Only use `systemctl restart nginx` when a reload cannot resolve the issue (for example, after upgrading the nginx binary). Restarting will briefly drop connections and may create a visible outage for connected users.

Prefer `nginx -s reload` or `systemctl reload nginx` to avoid dropping active connections. Use `restart` only when necessary (e.g., after a binary upgrade).

***

## 3) Global configuration and logging

The main `/etc/nginx/nginx.conf` holds global settings such as `worker_processes`, logging defaults, gzip and SSL settings. Avoid making broad global changes unless you understand their performance and compatibility implications.

A common global section:

```nginx theme={null}
include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##
ssl_protocols TLSv1.2 TLSv1.3; # Consider allowing only modern TLS versions
ssl_prefer_server_ciphers on;

##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
```

If you change TLS protocol support (for example, restricting to TLS 1.2 and 1.3), do so intentionally — older clients might be unable to connect:

```nginx theme={null}
ssl_protocols TLSv1.2 TLSv1.3;
```

***

## 4) Per-site logs: create directories and set permissions

When you configure per-site log paths, NGINX will create the log files but not the parent directories. If a parent directory is missing, `nginx -t` or startup will fail with an error indicating it couldn't open the log file.

Example site server block (corrected):

```nginx theme={null}
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/ssl/certs/example.com.pem;
    ssl_certificate_key /etc/ssl/certs/example.com-key.pem;

    root /var/www/html;

    access_log /var/log/nginx/example.com/access.log;
    error_log  /var/log/nginx/example.com/error.log;

    add_header Strict-Transport-Security "max-age=31560000; includeSubDomains; preload";
    add_header X-Frame-Options "SAMEORIGIN";
    add_header Content-Security-Policy "default-src 'self'";
    add_header Referrer-Policy origin;

    index index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
```

If `/var/log/nginx/example.com/` does not exist, `nginx -t` will report an error similar to:

```bash theme={null}
nginx: [emerg] open() "/var/log/nginx/example.com/access.log" failed (2: No such file or directory) in /etc/nginx/sites-enabled/example-https:...
nginx: configuration file /etc/nginx/nginx.conf test failed
```

Fix by creating the directory and setting ownership:

```bash theme={null}
mkdir -p /var/log/nginx/example.com
chown -R www-data:adm /var/log/nginx/example.com
```

Then re-run:

```bash theme={null}
nginx -t
# if OK
nginx -s reload
```

Verify logs are being written:

```bash theme={null}
cd /var/log/nginx/example.com
ls -l
tail -f access.log
```

***

## 5) Quick service checks with curl

When users report an outage, use `curl` locally on the server to determine whether NGINX is responding or if the issue is DNS/firewall/external:

Example: check local HTTP redirect (NGINX responding with 301):

```bash theme={null}
root@nginx:/var/log/nginx# curl -I localhost
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 (Ubuntu)
Date: ...
Location: https://localhost/
```

Check HTTPS for the public site:

```bash theme={null}
root@nginx:/var/log/nginx# curl -I https://example.com
HTTP/2 200
server: nginx/1.18.0 (Ubuntu)
date: ...
content-type: text/html; charset=UTF-8
```

If you stop NGINX, `curl` will show a connection failure:

```bash theme={null}
systemctl stop nginx
root@nginx:/var/log/nginx# curl -I https://example.com
curl: (7) Failed to connect to example.com port 443: Connection refused
```

If `curl` from the server works but external clients cannot connect, investigate DNS records and firewall/security group rules.

You can force local resolution using `/etc/hosts` when DNS isn't pointing to the server yet. Example entries:

```text theme={null}
127.0.0.1 localhost example.com
127.0.0.1 example.com www.example.com

# IPv6 entries
::1 ip6-localhost ip6-loopback
```

***

## 6) Firewalls and cloud security groups

Check both the host firewall and any cloud-level firewalls (security groups, network ACLs).

Example `ufw` status:

```bash theme={null}
root@nginx:/var/log/nginx# ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
```

Ensure ports `80` and `443` are open. Even if you redirect HTTP to HTTPS, keeping `80` open helps certificate challenges (Let's Encrypt) and users who type `http://`.

If your infrastructure is in a cloud provider (AWS, GCP, Azure), verify that security groups / firewall rules allow the same ports.

***

## Quick reference: common checks and commands

| Area | Command / File | When to use |
| - | - | - |
| Syntax test | `nginx -t` | After every config change |
| Graceful apply | `nginx -s reload` or `systemctl reload nginx` | Apply config without dropping connections |
| Restart | `systemctl restart nginx` | When reload fails or after binary upgrade |
| Logs | `tail -f /var/log/nginx/error.log` | Investigate runtime errors |
| Site logs | `ls -l /var/log/nginx/example.com` | Verify per-site logs exist and are writable |
| Local HTTP test | `curl -I http://localhost` | Verify NGINX is listening locally |
| Remote HTTPS test | `curl -I https://example.com` | Check site as external client |
| Firewall check | `ufw status` | Confirm ports `80`/`443` are allowed |

***

## Final tips (cheat-sheet)

* Always run `nginx -t` after editing configuration files and before reloading.
* Use `nginx -s reload` or `systemctl reload nginx` for config changes to avoid dropping active connections.
* Make minimal global configuration changes unless you understand performance and compatibility trade-offs.
* Create per-site log directories and set proper ownership so NGINX can write logs.
* Test from the server with `curl` to distinguish NGINX problems from DNS or network/firewall issues.
* When troubleshooting, follow the path: syntax → service state → local request → firewall/cloud network → DNS → clients.

Thanks for reading — I appreciate it.

## Links and references

* [NGINX Documentation — Beginner’s Guide](https://nginx.org/en/docs/beginners_guide.html)
* [systemd.service — systemctl reload/restart reference](https://www.freedesktop.org/software/systemd/man/systemctl.html)
* [curl — Manual](https://curl.se/docs/manpage.html)
* [UFW — Uncomplicated Firewall documentation](https://help.ubuntu.com/community/UFW)

> **[Watch Video](https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/4a5db5c4-df5f-4291-84f0-013d1c4ce235/lesson/53475fbe-d12f-48d7-9602-d4a93debd874)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.