Chuyển đến nội dung chính (Skip to content)
Mục lục bài viết
Nginx

Cấu hình server block NGINX cho nhiều website

Cấu hình server block NGINX cho nhiều website

Tách tên miền bằng server block, phục vụ website tĩnh, kết nối PHP-FPM và chuyển tiếp đến ứng dụng. Kèm cách kiểm tra chọn đúng virtual host.

Trước khi bắt đầu. Một server block định nghĩa cách NGINX xử lý một nhóm tên miền. Tách file cấu hình giúp dễ bảo trì, nhưng không thay thế cô lập tài khoản, tiến trình hoặc quyền truy cập của ứng dụng.

Sơ đồ kiểm tra server block nginx
Hai nhánh kiểm tra ban đầu: dns hoặc ip sai hoặc đúng ip nhưng sai website. Chạm vào hình để mở bản lớn.

1. Bản chất cơ chế server block trong NGINX

Trong NGINX, khái niệm Server Block (tương đương với Virtual Host trong Apache) cho phép bạn lưu trữ và vận hành hàng chục tên miền, ứng dụng web hoàn toàn độc lập trên cùng một máy chủ vật lý hoặc VPS duy nhất.

Khi một request HTTP gửi tới máy chủ, NGINX thực hiện phân giải và định tuyến theo thứ tự ưu tiên chặt chẽ:

  • Khớp cổng và địa chỉ IP: NGINX kiểm tra chỉ thị listen (ví dụ: listen 80; hoặc listen 443;).
  • Khớp tên miền yêu cầu: NGINX đọc header Host của request và đối chiếu với danh sách tên miền khai báo trong directive server_name. Thứ tự khớp lần lượt là: Tên miền chính xác > Tên miền chứa ký tự đại diện bắt đầu (*.example.com) > Tên miền chứa ký tự đại diện kết thúc (mail.*) > Biểu thức chính quy (Regular Expression).
  • Default Server: Nếu không có Server Block nào khớp với header Host, NGINX sẽ chuyển request về khối có khai báo default_server trên cổng tương ứng.
Minh họa Host header → server_name → location
Luồng khái niệm: Host header → server_name → location. Chạm vào hình để mở bản lớn.

2. Cấu hình virtual host cho Static Website

Dưới đây là quy trình chuẩn để thiết lập một website tĩnh (HTML, CSS, JS) cho tên miền static.example.com.

Bước 2.1: Tạo thư mục web root và phân quyền người dùng

sudo mkdir -p /var/www/static.example.com/html
sudo chown -R www-data:www-data /var/www/static.example.com/html
sudo chmod -R 755 /var/www/static.example.com

Tạo một file kiểm tra đơn giản /var/www/static.example.com/html/index.html:

<!DOCTYPE html>
<html lang="vi">
<head><meta charset="UTF-8"><title>Static Site NGINX</title></head>
<body><h1>Xin chào từ static.example.com!</h1></body>
</html>

Bước 2.2: Tạo file cấu hình server block

Tạo file /etc/nginx/conf.d/static.example.com.conf với nội dung sau:

server {
    listen 80;
    listen [::]:80;
    server_name static.example.com;

    root /var/www/static.example.com/html;
    index index.html index.htm;

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

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

    # Cache tài nguyên tĩnh tối đa 30 ngày
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|webp|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

3. Tích hợp FastCGI PHP-FPM 8.2 / 8.3 qua UNIX Socket

Khác với Apache sử dụng mod_php nhúng trực tiếp, NGINX không xử lý mã nguồn PHP nội bộ mà đóng vai trò Reverse Proxy chuyển tiếp các file PHP sang trình xử lý FastCGI riêng biệt là PHP-FPM (PHP FastCGI Process Manager).

Kết nối qua UNIX Domain Socket đem lại hiệu năng vượt trội và tiết kiệm tài nguyên mạng hơn so với kết nối TCP Port (127.0.0.1:9000).

Tạo file cấu hình /etc/nginx/conf.d/app.example.com.conf:

server {
    listen 80;
    listen [::]:80;
    server_name app.example.com;

    root /var/www/app.example.com/public;
    index index.php index.html;

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

    # Chuyển tiếp toàn bộ request qua Front Controller (Laravel/WordPress)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Xử lý các file PHP qua PHP-FPM 8.3 UNIX Socket
    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_PROXY ""; # Khắc phục lỗ hổng httpoxy
        
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_read_timeout 60s;
    }

    # Chặn truy cập trực tiếp vào các file ẩn và file nhạy cảm
    location ~ /\.(?!well-known) {
        deny all;
        access_log off;
        log_not_found off;
    }
}

4. Cấu hình server block làm reverse proxy cho Node.js và Go

Trong kiến trúc phát triển ứng dụng hiện đại, NGINX thường đứng trước các ứng dụng chạy trên runtime độc lập như Node.js (Next.js/Express), Python (FastAPI/Django) hoặc Go (Gin/Fiber). NGINX tiếp nhận request từ Internet, xử lý mã hóa SSL và chuyển tiếp lưu lượng vào cổng ứng dụng nội bộ.

Tạo file /etc/nginx/conf.d/api.example.com.conf:

upstream nodejs_backend {
    server 127.0.0.1:3000;
    keepalive 32; # Tái sử dụng kết nối TCP để tối ưu hiệu năng
}

server {
    listen 80;
    server_name api.example.com;

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

    location / {
        proxy_pass http://nodejs_backend;
        proxy_http_version 1.1;
        
        # Thiết lập các header quan trọng để ứng dụng backend nhận đúng IP thật
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # Hỗ trợ giao thức WebSocket mượt mà
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

5. Tổ chức cấu hình dạng Modular với Snippets

Khi quản lý hàng chục Server Block, việc lặp đi lặp lại các đoạn cấu hình giống nhau (như cấu hình FastCGI, cấu hình header bảo mật hoặc SSL) sẽ khiến hệ thống khó bảo trì. Giải pháp là gom các đoạn cấu hình dùng chung vào thư mục /etc/nginx/snippets/.

Ví dụ tạo file /etc/nginx/snippets/fastcgi-php.conf:

fastcgi_split_path_info ^(.+\.php)(/.+)$;
try_files $fastcgi_script_name =404;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
try_files $uri =404;
        include fastcgi_params;

Trong các file Virtual Host, bạn chỉ cần một dòng duy nhất: include snippets/fastcgi-php.conf; để áp dụng trọn vẹn cấu hình.

6. Kiểm tra cú pháp và kích hoạt cấu hình

Mỗi khi tạo mới hoặc sửa đổi bất kỳ file cấu hình nào trong /etc/nginx/conf.d/, luôn thực thi quy trình kiểm tra an toàn:

# 1. Kiem tra tinh hop le cua toan bo cu phap
sudo nginx -t

# 2. Neu syntax is ok, tien hanh nap lai cau hinh
sudo systemctl reload nginx

Với phương pháp này, bạn đã thiết lập thành công nền tảng Virtual Host linh hoạt, sẵn sàng phục vụ website tĩnh, ứng dụng PHP hoặc hệ thống Microservices backend. Ở bài tiếp theo, chúng ta sẽ mã hóa toàn bộ lưu lượng web bằng chứng chỉ bảo mật SSL/TLS miễn phí từ Let's Encrypt.

Socket /run/php/php8.3-fpm.sock là ví dụ cho cách bố trí thường gặp trên Ubuntu; kiểm tra pool PHP-FPM, phiên bản, quyền truy cập và SELinux của máy thực tế. Không dùng đường dẫn này cho Rocky Linux nếu pool đang nghe socket khác. Mẫu WebSocket cần phục vụ đúng endpoint; không ép Connection: upgrade cho mọi request nếu ứng dụng không cần. Với 502, xem error log và thử kết nối trực tiếp đến upstream trước khi tăng timeout.

Nguồn đối chiếu và kiểm tra trước khi áp dụng

Các địa chỉ example.com, IP riêng và đường dẫn trong ví dụ cần thay theo môi trường thực tế. Các sơ đồ trong bài là minh họa khái niệm, không phải bằng chứng thử nghiệm trên hệ thống của bạn.

Trước khi áp dụng: sao lưu file cấu hình bị đổi, chạy sudo nginx -t, chỉ reload khi kiểm tra thành công, rồi xác nhận endpoint, error log và chức năng ứng dụng. Nếu lỗi xuất hiện, phục hồi file đã sao lưu, kiểm tra cú pháp và reload lại; không xóa hàng loạt cấu hình để thử.

Tìm hiểu thêm

Xem toàn bộ lộ trình Nginx