Directory Structure
Learning Focus
Leave this lesson with a working understanding of directory structure that you can apply immediately in production.
Knowing where every file lives is essential for fast troubleshooting and clean config management.
Yazi Navigation
Browse the config tree interactively:
yazi /etc/nginx/
Use l to open dirs, h to go back, q to quit.
Full Layout
/etc/nginx/
├── nginx.conf # Main config — global settings, includes
├── conf.d/ # Drop-in server block configs (*.conf auto-loaded)
│ └── default.conf # Default server block (RHEL-family)
├── sites-available/ # All site configs (Debian/Ubuntu pattern)
│ └── example.com.conf # Inactive until symlinked to sites-enabled
├── sites-enabled/ # Symlinks to active sites
│ └── example.com.conf -> ../sites-available/example.com.conf
├── snippets/ # Reusable config fragments
│ ├── fastcgi-php.conf # FastCGI PHP pass snippet
│ └── snakeoil.conf # Self-signed cert snippet (Debian)
├── modules-enabled/ # Dynamic module configs (Debian)
├── modules-available/ # Available module configs
├── fastcgi_params # FastCGI parameter set (classic)
├── fastcgi.conf # FastCGI params + SCRIPT_FILENAME
├── uwsgi_params # uWSGI parameter set
├── scgi_params # SCGI parameter set
├── mime.types # MIME type → file extension mappings
├── koi-win # Legacy charset maps
├── koi-utf # Legacy charset maps
└── win-utf # Legacy charset maps
/var/log/nginx/
├── access.log # All HTTP requests
└── error.log # Errors — check this FIRST
/var/www/html/ # Default web root (Debian/Ubuntu)
/usr/share/nginx/html/ # Default web root (RHEL/AlmaLinux)
/run/nginx.pid # Master process PID (or /var/run/nginx.pid)
/usr/sbin/nginx # Nginx binary
/usr/lib/nginx/modules/ # Dynamic modules (.so files)
/etc/nginx/modules-enabled/ # Symlinks to enabled module configs (Debian)
Key Files — What They Do
nginx.conf — Master Config
The entry point for all configuration. It sets global worker settings, the events {} block, and includes the http {} block with all site configs.
# View it
sudo cat /etc/nginx/nginx.conf
# Edit it
sudo vim /etc/nginx/nginx.conf
# Search for include statements (see what gets loaded)
grep "include" /etc/nginx/nginx.conf
conf.d/ vs sites-available/ + sites-enabled/
These are two organizational patterns — both valid:
| Pattern | Where | Activation |
|---|---|---|
conf.d/ | /etc/nginx/conf.d/*.conf | All .conf files auto-loaded |
sites-available/ + sites-enabled/ | /etc/nginx/sites-available/ | Symlink to sites-enabled/ |
The symlink pattern lets you keep inactive configs around without loading them.
# Enable a site (Debian pattern)
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Disable a site
sudo rm /etc/nginx/sites-enabled/example.com
# Verify which sites are enabled
ls -la /etc/nginx/sites-enabled/
snippets/ — Reusable Fragments
Store repeated config blocks here and include them:
# In a server block
include /etc/nginx/snippets/fastcgi-php.conf;
include /etc/nginx/snippets/ssl-params.conf;
fastcgi_params vs fastcgi.conf
Both set FastCGI parameters for PHP-FPM. The difference:
fastcgi_params— does not includeSCRIPT_FILENAME(you must add it manually)fastcgi.conf— includesSCRIPT_FILENAME(usually prefer this)
# Using fastcgi.conf (simpler)
include fastcgi.conf;
# Using fastcgi_params (you must also add):
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
CLI Exploration Commands
# Full config tree
sudo find /etc/nginx -type f | sort
# List all active configs (everything included)
sudo nginx -T | head -100
# Find all server_name directives across all configs
sudo grep -rn "server_name" /etc/nginx/
# Find all listen directives
sudo grep -rn "^[[:space:]]*listen" /etc/nginx/
# Find all root/alias directives
sudo grep -rn "root\|alias" /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
# Find all fastcgi_pass lines (PHP-FPM connections)
sudo grep -rn "fastcgi_pass" /etc/nginx/
# Find all proxy_pass lines (reverse proxy connections)
sudo grep -rn "proxy_pass" /etc/nginx/
# Check which modules are loaded
nginx -V 2>&1 | tr -- - '\n' | grep module
Log Access
# Live error log (most useful for debugging)
sudo tail -f /var/log/nginx/error.log
# Live access log
sudo tail -f /var/log/nginx/access.log
# Filter errors from the last hour
sudo awk -v d="$(date '+%d/%b/%Y:%H')" '$0 ~ d' /var/log/nginx/error.log | grep -i error
# Log size check
du -sh /var/log/nginx/
# Per-site logs (if configured)
ls /var/log/nginx/
PID File
# Get master process PID
cat /run/nginx.pid
# Or
cat /var/run/nginx.pid
# Kill signals to master process (safer than systemctl in some cases)
sudo kill -HUP $(cat /run/nginx.pid) # Graceful reload (same as nginx -s reload)
sudo kill -QUIT $(cat /run/nginx.pid) # Graceful shutdown
sudo kill -TERM $(cat /run/nginx.pid) # Fast shutdown
sudo kill -USR1 $(cat /run/nginx.pid) # Reopen log files
Hands-On Practice
# Verify Nginx is running
sudo systemctl status nginx
# Test config syntax
sudo nginx -t
# Reload without downtime
sudo nginx -s reload
# Check error log
sudo tail -20 /var/log/nginx/error.log
Common Pitfalls
| Pitfall | What happens | Fix |
|---|---|---|
| Editing config without reloading | Changes not applied | sudo nginx -s reload after every edit |
Not running nginx -t first | Reload breaks with syntax error | Always test syntax before reloading |
| Wrong socket path for PHP-FPM | 502 Bad Gateway | ls /run/php/ and verify the exact socket filename |
What's Next
- Continue to the next lesson in this module, or go to the module index for an overview.
- Use the Cheatsheets for quick CLI reference.