Cache WordPress bằng nginx: cấu hình FastCGI page cache đúng cách
Hướng dẫn cache WordPress bằng nginx FastCGI cache: cấu hình, loại trừ trang đăng nhập và giỏ hàng, xoá cache khi cập nhật, kiểm tra HIT/MISS.

Ý chính
- Page cache của nginx lưu trang HTML đã tạo sẵn và trả cho khách tiếp theo mà không chạy PHP hay truy vấn database.
- Người đã đăng nhập, giỏ hàng, thanh toán, request POST và URL có query string phải luôn bỏ qua cache.
- Cần cơ chế xoá cache khi nội dung thay đổi, nếu không khách sẽ thấy bài cũ.
- Trong phép đo của chúng tôi, page cache nâng số website WordPress trên VPS 4 GB từ khoảng 100 lên 250.
Cache WordPress bằng nginx nghĩa là dùng FastCGI cache của nginx để lưu lại trang HTML mà WordPress đã tạo, rồi trả bản lưu đó cho những khách truy cập tiếp theo mà không cần chạy PHP hay truy vấn MySQL/MariaDB. Đây là cách tăng tốc WordPress hiệu quả nhất ở tầng server: trang được trả trong vài mili giây thay vì vài trăm mili giây, và cùng một VPS phục vụ được nhiều website hơn hẳn. Điều kiện để làm đúng là loại trừ người đã đăng nhập, giỏ hàng, thanh toán, và có cơ chế xoá cache khi nội dung thay đổi.
Bài này giải thích page cache hoạt động thế nào, cấu hình đầy đủ cho nginx trên Ubuntu 24.04 / Debian 12 (kèm lý do từng dòng), cách xoá cache, cách kiểm tra cache có thật sự chạy, và cách bật page cache trong ZoPanel.
Page cache của nginx hoạt động thế nào?
Không có cache, mỗi lượt xem trang WordPress đều chạy toàn bộ chuỗi: PHP khởi động WordPress, nạp plugin và giao diện, gửi hàng chục truy vấn tới database, rồi dựng HTML. Việc đó tốn CPU và RAM, và lặp lại y hệt cho mọi khách đọc cùng một bài viết.
Với FastCGI cache, request đầu tiên vẫn đi qua PHP (gọi là MISS), nhưng nginx lưu kết quả xuống đĩa. Những request sau cho cùng URL được nginx trả thẳng từ cache (HIT); PHP và database không làm gì cả. Khi bản lưu hết hạn, nginx có thể trả bản cũ ngay cho khách trong lúc làm mới ở nền, nên không có chuyện hàng trăm khách cùng lúc kích hoạt PHP cho một trang vừa hết hạn.
Page cache khác gì object cache, browser cache và CDN?
| Loại cache | Lưu cái gì | Ở đâu | Hữu ích nhất cho |
|---|---|---|---|
| Page cache (nginx FastCGI) | Nguyên trang HTML | Trên server, trước PHP | Khách chưa đăng nhập, blog, trang tin, landing page |
| Object cache (Redis) | Kết quả truy vấn database | Trong RAM, dùng bởi PHP | wp-admin, WooCommerce, người đã đăng nhập |
| OPcache | Mã PHP đã biên dịch | Trong RAM/đĩa | Mọi request có chạy PHP |
| Browser cache | Ảnh, CSS, JS | Trên máy khách | Lượt xem trang thứ hai trở đi |
| CDN | File tĩnh, có thể cả HTML | Máy chủ biên gần khách | Khách ở xa server, giảm tải băng thông |
Các lớp này bổ trợ cho nhau. Page cache cho hiệu quả lớn nhất với lượng khách chưa đăng nhập; object cache giúp phần còn lại, những trang không thể cache nguyên trang.
Page cache giúp được bao nhiêu?
Chúng tôi đã đo trên VPS thật: một VPS Ubuntu 24.04 với 4 GB RAM và 4 vCPU chạy được khoảng 100 website WordPress không có page cache, và 250 khi bật page cache, cùng với 30 ứng dụng khác. Với VPS Debian 12 3 GB, con số là 50 và 200. Phương pháp đo, kiểu lưu lượng và giới hạn của các con số này nằm trong bài VPS 4 GB chạy được bao nhiêu website WordPress. Website của bạn sẽ khác tuỳ plugin, lưu lượng và tỷ lệ khách đã đăng nhập.
Cấu hình cache WordPress bằng nginx (làm tay)
Phần dưới giả định bạn đã có WordPress chạy với nginx và PHP-FPM (ví dụ PHP 8.3 qua socket /run/php/php8.3-fpm.sock). Hãy sao lưu cấu hình nginx trước khi sửa.
Bước 1: Khai báo vùng cache
Tạo /etc/nginx/conf.d/wordpress-cache.conf (file trong conf.d nằm trong khối http):
fastcgi_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=WORDPRESS:64m
inactive=1d max_size=2g use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
keys_zone=WORDPRESS:64mlà vùng RAM lưu chỉ mục khoá; 1 MB chứa được khoảng tám nghìn khoá.inactive=1dxoá trang không ai xem trong một ngày.max_size=2ggiới hạn dung lượng cache trên đĩa.- Khoá cache gồm cả
$host, nên nhiều website dùng chung một vùng cache không bị lẫn trang của nhau.
Bước 2: Quy tắc không cache
Trong khối server của website, trước các location:
set $skip_cache 0;
# Chỉ cache GET và HEAD
if ($request_method !~ ^(GET|HEAD)$) { set $skip_cache 1; }
# URL có query string (tìm kiếm, lọc, phân trang kiểu ?page=)
if ($query_string != "") { set $skip_cache 1; }
# Trang quản trị, đăng nhập, API, feed, sitemap, giỏ hàng, thanh toán
if ($request_uri ~* "/wp-admin/|/wp-login\.php|/wp-json/|/xmlrpc\.php|/feed/|sitemap|/cart/|/checkout/|/my-account/") {
set $skip_cache 1;
}
# Người đã đăng nhập, người vừa bình luận, bài có mật khẩu, giỏ hàng WooCommerce
if ($http_cookie ~* "wordpress_logged_in|wp-postpass|comment_author|woocommerce_items_in_cart|wp_woocommerce_session") {
set $skip_cache 1;
}
Dùng if chỉ để set biến như trên là cách dùng an toàn trong nginx. Nếu shop của bạn đổi đường dẫn giỏ hàng hay thanh toán (ví dụ /gio-hang/, /thanh-toan/), hãy thêm chúng vào danh sách.
Bước 3: Bật cache cho PHP
Trong location ~ \.php$ hiện có:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 301 10m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_use_stale error timeout updating http_500 http_503;
fastcgi_cache_background_update on;
fastcgi_cache_lock on;
add_header X-Cache $upstream_cache_status;
}
fastcgi_cache_valid 200 301 10m: trang thành công được giữ 10 phút. Trang 404 hay lỗi không bị cache.fastcgi_cache_bypassvàfastcgi_no_cache: không đọc và không ghi cache cho các request bị loại trừ ở bước 2.use_stale updatingcùngbackground_update: khi trang hết hạn, khách vẫn nhận bản cũ ngay, một request ở nền làm mới.error timeout http_500 http_503còn cho phép trả bản cũ khi PHP đang lỗi, giúp website "sống" qua sự cố ngắn.fastcgi_cache_lock: nhiều request cùng lúc cho một trang chưa có trong cache chỉ tạo một request tới PHP.X-Cache: cho bạn thấy HIT, MISS hay BYPASS.
Lưu ý: add_header trong một location sẽ thay thế mọi add_header khai báo ở cấp server (ví dụ các header bảo mật). Nếu bạn có header ở cấp server, hãy lặp lại chúng trong location này. Chi tiết từng chỉ thị có trong tài liệu module FastCGI của nginx.
Tạo thư mục cache, kiểm tra và nạp lại cấu hình:
sudo mkdir -p /var/cache/nginx/wordpress
sudo nginx -t && sudo systemctl reload nginx
Bước 4: Xoá cache khi nội dung thay đổi
Nếu không xoá cache, khách có thể thấy bài viết cũ tới 10 phút sau khi bạn sửa. Có ba cách:
- Thời gian cache ngắn (vài phút) và chấp nhận độ trễ. Đơn giản nhất.
- Plugin Nginx Helper cùng module
ngx_cache_purge: plugin gửi yêu cầu xoá đúng những trang liên quan mỗi khi có bài mới, sửa bài hay bình luận. Trên Ubuntu 24.04 và Debian 12, module có sẵn trong góilibnginx-mod-http-cache-purge:
sudo apt install -y libnginx-mod-http-cache-purge
Thêm vào khối server một location chỉ cho phép chính server gọi:
location ~ /purge(/.*) {
allow 127.0.0.1;
allow IP_CUA_SERVER;
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
Khoá trong lệnh purge phải khớp với fastcgi_cache_key ở bước 1. Sau đó cài Nginx Helper, bật purge và chọn phương thức dùng module ngx_cache_purge. Nếu thư mục cache khác mặc định của plugin, khai báo nó trong wp-config.php theo hướng dẫn của plugin.
- Xoá toàn bộ bằng tay khi cần gấp:
sudo find /var/cache/nginx/wordpress -type f -delete.
Bước 5: Kiểm tra cache có thật sự chạy
Mở cửa sổ ẩn danh hoặc dùng curl (không có cookie đăng nhập), gọi cùng một URL hai lần:
curl -sI https://example.com/ | grep -i x-cache # lần 1: MISS
curl -sI https://example.com/ | grep -i x-cache # lần 2: HIT
Nếu lúc nào cũng là MISS hoặc BYPASS, nguyên nhân thường là:
- Một plugin gửi
Set-Cookietrên mọi trang. Theo tài liệu nginx, response cóSet-Cookiesẽ không được cache. Tìm plugin đó (thường là plugin thống kê, đa ngôn ngữ hoặc giỏ hàng) và cấu hình lại. - WordPress hoặc plugin gửi header
Cache-Control: no-cachehayExpirestrong quá khứ. - URL có query string, ví dụ link quảng cáo có
?utm_source=.
Bật page cache WordPress trong ZoPanel
ZoPanel có sẵn page cache của nginx cho mọi website PHP, đã gồm các quy tắc ở trên:
- Mở website, vào tab PHP & cấu hình.
- Bật Page cache.
Những gì được làm sẵn, theo tài liệu Website và PHP:
- Trang được cache 10 phút; trang hết hạn được trả ngay trong khi một request làm mới ở nền; trang không ai dùng trong một ngày rời khỏi cache.
- Không bao giờ cache request khác GET và HEAD; khách có cookie đăng nhập WordPress, bài có mật khẩu, người bình luận, giỏ hàng hoặc session WooCommerce; các URL
/wp-admin,/wp-login.php,/wp-json,/xmlrpc.php,/cart,/checkout,/my-account,/feed, sitemap; và URL có query string. Riêng query chỉ gồm tham số quảng cáo nhưutm_*,fbclid,gclidvẫn được tính là không có query, nên khách đến từ chiến dịch quảng cáo vẫn nhận trang đã cache. - Website WordPress được cài một must-use plugin nhỏ tự xoá cache của website khi bài viết, bình luận, menu, giao diện hoặc plugin thay đổi. Nút Xoá cache xoá thủ công. Response có header
X-Cache. - Trang Tối ưu liệt kê các website WordPress chưa bật page cache và có nút Áp dụng để bật cho tất cả.
Với WooCommerce và website có nhiều người đăng nhập, bật thêm Redis object cache trong cùng tab: ZoPanel tạo một database Redis riêng cho website và cấu hình plugin. Xem thêm WordPress Toolkit và Hiệu năng PHP. Lưu ý page cache tắt khi website dùng chế độ Apache.
Những lỗi hay gặp khi cache WordPress bằng nginx
- Cache trang của người đã đăng nhập: khách khác thấy thanh quản trị hay thông tin tài khoản của người khác. Luôn kiểm tra cookie
wordpress_logged_in. - Cache giỏ hàng và thanh toán: khách thấy giỏ hàng của người khác. Loại trừ đúng các URL của shop bạn, kể cả khi đã đổi tên.
- Không có cơ chế xoá cache: khách thấy giá hay bài cũ.
- Dùng thêm plugin page cache (lưu file HTML ở tầng PHP) cùng với cache của nginx: hai lớp cùng loại khó xoá đồng bộ và khó tìm lỗi. Chọn một.
- Giao diện khác nhau cho mobile và desktop mà dùng chung khoá cache: khách mobile nhận bản desktop. Giao diện responsive không gặp vấn đề này.
- Không kiểm tra
X-Cachesau khi cài: tưởng có cache nhưng thật ra mọi trang đều BYPASS.
Kết luận
Cache WordPress bằng nginx là thay đổi đơn lẻ có tác động lớn nhất tới tốc độ và mật độ website trên một VPS: trang trả nhanh hơn, PHP và database nhẹ hơn, server chịu được đột biến lưu lượng tốt hơn. Phần khó là làm đúng: loại trừ đủ trường hợp, xoá cache khi nội dung đổi, và kiểm tra nó thật sự chạy. Nếu bạn muốn tất cả được làm sẵn cho mọi website, hãy thử gói Free của ZoPanel với 10 website và bật page cache chỉ bằng một công tắc.
Câu hỏi thường gặp
Cache WordPress bằng nginx có cần plugin không?
Không bắt buộc. FastCGI cache chạy hoàn toàn trong nginx. Plugin chỉ cần để xoá cache tự động khi nội dung thay đổi, ví dụ Nginx Helper cùng module ngx_cache_purge; nếu không, bạn đặt thời gian cache ngắn hoặc xoá bằng tay. ZoPanel tự cài một must-use plugin nhỏ cho việc xoá cache.
Page cache có dùng được cho WooCommerce không?
Có, cho các trang sản phẩm và danh mục mà khách xem khi chưa thêm gì vào giỏ. Giỏ hàng, thanh toán, tài khoản và mọi khách đã có hàng trong giỏ phải bỏ qua cache. Shop có nhiều khách đăng nhập nên dùng thêm Redis object cache.
Nên đặt thời gian cache bao lâu?
Nếu có cơ chế xoá cache khi cập nhật, 10 phút đến vài giờ là hợp lý, kết hợp làm mới ở nền. Nếu không có cơ chế xoá, hãy đặt vài phút để nội dung mới không bị trễ lâu.
Làm sao biết trang đã được cache?
Xem header X-Cache của response bằng curl -sI https://tenmien/ | grep -i x-cache khi chưa đăng nhập. Lần đầu là MISS, lần sau là HIT. BYPASS nghĩa là request đó bị loại trừ theo quy tắc.
Page cache của nginx và plugin như WP Super Cache, W3 Total Cache khác nhau thế nào?
Plugin cache vẫn để request đi qua PHP (hoặc dựa vào quy tắc rewrite để trả file HTML), còn FastCGI cache được nginx phục vụ trước khi PHP được gọi, nên nhẹ hơn ở mức server. Đừng chạy cả hai loại page cache cùng lúc; các tính năng khác của plugin (nén ảnh, gộp CSS) vẫn có thể dùng song song.
Đọc tiếp

VPS cho WordPress cấu hình bao nhiêu là đủ? Cách chọn CPU, RAM, ổ đĩa
VPS cho WordPress cấu hình bao nhiêu là đủ cho 1, 10 hay 100 website? Cách ước lượng CPU, RAM, ổ đĩa theo lưu lượng, kèm số liệu đo thực tế và lỗi cần tránh.

Hosting cho WooCommerce: cấu hình, yêu cầu và cách tối ưu
Hosting cho WooCommerce cần gì: yêu cầu PHP, MariaDB, RAM theo tài liệu chính thức, vì sao cửa hàng nặng hơn blog, và cách cấu hình cache, cron, backup đúng.

WP-Cron chạy chậm? Thay bằng cron của server trong 10 phút
WP-Cron chạy chậm, bài hẹn giờ bị lỡ, email WooCommerce gửi trễ? Hướng dẫn tắt wp-cron và thay bằng cron hoặc systemd timer của server, kèm lệnh mẫu.