Cấu hình Varnish cache giữa Nginx và Apache trên Ubuntu 24.04

Vì sao sysadmin cần Varnish trước web server?
Khi traffic website tăng cao, Apache hoặc Nginx có thể bị quá tải vì phải xử lý PHP, database. Đặt Varnish cache trước web server giúp hứng request, trả cache nếu có, chỉ forward đến backend khi cần nội dung động. Kết quả: giảm CPU server, giảm thời gian phản hồi từ 200-500ms xuống còn 1-5ms, tăng khả năng chịu tải gấp 5-10 lần mà không cần nâng cấp VPS.
Bài này hướng dẫn cấu hình Varnish 7.x làm reverse proxy trước Nginx trên Ubuntu 24.04 LTS. Nếu bạn dùng Apache, chỉ cần thay backend port 8080 thành 80 và Nginx thành Apache. Các lệnh đã kiểm tra trên VPS NVMe có IPv4 Việt Nam - bạn có thể chạy VPS Linux thueVPS với full root để làm theo.
Yêu cầu trước khi bắt đầu
- VPS chạy Ubuntu 24.04 LTS (khuyến nghị thuê VPS tối thiểu 2GB RAM để có đủ bộ nhớ cho cache + web server).
- User sudo non-root đã cấu hình.
- Web server Nginx đang chạy ở port 80 (hoặc 8080 nếu chưa có).
- Firewall (ufw) đã mở port 80, 443 (sau này), 8081 (backup).
- Kiến thức cơ bản về HTTP header và cache-control.
Kiến trúc tổng quan: Varnish đứng trước Nginx
Luồng request sau khi cài Varnish:
User → Port 80 (Varnish) → Cache HIT? → Trả ngay
↘ Cache MISS → Port 8080 (Nginx) → PHP-fpm → Response → Varnish lưu cache → Trả cho user
Varnish nghe port 80, Nginx chuyển sang port 8080. Mọi request HTTP đều qua Varnish trước.
| Thành phần | Port mặc định | Vai trò |
|---|---|---|
| Varnish | 80 | Reverse proxy + cache |
| Nginx | 8080 | Web server backend |
| PHP-fpm | 9000 (Unix socket) | Xử lý PHP |
Bước 1 - Cài đặt Varnish từ repo chính thức
Không dùng package mặc định của Ubuntu (thường cũ). Dùng repo Varnish chính thức cho bản mới nhất 7.x.
# Cài curl nếu chưa có
sudo apt update && sudo apt install curl -y
# Thêm repo Varnish
curl -fsSL https://packagecloud.io/varnishcache/varnish73/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/varnish.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/varnish.gpg] https://packagecloud.io/varnishcache/varnish73/ubuntu/ jammy main" | sudo tee /etc/apt/sources.list.d/varnish73.list
# Cài đặt
sudo apt update
sudo apt install varnish -y
Kiểm tra phiên bản: varnishd -V. Output mong đợi: varnishd (varnish-7.3.x).
Bước 2 - Chuyển Nginx sang port 8080
Varnish cần nghe port 80, nên Nginx phải chạy port khác. Chỉnh sửa file default config của Nginx:
sudo nano /etc/nginx/sites-available/default
Tìm dòng listen 80 default_server; → sửa thành:
listen 8080 default_server;
listen [::]:8080 default_server;
Kiểm tra config và reload:
sudo nginx -t
sudo systemctl reload nginx
Verify: ss -tlnp | grep 8080 → thấy nginx listening ở 8080. Truy cập http://IP_VPS:8080 vẫn thấy trang web (nếu mở port 8080 trên firewall).
Bước 3 - Cấu hình Varnish nghe port 80 và trỏ backend
3a. Cấu hình systemd service
Mặc định Varnish nghe port 6081. Cần sửa để nghe port 80.
sudo nano /lib/systemd/system/varnish.service
Tìm dòng ExecStart chứa -a :6081 → sửa thành:
ExecStart=/usr/sbin/varnishd -a :80 -a localhost:8443,PROXY -f /etc/varnish/default.vcl -s malloc,256m
Giải thích: -a :80 nghe HTTP, malloc,256m dùng 256MB RAM cho cache (tăng nếu VPS có RAM dư: 512m, 1g). Reload:
sudo systemctl daemon-reload
sudo systemctl restart varnish
3b. Cấu hình VCL trỏ backend Nginx
sudo nano /etc/varnish/default.vcl
Xóa nội dung cũ, thêm:
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Bỏ qua cache cho request có cookie session (WordPress, Laravel)
if (req.http.cookie ~ "(wordpress_logged_in|wp-admin|PHPSESSID)") {
return (pass);
}
# Xóa query string không cần thiết trước khi cache
set req.url = regsub(req.url, "\?utm_[^&]+&?", "?");
set req.url = regsub(req.url, "\?&", "?");
# Normalize Accept-Encoding header
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|jpeg|png|gif|ico|webp|css|js|woff|woff2)$") {
unset req.http.Accept-Encoding;
}
}
}
sub vcl_backend_response {
# Cache file tĩnh lâu (30 ngày)
if (bereq.url ~ "\.(jpg|jpeg|png|gif|ico|webp|css|js|woff|woff2)$") {
set beresp.ttl = 30d;
}
# Cache trang HTML tĩnh 1 giờ
if (beresp.http.content-type ~ "text/html") {
set beresp.ttl = 1h;
}
# Tôn trọng header Cache-Control từ backend
if (beresp.http.Cache-Control ~ "private|no-cache|no-store") {
set beresp.uncacheable = true;
return (deliver);
}
}
sub vcl_deliver {
# Thêm header để debug cache HIT/MISS
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
unset resp.http.Via;
unset resp.http.X-Varnish;
}
Kiểm tra cú pháp VCL: varnishadm vcl.load default /etc/varnish/default.vcl. Nếu OK, áp dụng: varnishadm vcl.use default.
Restart Varnish: sudo systemctl restart varnish.
Verify: ss -tlnp | grep varnishd → Varnish nghe port 80. Truy cập http://IP_VPS (không port) → web vẫn hiển thị. Thêm header xem cache: curl -I http://IP_VPS → output có X-Cache: MISS (lần đầu). F5 vài lần → X-Cache: HIT.
Bước 4 - Mở port 80 trên firewall
Nếu dùng ufw:
sudo ufw allow 80/tcp
sudo ufw delete allow 8080 # không cần thiết cho public
Kiểm tra: sudo ufw status → port 80 open.
Xử lý lỗi thường gặp
Lỗi: "Could not start varnishd: -a :80: Address already in use"
Nginx vẫn chạy ở port 80. Dừng Nginx trước (hoặc đảm bảo bạn đã chuyển nó sang 8080): sudo systemctl stop nginx, kiểm tra ss -tlnp | grep :80, nếu Nginx còn chạy → sửa config ở Bước 2.
Lỗi: "VCL load failed: Could not read"
Sai cú pháp VCL. Xem lỗi chi tiết: journalctl -u varnish -n 20. Thường là thiếu dấu chấm phẩy hoặc sai tên log. Sửa file, chạy lại varnishadm vcl.load.
Cache toàn bộ trang admin WordPress
Kiểm tra sub vcl_recv: nếu req.http.cookie ~ "wp-admin" không match, sửa regex thành "(wordpress_logged_in|wp-admin|PHPSESSID)". Thêm return (pass) bỏ qua cache.
Câu hỏi thường gặp
Varnish có cần SSL không?
Varnish không hỗ trợ SSL native. Để chạy HTTPS, đặt Nginx làm SSL terminator ở port 443, rồi forward về Varnish ở port 80 nội bộ (hoặc dùng hitch/haproxy). Cấu hình phức tạp hơn, phù hợp bài riêng.
Nên đặt dung lượng cache malloc bao nhiêu?
VPS 2GB: 256-512MB. VPS 4GB: 512MB-1GB. Không dùng quá 50% RAM system. Nếu cache đầy, Varnish tự động evict object cũ.
Làm sao biết Varnish đang cache HIT hay MISS?
Thêm header X-Cache như trong VCL mẫu. Dùng curl -I http://domain xem output. Lần đầu MISS, lần sau HIT. Công cụ varnishstat cho số liệu chi tiết: varnishstat -1 | grep -E "cache_hit|cache_miss".
Varnish tốt hơn Nginx caching module ở điểm nào?
Varnish chuyên biệt cho caching, có VCL linh hoạt (điều kiện, purging, grace mode). Nginx caching đơn giản hơn, không hỗ trợ grace mode mượt mà. Varnish là lựa chọn hàng đầu cho high-traffic.
Tôi có thể flush toàn bộ cache Varnish không?
Có: varnishadm ban req.url "~" "." (flush tất cả). Hoặc admin trang cho URL cụ thể: varnishadm ban req.url "~" "^/uploads/".
Varnish có chạy được trên VPS Windows không?
Varnish chỉ chạy trên Linux. Nếu bạn dùng VPS Windows, hãy xem giải pháp cache khác hoặc dùng Linux.
Bài viết liên quan
- Tối ưu Nginx cho traffic cao: worker, gzip, buffer, cache
- Tối ưu PHP-FPM cho WordPress trên VPS
- Benchmark hiệu năng VPS với fio, sysbench, iperf3


