VPS

Nginx reverse proxy: một VPS chạy nhiều ứng dụng

Thanh Nguyễn Đăng 9 phút đọc 5 khối lệnh

Nginx reverse proxy: một VPS chạy nhiều ứng dụng
Mục lục bài viết
  1. Cấu hình cơ bản cho một ứng dụng
  2. HTTPS tự động
  3. Kết nối hai chiều và tải lên file lớn
  4. Chạy nhiều ứng dụng cho gọn
  5. Những lỗi hay gặp
  6. Bốn lỗi hay gặp
  7. Bộ lệnh kiểm
  8. Mỗi ứng dụng một tệp cấu hình theo tên miền
  9. Câu hỏi thường gặp
  10. Bài viết liên quan

Trả lời nhanh: Nginx reverse proxy đứng trước các ứng dụng của bạn, nhận mọi yêu cầu ở cổng 80 và 443 rồi chuyển tới đúng ứng dụng theo tên miền. Nhờ vậy một VPS phục vụ được nhiều trang, mỗi trang một tên miền, mà không cần thêm địa chỉ IP. Ba việc kèm theo phải làm đúng: cấp chứng chỉ HTTPS tự động, chuyển tiếp đúng tiêu đề để ứng dụng biết địa chỉ thật của khách, và bật hỗ trợ kết nối hai chiều nếu ứng dụng cần.

Có ba ứng dụng và một máy chủ, mỗi ứng dụng nghe một cổng khác nhau, nhưng khách không thể gõ số cổng vào trình duyệt. Đây là bài toán mà mọi người tự dựng hạ tầng đều gặp ở tuần đầu, và lời giải chuẩn là đặt một lớp trung chuyển phía trước.

Cấu hình cơ bản cho một ứng dụng

CodeCấu hình cơ bản cho một ứng dụngnginx
# /etc/nginx/sites-available/ung-dung-aserver {    listen 80;    server_name a.trangcuaban.vn;     location / {        proxy_pass http://127.0.0.1:3000;        proxy_http_version 1.1;         # Chuyen tiep thong tin that cua khach        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;    }}

Bốn dòng tiêu đề ở cuối quan trọng hơn vẻ ngoài. Không có chúng, ứng dụng của bạn nghĩ mọi khách đều đến từ chính máy chủ, nên phần ghi nhật ký, giới hạn tần suất và phân tích truy cập đều sai. Dòng cuối cũng cần cho ứng dụng biết khách đang dùng kết nối mã hóa, nếu không nó có thể tạo ra các đường dẫn sai giao thức.

Thêm ứng dụng thứ hai chỉ là thêm một khối tương tự với tên miền khác và cổng khác. Đó là toàn bộ ý tưởng.

HTTPS tự động

TerminalHTTPS tự độngbash
sudo apt install -y certbot python3-certbot-nginxsudo certbot --nginx -d a.trangcuaban.vn -d b.trangcuaban.vn # Kiem tra viec tu gia han hoat dongsudo certbot renew --dry-run

Công cụ này tự sửa cấu hình Nginx, tự chuyển hướng từ HTTP sang HTTPS, và tự gia hạn trước khi hết hạn. Lệnh cuối đáng chạy ngay sau khi cài: nó kiểm tra việc gia hạn tự động có chạy được không, thay vì để bạn phát hiện vào ngày chứng chỉ hết hạn.

Với nhiều tên miền, hãy cấp một lần cho tất cả thay vì cấp lẻ, nhờ vậy việc gia hạn cũng gọn. Nếu bạn thấy phần cấu hình chứng chỉ rườm rà, có lựa chọn thay thế tự lo hoàn toàn phần này, so sánh nằm ở bài riêng trong cụm.

Kết nối hai chiều và tải lên file lớn

Hai thứ mặc định không hoạt động và gây ra những lỗi khó hiểu nhất:

CodeKết nối hai chiều và tải lên file lớnnginx
location / {    proxy_pass http://127.0.0.1:3000;    proxy_http_version 1.1;     # Cho phep nang cap len ket noi hai chieu    proxy_set_header Upgrade $http_upgrade;    proxy_set_header Connection "upgrade";     # Ket noi dai khong bi cat sau 60 giay    proxy_read_timeout 3600s;} # Cho phep tai len file lon hon mac dinhclient_max_body_size 50M;

Thiếu hai dòng nâng cấp kết nối thì mọi tính năng thời gian thực im lặng không chạy, và thường bạn đi tìm lỗi trong mã nguồn ứng dụng. Thiếu dòng tăng thời gian chờ thì kết nối bị cắt sau một phút, tạo ra hiện tượng mất kết nối định kỳ rất khó hiểu.

Dòng cuối là nguyên nhân của lỗi tải file lớn thất bại: mặc định của Nginx khá nhỏ, và thông báo lỗi trả về không nói rõ nguyên nhân.

Chạy nhiều ứng dụng cho gọn

Vài quy ước giúp cấu hình không thành mớ hỗn độn sau nửa năm:

  • Mỗi ứng dụng một file cấu hình, đặt tên theo tên miền.
  • Ghi số cổng vào một bảng chung trong tài liệu nội bộ, tránh cảnh hai ứng dụng cùng chọn một cổng.
  • Cho ứng dụng chỉ nghe ở địa chỉ nội bộ, không nghe ra ngoài. Khi đó chỉ Nginx chạm tới được và bạn không phải lo ai đó gọi thẳng vào cổng.
  • Đặt trang mặc định trả về lỗi cho những yêu cầu không khớp tên miền nào, tránh việc một trang bất kỳ trở thành trang mặc định.

Nếu các ứng dụng chạy trong container thì cách bố trí gọn hơn nữa, xem bài Docker Compose nhiều service.

Những lỗi hay gặp

Lỗi cổng không kết nối được. Ứng dụng chưa chạy, hoặc đang nghe ở cổng khác. Kiểm tra bằng lệnh xem danh sách cổng đang mở trước khi sửa cấu hình Nginx.

Lỗi hết thời gian chờ. Ứng dụng xử lý quá lâu. Tăng thời gian chờ là cách chữa triệu chứng; nguyên nhân thường nằm ở truy vấn database, theo bài database chậm.

Vòng lặp chuyển hướng. Thường do ứng dụng không biết khách đang dùng kết nối mã hóa nên cứ chuyển hướng lại. Đây chính là lý do phải có dòng chuyển tiếp giao thức.

Đổi cấu hình mà không thấy tác dụng. Luôn kiểm tra cú pháp rồi nạp lại:

TerminalNhững lỗi hay gặpbash
sudo nginx -t && sudo systemctl reload nginx

Lệnh kiểm tra trước rất đáng làm thành thói quen: một lỗi cú pháp nhỏ mà bạn khởi động lại luôn thì Nginx không lên, và mọi trang trên máy cùng chết.

Bốn lỗi hay gặp

LỗiTriệu chứngCách sửa
Quên đặt các tiêu đề chuyển tiếpỨng dụng thấy sai địa chỉ khách và sai giao thức, sinh chuyển hướng vòng lặpĐặt đủ bốn tiêu đề chuyển tiếp
Giới hạn kích thước tải lên ở lớp gác cổng thấp hơn ứng dụngTải tệp lớn báo lỗi mà ứng dụng không ghi nhận gìĐặt hai nơi cùng một con số
Không cấu hình cho kết nối hai chiềuKết nối thời gian thực bị ngắt sau vài chục giâyBật nâng cấp giao thức và tăng thời gian chờ
Không kiểm cấu hình trước khi nạp lạiMột dấu chấm phẩy thiếu làm cả mười trang cùng chếtLuôn chạy lệnh kiểm trước

Bộ lệnh kiểm

TerminalBộ lệnh kiểmbash
# LUON kiem cau hinh truoc khi nap lainginx -t && systemctl reload nginx # Xem cac ung dung dang lang nghe tren cong noi boss -ltnp | grep 127.0.0.1 # Kiem tung site tra ve dungfor d in site1.vn site2.vn site3.vn; do  echo -n "$d: "; curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" https://$ddone # Kiem chung chi con han bao laufor d in site1.vn site2.vn; do  echo -n "$d: "; echo | openssl s_client -connect $d:443 2>/dev/null | openssl x509 -noout -enddatedone # Kiem tieu de chuyen tiep da dat chuacurl -sI https://site1.vn | head -8

Mỗi ứng dụng một tệp cấu hình theo tên miền

  • Mỗi ứng dụng một tệp cấu hình riêng, đặt tên theo tên miền. Gộp tất cả vào một tệp là cách chắc chắn để một lỗi làm chết tất cả.
  • Mỗi ứng dụng nghe trên một cổng nội bộ riêng, chỉ nghe trên địa chỉ nội bộ, không mở ra internet.
  • Ghi lại ứng dụng nào ở cổng nào trong một tệp ghi chú. Sau mười ứng dụng thì không ai nhớ nổi.
  • Đặt giới hạn kích thước nhật ký, vì mười trang sinh nhật ký nhanh gấp mười và ổ đầy làm mọi trang cùng chết.

Về khái niệm và cách bố trí, xem bài về lớp gác cổng.

Câu hỏi thường gặp

Một VPS chạy được bao nhiêu trang?

Giới hạn nằm ở tài nguyên chứ không ở Nginx. Bản thân lớp trung chuyển rất nhẹ. Cái tốn là các ứng dụng phía sau, nên hãy đếm theo tổng RAM và CPU mà chúng cần chứ đừng đếm theo số tên miền.

Có cần nhiều địa chỉ IP cho nhiều tên miền không?

Không. Nginx phân biệt theo tên miền trong yêu cầu, nên một địa chỉ IP phục vụ được rất nhiều trang. Đây chính là lý do cách bố trí này phổ biến.

Vì sao tính năng thời gian thực không chạy?

Thường vì thiếu hai dòng cho phép nâng cấp kết nối trong khối cấu hình, hoặc vì thời gian chờ mặc định cắt kết nối sau một phút. Cả hai đều là cấu hình phía Nginx chứ không phải lỗi ứng dụng.

Nginx có làm chậm ứng dụng không?

Không đáng kể, và thường còn nhanh hơn vì nó phục vụ file tĩnh rất tốt, xử lý nén và giữ kết nối hiệu quả. Phần chậm nếu có nằm ở ứng dụng phía sau chứ không ở lớp trung chuyển.

Chia sẻ:Facebook

Thanh Nguyễn

TND

Tư vấn bản quyền, VPS và máy chủ kèm hóa đơn VAT, hợp đồng đầy đủ cho doanh nghiệp.