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

Bài 3: Logging và Monitoring Nginx

Bài học về logging và monitoring Nginx với access log, error log, custom log format, và log rotation. Hướng dẫn phân tích logs, troubleshooting, sử dụng logrotate, và các metrics cơ bản để theo dõi hiệu suất server. Bao gồm ví dụ thực tế và best practices.

🔒 DevSecOps — Bài 3 Bài 3: Logging và Monitoring Nginx

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

Phần 1: Cơ bản

xdev.asia

1. Access Log và Error Log

Nginx có hai loại log chính để theo dõi hoạt động của server: Access log (ghi lại tất cả requests) và Error log (ghi lại errors và warnings).

1.1. Access Log

Access log ghi lại mọi request đến server, bao gồm thông tin về client, request, response status, và thời gian xử lý.

Vị trí mặc định:

# Ubuntu/Debian
/var/log/nginx/access.log

CentOS/RHEL

/var/log/nginx/access.log

macOS (Homebrew)

/usr/local/var/log/nginx/access.log

Cấu hình cơ bản:

http {
# Access log cho toàn bộ HTTP context
access_log /var/log/nginx/access.log;

server {
    listen 80;
    server_name example.com;
    
    # Access log riêng cho virtual host
    access_log /var/log/nginx/example.com.access.log;
    
    location / {
        root /var/www/html;
    }
    
    # Tắt access log cho location cụ thể
    location /health-check {
        access_log off;
        return 200 "OK\n";
    }
}

}

Format mặc định (combined):

192.168.1.100 - - [03/Dec/2024:10:30:45 +0700] "GET /index.html HTTP/1.1" 200 1234 "https://google.com" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

Giải thích các trường:

  • 192.168.1.100 - IP address của client
  • - - Remote user (thường là - nếu không có authentication)
  • - - Authenticated user
  • [03/Dec/2024:10:30:45 +0700] - Timestamp
  • "GET /index.html HTTP/1.1" - Request method, URI, và HTTP version
  • 200 - HTTP status code
  • 1234 - Response body size (bytes)
  • "https://google.com" - Referer
  • "Mozilla/5.0..." - User Agent

1.2. Error Log

Error log ghi lại các lỗi, warnings và debug information từ Nginx.

Vị trí mặc định:

/var/log/nginx/error.log

Log levels (từ ít đến nhiều chi tiết):

  1. emerg - Emergency: system unusable
  2. alert - Alert: action must be taken immediately
  3. crit - Critical conditions
  4. error - Error conditions
  5. warn - Warning conditions
  6. notice - Normal but significant
  7. info - Informational
  8. debug - Debug messages

Cấu hình:

# Global error log
error_log /var/log/nginx/error.log warn;

http { # HTTP-level error log error_log /var/log/nginx/http-error.log error;

server {
    listen 80;
    server_name example.com;
    
    # Server-level error log
    error_log /var/log/nginx/example.com.error.log error;
    
    # Debug log cho troubleshooting
    error_log /var/log/nginx/debug.log debug;
}

}

Ví dụ error log entries:

2024/12/03 10:30:45 [error] 1234#1234: *1 open() "/var/www/html/notfound.html" failed (2: No such file or directory), client: 192.168.1.100, server: example.com, request: "GET /notfound.html HTTP/1.1", host: "example.com"

2024/12/03 10:31:20 [warn] 1234#1234: *2 upstream server temporarily disabled while connecting to upstream, client: 192.168.1.101, server: api.example.com, request: "GET /api/users HTTP/1.1", upstream: "http://192.168.1.200:3000/api/users"

2024/12/03 10:32:05 [crit] 1234#1234: malloc() 8192 bytes failed (12: Cannot allocate memory)

1.3. Xem và theo dõi logs real-time

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

Xem error log

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

Xem 100 dòng cuối

sudo tail -n 100 /var/log/nginx/access.log

Xem cả 2 logs cùng lúc

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

Filter logs

sudo tail -f /var/log/nginx/access.log | grep "404" sudo tail -f /var/log/nginx/access.log | grep "192.168.1.100"

Xem logs với less (có thể scroll)

sudo less +F /var/log/nginx/access.log

1.4. Phân tích logs cơ bản

Đếm số requests:

# Tổng số requests
wc -l /var/log/nginx/access.log

Requests trong 1 giờ qua

sudo awk -v date="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" '$4 > "["date' /var/log/nginx/access.log | wc -l

Top 10 IPs:

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

Top 10 URLs được truy cập:

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

Số lượng HTTP status codes:

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

Top User Agents:

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

Requests per hour:

sudo awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-2 | sort | uniq -c

2. Định dạng Log Tùy chỉnh

Nginx cho phép tạo custom log format để thu thập đúng thông tin bạn cần.

2.1. Log Format cơ bản

Định nghĩa format:

http {
# Format mặc định (combined)
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

# Format đơn giản hơn
log_format simple '$remote_addr - $request - $status';

# Format chi tiết
log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';

server {
    listen 80;
    
    # Sử dụng format tùy chỉnh
    access_log /var/log/nginx/access.log detailed;
}

}

2.2. Các biến thường dùng trong log format

Client information:

$remote_addr          # IP của client
$remote_user          # HTTP authenticated user
$http_x_forwarded_for # IP thật nếu đằng sau proxy/CDN

Request information:

$time_local           # Local time
$time_iso8601         # ISO 8601 time
$request              # Full request line
$request_method       # GET, POST, etc.
$request_uri          # Request URI with arguments
$uri                  # Current URI
$args                 # Query string arguments
$query_string         # Same as $args
$scheme               # http or https
$server_protocol      # HTTP/1.1, HTTP/2.0
$host                 # Host header
$server_name          # Server name

Response information:

$status               # HTTP status code
$body_bytes_sent      # Response body size
$bytes_sent           # Total bytes sent (headers + body)
$request_length       # Request length (including headers)

Timing information:

$request_time         # Request processing time (seconds)
$upstream_response_time    # Backend response time
$upstream_connect_time     # Time to connect to upstream
$upstream_header_time      # Time to receive upstream headers

Upstream information:

$upstream_addr             # Upstream server address
$upstream_status           # Upstream response status
$upstream_cache_status     # Cache status (HIT, MISS, etc.)

Headers:

$http_user_agent      # User-Agent header
$http_referer         # Referer header
$http_cookie          # Cookie header
$http_<header_name>   # Any HTTP header (lowercase with underscores)

2.3. Ví dụ Log Formats thực tế

Performance monitoring format:

log_format performance '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent '
'rt=$request_time '
'uct=$upstream_connect_time '
'uht=$upstream_header_time '
'urt=$upstream_response_time';

server { listen 80; access_log /var/log/nginx/performance.log performance; }

Output:

192.168.1.100 - [03/Dec/2024:10:30:45 +0700] "GET /api/users HTTP/1.1" 200 1234 rt=0.125 uct=0.005 uht=0.050 urt=0.120

JSON format (dễ parse):

log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';

server { listen 80; access_log /var/log/nginx/access.json json_combined; }

Output:

{"time_local":"03/Dec/2024:10:30:45 +0700","remote_addr":"192.168.1.100","request":"GET /index.html HTTP/1.1","status":200,"body_bytes_sent":1234,"request_time":0.005,"http_referer":"https://google.com","http_user_agent":"Mozilla/5.0"}

Security monitoring format:

log_format security '$remote_addr - [$time_local] '
'"$request" $status '
'"$http_user_agent" '
'"$http_x_forwarded_for" '
'host=$host '
'args=$args';

server { listen 80; access_log /var/log/nginx/security.log security; }

CDN/Proxy format:

log_format cdn '$http_x_forwarded_for - $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'cache=$upstream_cache_status';

server { listen 80; access_log /var/log/nginx/cdn.log cdn; }

2.4. Conditional Logging

Log chỉ khi có điều kiện:

http {
# Định nghĩa map để check conditions
map $status $loggable {
~^[23]  0;  # Don't log 2xx và 3xx
default 1;  # Log tất cả còn lại
}

server {
    listen 80;
    
    # Chỉ log nếu $loggable = 1
    access_log /var/log/nginx/errors-only.log combined if=$loggable;
}

}

Không log static files:

map $request_uri $log_static {
~*.(jpg|jpeg|png|gif|ico|css|js)$ 0;
default 1;
}

server { listen 80; access_log /var/log/nginx/access.log combined if=$log_static; }

Không log health checks:

map $request_uri $log_health {
~^/health$ 0;
~^/ping$ 0;
default 1;
}

server { listen 80; access_log /var/log/nginx/access.log combined if=$log_health; }

Không log bots:

map $http_user_agent $log_bots {
~bot 0;
~crawler 0;
~*spider 0;
default 1;
}

server { listen 80; access_log /var/log/nginx/access.log combined if=$log_bots; }

2.5. Multiple Access Logs

server {
listen 80;
server_name example.com;

# Log tất cả requests
access_log /var/log/nginx/all.log combined;

# Log chỉ errors
access_log /var/log/nginx/errors.log combined if=$loggable;

# Log performance
access_log /var/log/nginx/performance.log performance;

# Log JSON cho processing
access_log /var/log/nginx/json.log json_combined;

}


3. Log Rotation với Logrotate

Log files có thể phình to rất nhanh. Log rotation giúp quản lý dung lượng bằng cách tự động nén và xóa logs cũ.

3.1. Logrotate cơ bản

File cấu hình mặc định:

# Ubuntu/Debian
/etc/logrotate.d/nginx

CentOS/RHEL

/etc/logrotate.d/nginx

Nội dung mặc định:

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

Giải thích directives:

  • daily - Rotate mỗi ngày
  • missingok - Không báo lỗi nếu log file không tồn tại
  • rotate 14 - Giữ 14 bản backup
  • compress - Nén logs cũ bằng gzip
  • delaycompress - Chờ đến lần rotate sau mới nén
  • notifempty - Không rotate nếu file rỗng
  • create 0640 www-data adm - Tạo file mới với permissions
  • sharedscripts - Chạy postrotate script 1 lần cho tất cả logs
  • postrotate/endscript - Script chạy sau rotation

3.2. Custom Logrotate Configuration

Rotate hourly (cho high-traffic sites):

sudo nano /etc/logrotate.d/nginx-hourly

Nội dung:

/var/log/nginx/high-traffic.log { hourly rotate 168 # 7 days * 24 hours compress delaycompress notifempty create 0640 www-data adm dateext dateformat -%Y%m%d-%H sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 cat /var/run/nginx.pid fi endscript }

Rotate theo size:

/var/log/nginx/.log {
size 100M           # Rotate khi đạt 100MB
rotate 10
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 cat /var/run/nginx.pid
fi
endscript
}

Rotate với custom naming:

/var/log/nginx/.log {
daily
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
dateext
dateformat -.%Y-%m-%d
extension .log
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 cat /var/run/nginx.pid
fi
endscript
}

Output: access.log-2024-12-03.log.gz

Separate rotation cho từng log:

# Performance logs - giữ lâu hơn
/var/log/nginx/performance.log {
daily
rotate 90           # 3 months
compress
delaycompress
notifempty
create 0640 www-data adm
}

Error logs - giữ rất lâu

/var/log/nginx/error.log { weekly rotate 52 # 1 year compress delaycompress notifempty create 0640 www-data adm }

Access logs - rotate nhanh

/var/log/nginx/access.log { daily rotate 7 # 1 week compress delaycompress notifempty create 0640 www-data adm }

3.3. Test và Force Rotation

# Test cấu hình (dry run)
sudo logrotate -d /etc/logrotate.d/nginx

Force rotation (thực thi ngay)

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

Check status

sudo cat /var/lib/logrotate/status

Manual rotation (không dùng logrotate)

sudo mv /var/log/nginx/access.log /var/log/nginx/access.log.1 sudo nginx -s reopen sudo gzip /var/log/nginx/access.log.1

3.4. Troubleshooting Logrotate

Kiểm tra logrotate có chạy không:

# Check cron job
ls -la /etc/cron.daily/logrotate

Check logrotate status

sudo cat /var/lib/logrotate/status | grep nginx

Run logrotate manually với verbose

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

Lỗi thường gặp:

# Lỗi: Permission denied

Fix: Check ownership

ls -la /var/log/nginx/ sudo chown www-data:adm /var/log/nginx/*.log

Lỗi: Nginx không reopen logs

Fix: Check PID file

ls -la /var/run/nginx.pid sudo systemctl restart nginx

Lỗi: Logs không được nén

Fix: Check gzip installed

which gzip sudo apt install gzip


4. Các Metrics Cơ bản để Theo dõi

4.1. Requests per Second (RPS)

Script để tính RPS:

#!/bin/bash

rps.sh - Calculate requests per second

LOG_FILE="/var/log/nginx/access.log" INTERVAL=60 # seconds

while true; do START_COUNT=$(wc -l < "$LOG_FILE") sleep $INTERVAL END_COUNT=$(wc -l < "$LOG_FILE")

REQUESTS=$((END_COUNT - START_COUNT))
RPS=$(echo "scale=2; $REQUESTS / $INTERVAL" | bc)

echo "$(date '+%Y-%m-%d %H:%M:%S') - RPS: $RPS"

done

Chạy script:

chmod +x rps.sh
./rps.sh

4.2. Response Time Analysis

Script phân tích response time:

#!/bin/bash

response_time.sh - Analyze response times

LOG_FILE="/var/log/nginx/access.log"

echo "Response Time Statistics:" echo "========================"

Extract request_time (assuming it's logged)

awk '{print $NF}' "$LOG_FILE" |
awk '{ sum += $1; count++; if ($1 > max) max = $1; if (min == 0 || $1 < min) min = $1; } END { print "Average: " sum/count " seconds"; print "Min: " min " seconds"; print "Max: " max " seconds"; }'

4.3. Status Code Distribution

#!/bin/bash

status_codes.sh - Count HTTP status codes

LOG_FILE="/var/log/nginx/access.log"

echo "HTTP Status Code Distribution:" echo "=============================="

awk '{print $9}' "$LOG_FILE" | sort | uniq -c | sort -rn |
while read count code; do percentage=$(echo "scale=2; ($count * 100) / $(wc -l < $LOG_FILE)" | bc) printf "%3s: %6d requests (%5.2f%%)\n" "$code" "$count" "$percentage" done

4.4. Traffic by Hour

#!/bin/bash

traffic_by_hour.sh - Analyze traffic by hour

LOG_FILE="/var/log/nginx/access.log"

echo "Traffic by Hour:" echo "================"

awk '{print $4}' "$LOG_FILE" | cut -d: -f2 | sort | uniq -c |
while read count hour; do printf "Hour %02d: %6d requests\n" "$hour" "$count" done

4.5. Top Clients (IP Addresses)

#!/bin/bash

top_clients.sh - Find top clients by requests

LOG_FILE="/var/log/nginx/access.log" TOP_N=10

echo "Top $TOP_N Clients:" echo "=================="

awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -n $TOP_N |
while read count ip; do printf "%15s: %6d requests\n" "$ip" "$count" done

4.6. Bandwidth Usage

#!/bin/bash

bandwidth.sh - Calculate bandwidth usage

LOG_FILE="/var/log/nginx/access.log"

echo "Bandwidth Statistics:" echo "===================="

Assuming $body_bytes_sent is in position 10

awk '{sum += $10} END { gb = sum / 1024 / 1024 / 1024; mb = sum / 1024 / 1024; kb = sum / 1024; printf "Total: %.2f GB (%.2f MB, %.2f KB)\n", gb, mb, kb; }' "$LOG_FILE"

4.7. Real-time Dashboard Script

#!/bin/bash

dashboard.sh - Real-time Nginx monitoring dashboard

LOG_FILE="/var/log/nginx/access.log"

while true; do clear echo "===================================" echo " NGINX MONITORING DASHBOARD" echo "===================================" echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" echo

# Total requests
TOTAL=$(wc -l &lt; "$LOG_FILE")
echo "Total Requests: $TOTAL"
echo

# Last minute requests
LAST_MINUTE=$(tail -n 1000 "$LOG_FILE" | wc -l)
echo "Last ~1000 requests"
echo

# Status codes (last 1000)
echo "Status Codes (recent):"
tail -n 1000 "$LOG_FILE" | awk '{print $9}' | sort | uniq -c | sort -rn
echo

# Top 5 IPs (recent)
echo "Top 5 IPs (recent):"
tail -n 1000 "$LOG_FILE" | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
echo

# Top 5 URLs (recent)
echo "Top 5 URLs (recent):"
tail -n 1000 "$LOG_FILE" | awk '{print $7}' | sort | uniq -c | sort -rn | head -5

sleep 5

done

Chạy dashboard:

chmod +x dashboard.sh
./dashboard.sh

4.8. Gửi Alerts khi có vấn đề

#!/bin/bash

alert.sh - Send alert when error rate is high

LOG_FILE="/var/log/nginx/access.log" ERROR_THRESHOLD=10 # % of 5xx errors EMAIL="[email protected]"

Count last 100 requests

TOTAL=$(tail -n 100 "$LOG_FILE" | wc -l) ERRORS=$(tail -n 100 "$LOG_FILE" | awk '{print $9}' | grep "^5" | wc -l)

ERROR_RATE=$(echo "scale=2; ($ERRORS * 100) / $TOTAL" | bc)

if (( $(echo "$ERROR_RATE > $ERROR_THRESHOLD" | bc -l) )); then MESSAGE="ALERT: High error rate detected! $ERROR_RATE% of requests are 5xx errors" echo "$MESSAGE" | mail -s "Nginx Alert" "$EMAIL" echo "$MESSAGE" fi

4.9. Integration với Monitoring Tools

Export metrics cho Prometheus:

# Install nginx-prometheus-exporter
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
tar xzf nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/

Run exporter

nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:8080/stub_status

Configure Nginx stub_status:

server {
listen 8080;
server_name localhost;

location /stub_status {
    stub_status;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

}


5. Bài tập Thực hành

Bài tập 1: Custom Log Format

  1. Tạo custom log format có tên timing bao gồm:
    • Remote address
    • Request
    • Status
    • Request time
    • Upstream response time
  2. Apply format này cho một virtual host
  3. Generate traffic và xem logs

Bài tập 2: JSON Logging

  1. Tạo JSON log format
  2. Configure Nginx để log ra JSON
  3. Parse JSON logs bằng jq:
cat /var/log/nginx/access.json | jq '.status'
cat /var/log/nginx/access.json | jq 'select(.status >= 400)'

Bài tập 3: Log Rotation

  1. Tạo custom logrotate config rotate theo size 10MB
  2. Test với logrotate -d
  3. Force rotation và verify

Bài tập 4: Traffic Analysis

  1. Generate 1000 requests với ab:
ab -n 1000 -c 10 http://localhost/
  1. Phân tích logs để tìm:
    • Total requests
    • Average response time
    • Status code distribution
    • Top URLs

Bài tập 5: Real-time Monitoring

  1. Setup dashboard script
  2. Modify để thêm:
    • Error rate (%)
    • Bandwidth usage
    • Slowest requests

Bài tập 6: Conditional Logging

  1. Configure để không log:
    • Static files (.css, .js, .jpg, .png)
    • Health check endpoint (/health)
    • Bot traffic
  2. Verify rằng những requests này không xuất hiện trong logs

6. Troubleshooting với Logs

6.1. Debug 404 Errors

# Tìm tất cả 404s
grep " 404 " /var/log/nginx/access.log

Top URLs gây 404

grep " 404 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10

404s từ IP cụ thể

grep "192.168.1.100" /var/log/nginx/access.log | grep " 404 "

6.2. Debug 500 Errors

# Tìm 5xx errors
grep " 50[0-9] " /var/log/nginx/access.log

Check error log cho details

sudo tail -100 /var/log/nginx/error.log | grep "error"

5xx errors theo thời gian

grep " 50[0-9] " /var/log/nginx/access.log | awk '{print $4}' | cut -d: -f1-2 | uniq -c

6.3. Debug Slow Requests

# Tìm requests > 1 second (assuming request_time is logged)
awk '$NF > 1.0' /var/log/nginx/access.log

Top 10 slowest requests

awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -10

6.4. Debug High Traffic

# Requests per minute
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-3 | uniq -c

Identify traffic spikes

awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-3 | uniq -c | awk '$1 > 1000'

6.5. Debug Security Issues

# Tìm SQL injection attempts
grep -i "select.*from|union.*select" /var/log/nginx/access.log

Tìm path traversal attempts

grep ".." /var/log/nginx/access.log

Suspicious user agents

grep -i "sqlmap|nikto|nmap" /var/log/nginx/access.log


7. Best Practices

7.1. Log Management

  1. Separate logs cho từng virtual host:
server {
server_name site1.com;
access_log /var/log/nginx/site1.access.log;
error_log /var/log/nginx/site1.error.log;
}
  1. Sử dụng log levels phù hợp:
# Production: error hoặc warn
error_log /var/log/nginx/error.log warn;

Development: info hoặc debug

error_log /var/log/nginx/error.log debug;

  1. Không log quá nhiều:
# Disable cho static files
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
access_log off;
}

Disable cho health checks

location /health { access_log off; return 200; }

7.2. Performance

  1. Buffer logs:
access_log /var/log/nginx/access.log combined buffer=32k;
  1. Async logging (Nginx 1.7.11+):
access_log /var/log/nginx/access.log combined buffer=32k flush=5s;

7.3. Security

  1. Protect log files:
sudo chmod 640 /var/log/nginx/.log
sudo chown www-data:adm /var/log/nginx/.log
  1. Rotate regularly:
# Daily rotation cho high-traffic sites

Weekly cho low-traffic sites

  1. Monitor và alert:
# Setup monitoring cho error rates

Alert khi có spikes bất thường


Tổng kết

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

  • ✅ Access log và error log
  • ✅ Custom log formats và variables
  • ✅ Log rotation với logrotate
  • ✅ Phân tích logs và metrics
  • ✅ Troubleshooting với logs
  • ✅ Best practices cho logging

Bài tiếp theo: Chúng ta sẽ tìm hiểu về Reverse Proxy - cách sử dụng Nginx làm reverse proxy cho backend applications.