Lab 9 — Web Server & Reverse Proxy
1. Mục tiêu
Ở các lab trước, chúng ta đã đi qua:
Ảnh Minh hoạ |
||
|---|---|---|
![]() |
![]() |
![]() |
Trong thực tế, client thường không truy cập trực tiếp application.
Ảnh Minh hoạ |
||
|---|---|---|
![]() |
![]() |
![]() |
Sau lab này, bạn sẽ:
- Hiểu Web Server là gì.
- Hiểu Reverse Proxy là gì.
- Cài đặt và cấu hình Nginx.
- Serve static file bằng Nginx.
- Forward request từ Nginx tới Backend.
- Hiểu
proxy_pass. - Biết cách debug Nginx.
- Hiểu mô hình thường gặp trong production.
2. Web Server là gì?
Web Server là phần mềm nhận HTTP request và trả HTTP response.
Ví dụ:
Ảnh Minh hoạ |
||
|---|---|---|
![]() |
![]() |
![]() |
Các Web Server phổ biến:
Nginx
Apache
Caddy
Trong lab này sử dụng Nginx.
3. Nginx có thể làm gì?
Nginx không chỉ serve HTML.
Nó thường được sử dụng để:
Nginx
├── Static Web Server
├── Reverse Proxy
├── Load Balancer
├── TLS/HTTPS Termination
└── HTTP Gateway
Trong production, một kiến trúc rất phổ biến là:
Internet
│
▼
Nginx
│
▼
Backend
4. Reverse Proxy là gì?
Đây là khái niệm quan trọng nhất của lab.
Giả sử Backend chạy:
127.0.0.1:8080
Client không truy cập trực tiếp:
http://server:8080
Thay vào đó:
Client
│
│ :80
▼
Nginx
│
│ :8080
▼
Backend
Nginx nhận request rồi forward request tới Backend.
Đó gọi là:
Reverse Proxy
5. Reverse Proxy khác Forward Proxy thế nào?
Forward Proxy
Proxy đại diện cho Client:
Client
│
▼
Forward Proxy
│
▼
Internet
Reverse Proxy
Proxy đại diện cho Server:
Client
│
▼
Reverse Proxy
│
▼
Backend
Trong DevOps, bạn sẽ gặp Reverse Proxy thường xuyên hơn.
6. Tại sao cần Reverse Proxy?
Nếu expose trực tiếp:
Internet
│
▼
Spring Boot :8080
thì application phải xử lý trực tiếp traffic từ Internet.
Một mô hình tốt hơn:
Internet
│
▼
Nginx :443
│
▼
Spring Boot :8080
Nginx có thể đảm nhiệm:
- HTTPS.
- Routing.
- Access log.
- Rate limiting.
- Load balancing.
- Security headers.
- Static files.
Backend chỉ cần tập trung xử lý business logic.
7. Cài Nginx
Trên Ubuntu:
sudo apt update
sudo apt install nginx
Kiểm tra:
nginx -v
Ví dụ:
nginx version: nginx/1.24.x
Kiểm tra service:
sudo systemctl status nginx
8. Kiểm tra Nginx
Mở browser:
http://SERVER_IP
Hoặc:
curl http://localhost
Nếu thành công, bạn sẽ nhận HTML mặc định của Nginx.
Kiểm tra port:
sudo ss -lntp | grep nginx
Thông thường:
0.0.0.0:80
Nginx đang listen trên HTTP port 80.
9. Nginx Configuration
Các file quan trọng thường nằm ở:
/etc/nginx/
Kiểm tra:
ls /etc/nginx
Bạn sẽ thường gặp:
nginx.conf
sites-available/
sites-enabled/
conf.d/
10. nginx.conf
File chính:
/etc/nginx/nginx.conf
Xem:
sudo cat /etc/nginx/nginx.conf
Bạn có thể thấy:
http {
...
include /etc/nginx/sites-enabled/*;
}
Điều này có nghĩa Nginx sẽ load các configuration trong:
/etc/nginx/sites-enabled/
11. sites-available và sites-enabled
Một convention phổ biến:
sites-available/
│
│ configuration
▼
sites-enabled/
│
▼
Nginx
Ví dụ:
/etc/nginx/sites-available/myapp
Sau đó tạo symbolic link:
sudo ln -s \
/etc/nginx/sites-available/myapp \
/etc/nginx/sites-enabled/myapp
Có thể hiểu:
sites-available
↓
Available
sites-enabled
↓
Active
12. Tạo Static Website
Tạo thư mục:
sudo mkdir -p /var/www/lab9
Tạo HTML:
echo "Hello from Nginx" | sudo tee /var/www/lab9/index.html
Tạo config:
sudo nano /etc/nginx/sites-available/lab9
Nội dung:
server {
listen 80;
server_name _;
root /var/www/lab9;
index index.html;
}
13. Enable Website
Tạo symbolic link:
sudo ln -s \
/etc/nginx/sites-available/lab9 \
/etc/nginx/sites-enabled/lab9
Kiểm tra configuration:
sudo nginx -t
Nếu:
syntax is ok
test is successful
thì configuration hợp lệ.
Đây là command phải nhớ.
Trước khi reload Nginx:
sudo nginx -t
14. Reload Nginx
Sau khi configuration hợp lệ:
sudo systemctl reload nginx
Test:
curl http://localhost
Kết quả:
Hello from Nginx
15. Reload vs Restart
Đây là một kinh nghiệm thực tế quan trọng.
Reload
sudo systemctl reload nginx
Nginx đọc lại configuration mà không cần dừng service theo cách restart.
Thường dùng khi:
Thay đổi configuration
Restart
sudo systemctl restart nginx
Dừng rồi khởi động lại service.
Trong production:
Nếu chỉ thay đổi config, ưu tiên
nginx -trồireload.
16. Nginx làm Reverse Proxy
Bây giờ chúng ta tạo Backend giả.
Chạy:
mkdir ~/backend
cd ~/backend
echo "Hello from Backend" > index.html
python3 -m http.server 8080
Kiểm tra:
curl http://localhost:8080
Kết quả:
Hello from Backend
Kiến trúc hiện tại:
Client
│
├── :80 → Nginx
│
└── :8080 → Backend
17. Cấu hình Reverse Proxy
Sửa:
sudo nano /etc/nginx/sites-available/lab9
Dùng:
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
Kiểm tra:
sudo nginx -t
Sau đó:
sudo systemctl reload nginx
18. Test
Bây giờ:
curl http://localhost
Bạn nhận:
Hello from Backend
Nhưng request thực tế là:
Client
│
│ :80
▼
Nginx
│
│ :8080
▼
Backend
Client không cần biết Backend đang chạy port 8080.
19. proxy_pass là gì?
Dòng:
proxy_pass http://127.0.0.1:8080;
có nghĩa:
Khi request vào location này, Nginx chuyển request tới Backend ở
127.0.0.1:8080.
Ví dụ:
GET /
│
▼
Nginx :80
│
▼
127.0.0.1:8080
20. Routing theo Path
Đây là khả năng rất hữu ích của Reverse Proxy.
Ví dụ:
/api
↓
Backend :8080
/admin
↓
Admin App :3000
Nginx:
server {
listen 80;
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
location /admin/ {
proxy_pass http://127.0.0.1:3000;
}
}
Kiến trúc:
Nginx
│
┌────────┴────────┐
│ │
/api /admin
│ │
▼ ▼
Backend Admin App
:8080 :3000
Đây là một mô hình rất phổ biến.
21. Routing theo Domain
Bạn cũng có thể route dựa trên domain:
api.example.com
↓
Backend :8080
admin.example.com
↓
Admin :3000
Ví dụ:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
và:
server {
listen 80;
server_name admin.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
22. Forwarded Headers
Khi Nginx proxy request, Backend có thể không biết IP thật của Client nếu không cấu hình đúng.
Thường sử dụng:
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
Các header quan trọng:
Host
X-Real-IP
X-Forwarded-For
X-Forwarded-Proto
Có thể hiểu:
Client
│
│ IP = 1.2.3.4
▼
Nginx
│
│ X-Real-IP: 1.2.3.4
▼
Backend
Backend có thể sử dụng thông tin này để biết request ban đầu đến từ đâu.
23. Tại sao X-Forwarded-For quan trọng?
Nếu không có reverse proxy:
Client
↓
Backend
Backend thấy:
Client IP
Nhưng khi có Nginx:
Client
↓
Nginx
↓
Backend
Backend có thể chỉ nhìn thấy:
Nginx IP
Vì vậy proxy cần truyền thông tin Client IP.
Đặc biệt quan trọng cho:
- Access log.
- Rate limiting.
- Audit.
- Security.
- Application monitoring.
24. Nginx Logs
Đây là một trong những thứ bạn sẽ dùng rất nhiều khi troubleshooting.
Thông thường:
/var/log/nginx/access.log
/var/log/nginx/error.log
Xem access log:
sudo tail -f /var/log/nginx/access.log
Xem error log:
sudo tail -f /var/log/nginx/error.log
Sau đó:
curl http://localhost
Bạn sẽ thấy request xuất hiện trong access log.
25. Debug 502 Bad Gateway
Một lỗi cực kỳ quan trọng.
Giả sử:
Client
↓
Nginx
↓
Backend :8080
Backend chết:
Backend :8080
X
Client:
curl http://localhost
có thể nhận:
502 Bad Gateway
Kiểm tra Backend:
curl http://localhost:8080
Nếu fail:
Backend ✗
Kiểm tra Nginx:
sudo tail -f /var/log/nginx/error.log
Bạn có thể thấy lỗi kiểu:
connect() failed
26. Debug theo tầng
Khi nhận:
502 Bad Gateway
đừng chỉ restart Nginx.
Kiểm tra:
1. Nginx đang chạy?
↓
2. Backend đang chạy?
↓
3. Backend listen port nào?
↓
4. Nginx proxy tới đúng port?
↓
5. Firewall có chặn?
↓
6. Backend có trả HTTP response?
Command:
sudo systemctl status nginx
sudo ss -lntp
curl http://localhost:8080
sudo nginx -t
sudo tail -f /var/log/nginx/error.log
27. Debug 404
Nếu:
GET /api/todos
trả:
404 Not Found
có thể do:
Nginx routing sai
Backend routing sai
Path bị thay đổi
Đừng mặc định rằng Backend bị lỗi.
Test trực tiếp:
curl http://localhost:8080/api/todos
Sau đó test qua Nginx:
curl http://localhost/api/todos
So sánh hai kết quả.
28. Một trick rất hữu ích
Khi debug Reverse Proxy, luôn test hai đường:
Direct Backend
curl http://127.0.0.1:8080
Through Nginx
curl http://localhost
Nếu:
Backend → OK
Nginx → FAIL
thì tập trung vào:
Nginx config
proxy_pass
location
headers
firewall
Nếu:
Backend → FAIL
Nginx → FAIL
thì xử lý Backend trước.
29. nginx -t trước khi reload
Đây là một thói quen nên hình thành:
sudo nginx -t
Nếu OK:
sudo systemctl reload nginx
Không nên:
sudo systemctl restart nginx
ngay sau mỗi lần sửa config mà chưa kiểm tra syntax.
Một typo trong config có thể khiến Nginx không reload được.
30. Firewall cho mô hình Reverse Proxy
Một kiến trúc tốt hơn:
Internet
│
▼
Nginx :80/:443
│
▼
Backend :8080
Nếu Backend và Nginx cùng server:
Internet
│
├── 80 ✓
├── 443 ✓
│
└── 8080 ✗
Không cần expose 8080 ra Internet.
Backend chỉ cần:
127.0.0.1:8080
hoặc private network.
Đây là một nguyên tắc bảo mật quan trọng:
Chỉ expose những port thực sự cần public.
31. Mô hình production cơ bản
Một server có thể được triển khai:
Internet
│
│ HTTPS :443
▼
Nginx
│
Reverse Proxy
│
▼
Spring Boot
:8080
│
▼
PostgreSQL
:5432
Public:
443
Internal:
8080
5432
Đây là kiến trúc tốt hơn rất nhiều so với:
Internet
│
├── 8080
└── 5432
32. Challenge 1 — Tự tạo 502
Chạy Backend:
python3 -m http.server 8080
Test:
curl http://localhost
→ OK.
Bây giờ tắt Backend:
Ctrl + C
Test lại:
curl http://localhost
→ Có thể nhận 502 Bad Gateway.
Kiểm tra:
sudo tail -f /var/log/nginx/error.log
Bạn vừa mô phỏng một lỗi production rất phổ biến:
Nginx ✓
Backend ✗
↓
502
33. Challenge 2 — Sai Port
Backend chạy:
8080
Nhưng Nginx cấu hình:
proxy_pass http://127.0.0.1:8081;
Test:
curl http://localhost
Debug:
sudo ss -lntp
và:
curl http://127.0.0.1:8080
Sau đó kiểm tra:
sudo tail -f /var/log/nginx/error.log
Tìm nguyên nhân và sửa lại:
proxy_pass http://127.0.0.1:8080;
34. Challenge 3 — Path Routing
Tạo:
/api
forward tới:
8080
và:
/admin
forward tới:
3000
Sau đó test:
curl http://localhost/api
curl http://localhost/admin
Mục tiêu:
Nginx
│
┌────────┴────────┐
│ │
/api /admin
│ │
▼ ▼
:8080 :3000
35. Những command cần nhớ
| Command | Mục đích |
|---|---|
nginx -v |
Kiểm tra version |
sudo nginx -t |
Kiểm tra config |
systemctl status nginx |
Kiểm tra service |
systemctl reload nginx |
Reload config |
systemctl restart nginx |
Restart |
ss -lntp |
Kiểm tra listening ports |
curl -v |
Debug HTTP |
tail -f access.log |
Theo dõi request |
tail -f error.log |
Theo dõi lỗi |
36. Checklist
Sau Lab 9, bạn cần hiểu:
✓ Web Server là gì?
✓ Nginx là gì?
✓ Reverse Proxy là gì?
✓ Forward Proxy khác Reverse Proxy thế nào?
✓ proxy_pass dùng để làm gì?
✓ Nginx routing theo path thế nào?
✓ Nginx routing theo domain thế nào?
✓ 127.0.0.1 và 0.0.0.0 khác nhau thế nào?
✓ access.log dùng để làm gì?
✓ error.log dùng để làm gì?
✓ 502 Bad Gateway thường liên quan đến gì?
✓ nginx -t dùng để làm gì?
✓ reload khác restart thế nào?
✓ Vì sao Backend không nên public trực tiếp?
37. Kết quả cần đạt
Sau Lab 8:
Client
↓
DNS
↓
Firewall
↓
Server
↓
Port
↓
Application
Sau Lab 9, chúng ta có kiến trúc gần production hơn:
Client
│
│ HTTP/HTTPS
▼
Nginx
│
Reverse Proxy
│
▼
Application
│
▼
Database
Quan trọng nhất, bạn phải hiểu được flow:
https://api.example.com
│
▼
DNS
│
▼
Server IP
│
▼
Firewall :443
│
▼
Nginx :443
│
▼
proxy_pass :8080
│
▼
Spring Boot
Đây là nền móng trực tiếp cho những kiến thức sau này như:
Docker
↓
Docker Compose
↓
Kubernetes Service
↓
Ingress
↓
Load Balancer
↓
Azure Application Gateway
Kinh nghiệm quan trọng nhất của Lab 9:
Khi gặp
502, đừng vội kết luận Nginx hỏng. Hãy kiểm tra Nginx → Backend → Port → Process theo từng tầng.
All rights reserved



