Chuyển đến nội dung chính

Bài 2: Cấu hình Cơ bản Nginx

Bài học về cấu hình Nginx với cú pháp nginx.conf, context (http/server/location), directive cơ bản. Hướng dẫn tạo virtual hosts, serving static files, index files, autoindex và custom error pages. Bao gồm ví dụ thực tế và best practices cho production.

🔒 DevSecOps — Bài 2 Bài 2: Cấu hình Cơ bản Nginx

Nginx từ Cơ bản đến Nâng cao

Phần 1: Cơ bản

xdev.asia

1. Cú pháp file cấu hình nginx.conf

File nginx.conf là trái tim của Nginx, nơi định nghĩa toàn bộ cách hoạt động của web server. Hiểu rõ cú pháp cấu hình là bước đầu tiên để làm chủ Nginx.

1.1. Cấu trúc cơ bản

# 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. Quy tắc cú pháp

1. Directives:

  • Mỗi directive kết thúc bằng dấu chấm phẩy ;
  • Directives có thể là simple (một dòng) hoặc block (có dấu {})
  • Case-sensitive: Root khác với root
# Đúng
worker_processes 2;

Sai - thiếu dấu chấm phẩy

worker_processes 2

Sai - case sai

Worker_Processes 2;

2. Comments:

# Đây là comment một dòng
worker_processes 4;  # Comment cuối dòng

Không có comment nhiều dòng trong Nginx

Phải dùng # cho mỗi dòng

3. Include files:

# Include file khác
include /etc/nginx/mime.types;

Include nhiều files với wildcard

include /etc/nginx/conf.d/.conf; include /etc/nginx/sites-enabled/;

4. Variables:

# Nginx có nhiều biến built-in

Bắt đầu bằng $

$remote_addr # IP của client $request_uri # URI được request $host # Hostname

Ví dụ sử dụng

location / { return 200 "Your IP: $remote_addr\n"; }

5. String values:

# Không cần quotes cho giá trị đơn giản
root /var/www/html;

Cần quotes nếu có space hoặc ký tự đặc biệt

error_log "/var/log/nginx/error.log" warn; add_header X-Custom-Header "Hello World";

Có thể dùng single hoặc double quotes

root '/var/www/html'; root "/var/www/html";

1.3. Units và sizes

# Time units
client_body_timeout 60s;      # seconds (mặc định)
client_body_timeout 60;       # cũng là seconds
client_body_timeout 60m;      # minutes
client_body_timeout 1h;       # hours
client_body_timeout 1d;       # days

Size units

client_max_body_size 10m; # megabytes client_max_body_size 10M; # cũng là megabytes client_max_body_size 1g; # gigabytes client_max_body_size 1024k; # kilobytes client_max_body_size 1048576; # bytes (không có unit)

1.4. Measurement units

# Không có unit = bytes
client_max_body_size 1048576;  # 1MB

k/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. Context và Directive

Nginx sử dụng hệ thống context (ngữ cảnh) để tổ chức cấu hình theo cấp độ. Mỗi context định nghĩa phạm vi áp dụng của các directives.

2.1. Các Context chính

# 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 { # Áp dụng cho tất cả HTTP traffic

# SERVER CONTEXT
server {
    # Áp dụng cho một virtual host cụ thể
    
    # LOCATION CONTEXT
    location / {
        # Áp dụng cho một URL pattern cụ thể
    }
}

}

STREAM CONTEXT (cho TCP/UDP)

stream { server { listen 3306; } }

MAIL CONTEXT (cho mail proxy)

mail { server { listen 25; } }

2.2. HTTP Context - Cấu hình toàn cục

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 {
    # Chỉ match đúng /about
}

# Prefix match
location /images/ {
    # Match /images/*, /images/photo.jpg, etc.
}

# Regex match (case-sensitive)
location ~ \.(jpg|png|gif)$ {
    # Match file kết thúc bằng .jpg, .png, .gif
}

# Regex match (case-insensitive)
location ~* \.(jpg|png|gif)$ {
    # Match JPG, jpg, JpG, etc.
}

# Prefix match (stop regex checking)
location ^~ /api/ {
    # Match /api/* và không check regex
}

# Default location
location / {
    # Match tất cả nếu không có match nào khác
}

}

2.5. Priority của Location Matching

Nginx xử lý location theo thứ tự ưu tiên:

  1. = - Exact match (cao nhất)
  2. ^ - Prefix match (stop regex)
  3. hoặc ~* - Regex match (theo thứ tự xuất hiện trong file)
  4. No modifier - Prefix match (thấp nhất)

Ví dụ minh họa:

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 kết quả:

curl http://example.com/test

→ "Exact match: /test"

curl http://example.com/test123

→ "Prefix match (^): /test*" (vì ^ stop regex)

Nếu xóa ^~ location:

curl http://example.com/test123

→ "Regex match (~): /test"


3. Cấu hình Virtual Host (Server Blocks)

Virtual hosts cho phép một Nginx server phục vụ nhiều websites/domains khác nhau.

3.1. Tạo Virtual Host đầu tiên

Bước 1: Tạo thư mục cho website

# Tạo document root
sudo mkdir -p /var/www/mysite.com/html

Tạo thư mục logs

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

Bước 2: Tạo file HTML mẫu

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

Bước 3: Tạo file cấu hình virtual host

# Ubuntu/Debian
sudo nano /etc/nginx/sites-available/mysite.com

CentOS/RHEL

sudo nano /etc/nginx/conf.d/mysite.com.conf

Nội dung file cấu hình:

server {
# Port và 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;
}

}

Bước 4: Enable virtual host (Ubuntu/Debian)

# Tạo symlink
sudo ln -s /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/

Kiểm tra cấu hình

sudo nginx -t

Reload Nginx

sudo systemctl reload nginx

Bước 5: Cấu hình DNS hoặc hosts file

# Thêm vào /etc/hosts (cho local testing)
sudo nano /etc/hosts

Thêm dòng:

127.0.0.1 mysite.com www.mysite.com

Bước 6: Test

curl http://mysite.com

hoặc mở browser: http://mysite.com

3.2. Virtual Host với nhiều domains

# Cấu hình 1: Nhiều domains cho cùng nội dung
server {
listen 80;
server_name mysite.com www.mysite.com example.com www.example.com;
root /var/www/mysite.com/html;
index index.html;
}

Cấu hình 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; }

Cấu hình 3: Wildcard subdomain

server { listen 80; server_name *.mysite.com; root /var/www/subdomains/$host;

# $host sẽ chứa subdomain.mysite.com

}

Cấu hình 4: Regex server name

server { listen 80; server_name ~^(www.)?(?<domain>.+)$; root /var/www/$domain; }

3.3. Default Server (Catch-all)

# Default server để handle requests không match
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;  # Underscore = không quan tâm 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. Listen directives nâng cao

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 rất xuất sắc trong việc phục vụ static content (HTML, CSS, JS, images).

4.1. Cấu hình cơ bản

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;
}

}

Cấu trúc thư mục:

/var/www/static/
├── index.html
├── css/
│   ├── style.css
│   └── bootstrap.css
├── js/
│   ├── app.js
│   └── jquery.js
└── images/
├── logo.png
└── background.jpg

Requests được handle:

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 thay thế location path)

Ví dụ chi tiết:

server {
listen 80;
server_name example.com;

# Sử dụng root
location /static/ {
    root /var/www;
}
# /static/style.css → /var/www/static/style.css

# Sử dụng alias
location /assets/ {
    alias /var/www/static/;
}
# /assets/style.css → /var/www/static/style.css

# Alias cho exact path
location = /favicon.ico {
    alias /var/www/icons/favicon.ico;
}

}

Lưu ý: Khi dùng alias, location path phải kết thúc bằng / nếu alias cũng kết thúc bằng /.

4.3. Try_files directive

# Cú pháp
try_files file ... uri;
try_files file ... =code;

Ví dụ 1: Check file, folder, rồi 404

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

Ví dụ 2: Fallback to index.html (SPA)

location / { try_files $uri $uri/ /index.html; }

Ví dụ 3: Check multiple files

location / { try_files $uri $uri/index.html $uri.html =404; }

Ví dụ 4: Fallback to backend

location / { try_files $uri $uri/ @backend; }

location @backend { proxy_pass http://localhost:3000; }

4.4. Cấu hình cho từng loại file

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 và 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 cho 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. Cấu hình Index Files và Autoindex

5.1. Index directive

# Cú pháp
index file ...;

Ví dụ 1: Default index

server { listen 80; root /var/www/html; index index.html index.htm; }

Ví dụ 2: Nhiều index files (theo thứ tự)

server { listen 80; root /var/www/html; index index.php index.html index.htm default.html; }

Ví dụ 3: Index khác nhau cho từng 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)

# Bật autoindex
server {
listen 80;
server_name files.example.com;
root /var/www/files;

location / {
    autoindex on;
}

}

Cấu hình autoindex chi tiết

location /downloads/ { autoindex on; # Bật directory listing autoindex_exact_size off; # Hiển thị size dạng KB, MB thay vì bytes autoindex_localtime on; # Hiển thị local time thay vì GMT autoindex_format html; # Format: html, xml, json, jsonp }

Ví dụ với format JSON

location /api/files/ { autoindex on; autoindex_format json; }

Output autoindex:

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/;
}

}

File header.html:

<!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>

File footer.html:

    <hr>
<p>© 2024 My Company</p>
</body>
</html>

6. Error Pages Tùy chỉnh

6.1. Cấu hình cơ bản

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 cho error pages
location = /404.html {
    internal;  # Chỉ accessible internally
}

location = /50x.html {
    internal;
}

}

6.2. Error pages chi tiết

Tạo file 404.html:

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

Tạo file 50x.html:

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. Error pages nâng cao

server {
listen 80;
server_name example.com;
root /var/www/html;

# Error pages cho từng 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 với custom message
location /special/ {
    error_page 404 =200 /custom-404.html;
    # =200 override 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 với variable
location /dynamic/ {
    error_page 404 /404.html?page=$uri;
}

# Named location cho errors
error_page 404 = @notfound;

location @notfound {
    return 404 "Custom 404 message\n";
}

}

6.4. Error log với 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. Bài tập thực hành

Bài tập 1: Tạo Virtual Host

  1. Tạo virtual host cho mysite.local
  2. Document root: /var/www/mysite
  3. Tạo file index.html với nội dung tùy ý
  4. Thêm vào /etc/hosts và test

Bài tập 2: Static File Server

  1. Tạo cấu trúc thư mục:
/var/www/static/
├── index.html
├── css/style.css
├── js/app.js
└── images/logo.png
  1. Cấu hình Nginx serve các file này
  2. Set cache headers khác nhau cho từng loại file

Bài tập 3: Directory Listing

  1. Tạo virtual host cho files.local
  2. Bật autoindex
  3. Tùy chỉnh format và styling
  4. Test với nhiều files

Bài tập 4: Custom Error Pages

  1. Tạo custom 404 và 500 pages
  2. Apply cho một virtual host
  3. Test bằng cách truy cập URL không tồn tại
  4. Test 500 error (có thể fake bằng return 500)

Bài tập 5: Multiple Virtual Hosts

  1. Tạo 3 virtual hosts:
    • site1.local → /var/www/site1
    • site2.local → /var/www/site2
    • blog.site1.local → /var/www/blog
  2. Mỗi site có content khác nhau
  3. Configure và test tất cả

8. Troubleshooting thường gặp

Lỗi 1: 403 Forbidden

# Nguyên nhân: Permission
ls -la /var/www/html

Fix: Set đúng ownership

sudo chown -R www-data:www-data /var/www/html sudo chmod -R 755 /var/www/html

Nguyên nhân: SELinux (CentOS)

sudo setenforce 0

Lỗi 2: 404 Not Found

# Check root directive
location / {
root /var/www/html;  # Đường dẫn đúng chưa?
index index.html;    # File có tồn tại không?
}

Check với curl

curl -I http://example.com

Lỗi 3: Cấu hình không reload

# Test config trước
sudo nginx -t

Nếu OK thì reload

sudo systemctl reload nginx

Check error log

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

Lỗi 4: Server name không work

# Check DNS/hosts
cat /etc/hosts

Check server_name directive

grep server_name /etc/nginx/sites-available/*

Clear browser cache

Hoặc test với curl

curl -H "Host: mysite.com" http://localhost


9. Best Practices

  1. Tổ chức file cấu hình:
/etc/nginx/
├── nginx.conf (main config)
├── conf.d/ (global configs)
└── sites-available/ (individual sites)
  1. Comment rõ ràng:
# Block spam bots
if ($http_user_agent ~* (bot|crawler|spider)) {
return 403;
}
  1. Sử dụng include:
http {
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
}
  1. Test trước khi reload:
sudo nginx -t && sudo systemctl reload nginx
  1. Backup configs:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

Tổng kết

Trong bài này, bạn đã học:

  • ✅ Cú pháp và cấu trúc nginx.conf
  • ✅ Context và directive trong Nginx
  • ✅ Tạo và quản lý virtual hosts
  • ✅ Serving static files hiệu quả
  • ✅ Cấu hình index files và autoindex
  • ✅ Tùy chỉnh error pages

Bài tiếp theo: Chúng ta sẽ tìm hiểu về Logging và Monitoring - cách theo dõi và phân tích traffic trên Nginx server.