1. nginx.conf Configuration File Syntax
The nginx.conf file is the heart of Nginx, defining the entire behavior of the web server. Understanding the configuration syntax is the first step to mastering Nginx.
1.1. Basic Structure
# Directive đơn giản (simple directive) worker_processes 4;Directive block (block directive)
events { worker_connections 1024; }
Block lồng nhau (nested blocks)
http { server { location / { root /var/www/html; } } }
1.2. Syntax Rules
1. Directives:
- Each directive ends with a semicolon
; - Directives can be simple (one line) or block (with
{}) - Case-sensitive:
Rootdiffers fromroot
# Correct worker_processes 2;Wrong - missing semicolon
worker_processes 2
Wrong - incorrect case
Worker_Processes 2;
2. Comments:
# This is a single-line comment worker_processes 4; # End-of-line commentNo multi-line comments in Nginx
Must use # for each line
3. Include files:
# Include another file include /etc/nginx/mime.types;Include multiple files with wildcard
include /etc/nginx/conf.d/.conf; include /etc/nginx/sites-enabled/;
4. Variables:
# Nginx has many built-in variablesStart with $
$remote_addr # Client IP $request_uri # Requested URI $host # Hostname
Usage example
location / { return 200 "Your IP: $remote_addr\n"; }
5. String values:
# No quotes needed for simple values root /var/www/html;Quotes required if there are spaces or special characters
error_log "/var/log/nginx/error.log" warn; add_header X-Custom-Header "Hello World";
Can use single or double quotes
root '/var/www/html'; root "/var/www/html";
1.3. Units and Sizes
# Time units client_body_timeout 60s; # seconds (default) client_body_timeout 60; # also seconds client_body_timeout 60m; # minutes client_body_timeout 1h; # hours client_body_timeout 1d; # daysSize units
client_max_body_size 10m; # megabytes client_max_body_size 10M; # also megabytes client_max_body_size 1g; # gigabytes client_max_body_size 1024k; # kilobytes client_max_body_size 1048576; # bytes (no unit)
1.4. Measurement units
# No unit = bytes client_max_body_size 1048576; # 1MBk/K = kilobytes
client_max_body_size 1024k;
m/M = megabytes
client_max_body_size 1m;
g/G = gigabytes (Nginx 0.7.0+)
client_max_body_size 1g;
2. Contexts and Directives
Nginx uses a context system to organize configuration by level. Each context defines the scope of applicable directives.
2.1. Main Contexts
# MAIN CONTEXT (global) user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid;EVENTS CONTEXT
events { worker_connections 1024; use epoll; }
HTTP CONTEXT
http { # Applies to all HTTP traffic
# SERVER CONTEXT server { # Applies to a specific virtual host # LOCATION CONTEXT location / { # Applies to a specific URL pattern } }}
STREAM CONTEXT (for TCP/UDP)
stream { server { listen 3306; } }
MAIL CONTEXT (for mail proxy)
mail { server { listen 25; } }
2.2. HTTP Context - Global Configuration
http { # MIME types include /etc/nginx/mime.types; default_type application/octet-stream;# Logging 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; error_log /var/log/nginx/error.log warn; # Performance sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # Gzip compression gzip on; gzip_vary on; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # Include server blocks include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;
}
2.3. Server Context - Virtual Host
http { # Server block 1 server { listen 80; server_name example.com www.example.com; root /var/www/example.com;access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; } # Server block 2 server { listen 80; server_name blog.example.com; root /var/www/blog; } # Default server (catch-all) server { listen 80 default_server; server_name _; return 444; # Close connection }
}
2.4. Location Context - URL Matching
server { listen 80; server_name example.com; root /var/www/html;# Exact match location = /about { # Matches only /about } # Prefix match location /images/ { # Matches /images/*, /images/photo.jpg, etc. } # Regex match (case-sensitive) location ~ \.(jpg|png|gif)$ { # Matches files ending with .jpg, .png, .gif } # Regex match (case-insensitive) location ~* \.(jpg|png|gif)$ { # Matches JPG, jpg, JpG, etc. } # Prefix match (stop regex checking) location ^~ /api/ { # Matches /api/* and stops regex checking } # Default location location / { # Matches everything if no other match }
}
2.5. Location Matching Priority
Nginx processes locations in priority order:
=- Exact match (highest)^- Prefix match (stop regex)or~*- Regex match (in order of appearance in file)- No modifier - Prefix match (lowest)
Illustrative example:
server { listen 80; server_name example.com;# Priority 1 - Exact match location = /test { return 200 "Exact match: /test\n"; } # Priority 2 - Prefix (stop regex) location ^~ /test { return 200 "Prefix match (^~): /test*\n"; } # Priority 3 - Regex (case-insensitive) location ~* ^/test { return 200 "Regex match (~*): /test*\n"; } # Priority 4 - Prefix match location /test { return 200 "Prefix match: /test*\n"; } # Default location / { return 200 "Default location\n"; }
}
Test results:
curl http://example.com/test→ "Exact match: /test"
curl http://example.com/test123
→ "Prefix match (^
): /test*" (because ^stops regex)If removing the ^~ location:
curl http://example.com/test123
→ "Regex match (~): /test"
3. Configuring Virtual Hosts (Server Blocks)
Virtual hosts allow a single Nginx server to serve multiple websites and domains.
3.1. Creating Your First Virtual Host
Step 1: Create the website directory
# Create document root sudo mkdir -p /var/www/mysite.com/htmlCreate logs directory
sudo mkdir -p /var/www/mysite.com/logs
Set ownership
sudo chown -R $USER:$USER /var/www/mysite.com sudo chmod -R 755 /var/www/mysite.com
Step 2: Create a sample HTML file
cat > /var/www/mysite.com/html/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Welcome to mysite.com</title>
<style>
body { font-family: Arial, sans-serif; margin: 50px; }
h1 { color: #00539C; }
</style>
</head>
<body>
<h1>Welcome to mysite.com!</h1>
<p>This is my first Nginx virtual host.</p>
</body>
</html>
EOF
Step 3: Create the virtual host configuration file
# Ubuntu/Debian sudo nano /etc/nginx/sites-available/mysite.comCentOS/RHEL
sudo nano /etc/nginx/conf.d/mysite.com.conf
Configuration file contents:
server { # Port and server name listen 80; listen [::]:80; server_name mysite.com www.mysite.com;# Document root root /var/www/mysite.com/html; index index.html index.htm; # Logs access_log /var/www/mysite.com/logs/access.log; error_log /var/www/mysite.com/logs/error.log; # Main location location / { try_files $uri $uri/ =404; } # Error pages error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /404.html { internal; } location = /50x.html { internal; } # Deny access to hidden files location ~ /\. { deny all; access_log off; log_not_found off; }
}
Step 4: Enable the virtual host (Ubuntu/Debian)
# Create symlink sudo ln -s /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/Check configuration
sudo nginx -t
Reload Nginx
sudo systemctl reload nginx
Step 5: Configure DNS or hosts file
# Add to /etc/hosts (for local testing) sudo nano /etc/hostsAdd the line:
127.0.0.1 mysite.com www.mysite.com
Step 6: Test
curl http://mysite.comor open browser: http://mysite.com
3.2. Virtual Host with Multiple Domains
# Config 1: Multiple domains for the same content server { listen 80; server_name mysite.com www.mysite.com example.com www.example.com; root /var/www/mysite.com/html; index index.html; }Config 2: Subdomain
server { listen 80; server_name blog.mysite.com; root /var/www/blog; index index.html; }
server { listen 80; server_name shop.mysite.com; root /var/www/shop; index index.html; }
Config 3: Wildcard subdomain
server { listen 80; server_name *.mysite.com; root /var/www/subdomains/$host;
# $host will contain subdomain.mysite.com}
Config 4: Regex server name
server { listen 80; server_name ~^(www.)?(?<domain>.+)$; root /var/www/$domain; }
3.3. Default Server (Catch-all)
# Default server to handle unmatched requests server { listen 80 default_server; listen [::]:80 default_server; server_name _; # Underscore = don't care about server name# Option 1: Return 444 (close connection) return 444; # Option 2: Return 403 Forbidden # return 403; # Option 3: Redirect to main site # return 301 https://mainsite.com$request_uri; # Option 4: Show maintenance page # root /var/www/default; # index maintenance.html;
}
3.4. Advanced Listen Directives
server { # IPv4 listen 80;# IPv6 listen [::]:80; # Specific IP listen 192.168.1.100:80; # Different port listen 8080; # Default server listen 80 default_server; # SSL listen 443 ssl; listen [::]:443 ssl; # HTTP/2 listen 443 ssl http2; # Multiple options listen 80 default_server reuseport;
}
4. Serving Static Files
Nginx excels at serving static content (HTML, CSS, JS, images).
4.1. Basic Configuration
server { listen 80; server_name static.example.com;# Document root root /var/www/static; # Index files index index.html index.htm; # Main location location / { try_files $uri $uri/ =404; }
}
Directory structure:
/var/www/static/
├── index.html
├── css/
│ ├── style.css
│ └── bootstrap.css
├── js/
│ ├── app.js
│ └── jquery.js
└── images/
├── logo.png
└── background.jpg
Requests handled:
http://static.example.com/ → /var/www/static/index.html
http://static.example.com/css/style.css → /var/www/static/css/style.css
http://static.example.com/images/logo.png → /var/www/static/images/logo.png
4.2. Root vs Alias
Root directive:
location /images/ { root /var/www/static; }Request: /images/photo.jpg
File path: /var/www/static/images/photo.jpg
(root + location path)
Alias directive:
location /images/ { alias /var/www/photos/; }Request: /images/photo.jpg
File path: /var/www/photos/photo.jpg
(alias replaces location path)
Detailed example:
server { listen 80; server_name example.com;# Using root location /static/ { root /var/www; } # /static/style.css → /var/www/static/style.css # Using alias location /assets/ { alias /var/www/static/; } # /assets/style.css → /var/www/static/style.css # Alias for exact path location = /favicon.ico { alias /var/www/icons/favicon.ico; }
}
Note: When using alias, the location path must end with / if alias also ends with /.
4.3. Try_files Directive
# Syntax try_files file ... uri; try_files file ... =code;Example 1: Check file, folder, then 404
location / { try_files $uri $uri/ =404; }
Example 2: Fallback to index.html (SPA)
location / { try_files $uri $uri/ /index.html; }
Example 3: Check multiple files
location / { try_files $uri $uri/index.html $uri.html =404; }
Example 4: Fallback to backend
location / { try_files $uri $uri/ @backend; }
location @backend { proxy_pass http://localhost:3000; }
4.4. Configuration per File Type
server { listen 80; server_name cdn.example.com; root /var/www/cdn;# HTML files location ~ \.html$ { add_header Cache-Control "public, max-age=3600"; } # CSS and JavaScript location ~ \.(css|js)$ { add_header Cache-Control "public, max-age=31536000"; access_log off; } # Images location ~ \.(jpg|jpeg|png|gif|ico|svg|webp)$ { add_header Cache-Control "public, max-age=31536000"; access_log off; expires 1y; } # Fonts location ~ \.(woff|woff2|ttf|otf|eot)$ { add_header Cache-Control "public, max-age=31536000"; add_header Access-Control-Allow-Origin "*"; access_log off; } # Videos location ~ \.(mp4|webm|ogg)$ { add_header Cache-Control "public, max-age=31536000"; mp4; # Enable MP4 streaming access_log off; } # Downloads location /downloads/ { add_header Content-Disposition "attachment"; }
}
4.5. Security for Static Files
server { listen 80; root /var/www/html;# Deny access to hidden files location ~ /\. { deny all; access_log off; log_not_found off; } # Deny access to backup files location ~ ~$ { deny all; access_log off; log_not_found off; } # Deny access to config files location ~ \.(conf|config|yml|yaml|ini)$ { deny all; } # Protect sensitive directories location ~ ^/(\.git|\.svn|\.env) { deny all; }
}
5. Configuring Index Files and Autoindex
5.1. Index Directive
# Syntax index file ...;Example 1: Default index
server { listen 80; root /var/www/html; index index.html index.htm; }
Example 2: Multiple index files (in order)
server { listen 80; root /var/www/html; index index.php index.html index.htm default.html; }
Example 3: Different index files per location
server { listen 80; root /var/www/html;
location / { index index.html; } location /blog/ { index index.php; } location /docs/ { index readme.md index.html; }
}
5.2. Autoindex (Directory Listing)
# Enable autoindex server { listen 80; server_name files.example.com; root /var/www/files;location / { autoindex on; }}
Detailed autoindex configuration
location /downloads/ { autoindex on; # Enable directory listing autoindex_exact_size off; # Show size in KB, MB instead of bytes autoindex_localtime on; # Show local time instead of GMT autoindex_format html; # Format: html, xml, json, jsonp }
Example with JSON format
location /api/files/ { autoindex on; autoindex_format json; }
Autoindex output:
Index of /downloads/
../ file1.pdf 23-Nov-2024 10:30 2.5M file2.zip 22-Nov-2024 15:45 15M folder/ 20-Nov-2024 09:00 -
5.3. Custom Autoindex Styling
server { listen 80; root /var/www/files;location / { autoindex on; autoindex_exact_size off; autoindex_localtime on; # Add custom header/footer add_before_body /autoindex/header.html; add_after_body /autoindex/footer.html; } location /autoindex/ { internal; alias /var/www/autoindex/; }
}
header.html file:
<!DOCTYPE html>
<html>
<head>
<title>File Directory</title>
<style>
body { font-family: Arial; margin: 20px; }
h1 { color: #333; }
a { color: #0066cc; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
</head>
<body>
<h1>File Directory</h1>
<hr>
footer.html file:
<hr>
<p>© 2024 My Company</p>
</body>
</html>
6. Custom Error Pages
6.1. Basic Configuration
server { listen 80; server_name example.com; root /var/www/html;# Custom error pages error_page 404 /404.html; error_page 500 502 503 504 /50x.html; # Location for error pages location = /404.html { internal; # Only accessible internally } location = /50x.html { internal; }
}
6.2. Detailed Error Pages
Create 404.html file:
cat > /var/www/html/404.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>404 - Page Not Found</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 50px;
background: #f5f5f5;
}
h1 { font-size: 72px; color: #e74c3c; }
p { font-size: 24px; color: #555; }
a { color: #3498db; text-decoration: none; }
</style>
</head>
<body>
<h1>404</h1>
<p>Oops! Page not found.</p>
<p><a href="/">← Go back home</a></p>
</body>
</html>
EOF
Create 50x.html file:
cat > /var/www/html/50x.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>500 - Server Error</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 50px;
background: #f5f5f5;
}
h1 { font-size: 72px; color: #e67e22; }
p { font-size: 24px; color: #555; }
</style>
</head>
<body>
<h1>500</h1>
<p>Internal Server Error</p>
<p>We're working on it!</p>
</body>
</html>
EOF
6.3. Advanced Error Pages
server { listen 80; server_name example.com; root /var/www/html;# Error pages per location location / { error_page 404 /errors/404.html; } location /api/ { error_page 404 /errors/api-404.json; error_page 500 /errors/api-500.json; } # Error page with custom message location /special/ { error_page 404 =200 /custom-404.html; # =200 overrides the status code } # Redirect to external error page location /old-site/ { error_page 404 = @external_error; } location @external_error { return 302 https://example.com/error-handler; } # Error page with variable location /dynamic/ { error_page 404 /404.html?page=$uri; } # Named location for errors error_page 404 = @notfound; location @notfound { return 404 "Custom 404 message\n"; }
}
6.4. Error Log with Format
http { # Define custom error log format log_format error_log '[$time_local] $status $request ' 'Client: $remote_addr ' 'Server: $server_name';server { listen 80; server_name example.com; # Use custom format error_log /var/log/nginx/example.error.log error_log; # Different log level error_log /var/log/nginx/debug.log debug; }
}
7. Practice Exercises
Exercise 1: Create a Virtual Host
- Create a virtual host for
mysite.local - Document root:
/var/www/mysite - Create an index.html file with any content
- Add to /etc/hosts and test
Exercise 2: Static File Server
- Create the directory structure:
/var/www/static/
├── index.html
├── css/style.css
├── js/app.js
└── images/logo.png
- Configure Nginx to serve these files
- Set different cache headers for each file type
Exercise 3: Directory Listing
- Create a virtual host for
files.local - Enable autoindex
- Customize the format and styling
- Test with multiple files
Exercise 4: Custom Error Pages
- Create custom 404 and 500 pages
- Apply to a virtual host
- Test by accessing a non-existent URL
- Test a 500 error (can fake with
return 500)
Exercise 5: Multiple Virtual Hosts
- Create 3 virtual hosts:
site1.local→/var/www/site1site2.local→/var/www/site2blog.site1.local→/var/www/blog
- Each site has different content
- Configure and test all of them
8. Common Troubleshooting
Error 1: 403 Forbidden
# Cause: Permission ls -la /var/www/htmlFix: Set correct ownership
sudo chown -R www-data:www-data /var/www/html sudo chmod -R 755 /var/www/html
Cause: SELinux (CentOS)
sudo setenforce 0
Error 2: 404 Not Found
# Check root directive location / { root /var/www/html; # Is this path correct? index index.html; # Does this file exist? }Check with curl
curl -I http://example.com
Error 3: Configuration Not Reloading
# Test config first sudo nginx -tIf OK, reload
sudo systemctl reload nginx
Check error log
sudo tail -f /var/log/nginx/error.log
Error 4: Server Name Not Working
# Check DNS/hosts cat /etc/hostsCheck server_name directive
grep server_name /etc/nginx/sites-available/*
Clear browser cache
Or test with curl
curl -H "Host: mysite.com" http://localhost
9. Best Practices
- Organize configuration files:
/etc/nginx/
├── nginx.conf (main config)
├── conf.d/ (global configs)
└── sites-available/ (individual sites)
- Clear comments:
# Block spam bots
if ($http_user_agent ~* (bot|crawler|spider)) {
return 403;
}
- Use includes:
http {
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
}
- Test before reloading:
sudo nginx -t && sudo systemctl reload nginx
- Backup configs:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
Summary
In this lesson, you learned:
- ✅ nginx.conf syntax and structure
- ✅ Contexts and directives in Nginx
- ✅ Creating and managing virtual hosts
- ✅ Serving static files efficiently
- ✅ Configuring index files and autoindex
- ✅ Customizing error pages
Next lesson: We will explore Logging and Monitoring — how to track and analyze traffic on your Nginx server.