[英]How to config Varnish for multiple application containing WordPress and Ghost CMS with nginx as proxy?
我們正在為 WordPress 和 Ghost 博客平台設置清漆緩存系統,以 nginx 作為網絡服務器/代理。
Wordpress Vcl(默認)
vcl 4.0;
import std;
backend default {
.host = "127.0.0.1";
.port = "8080";
.first_byte_timeout = 600s;
}
acl purger {
"localhost";
"127.0.0.1";
"172.17.0.1";
}
sub vcl_recv {
if (req.restarts \> 0) {
set req.hash_always_miss = true;
}
#return (pass);
if (req.method == "PURGE") {
if (client.ip !~ purger) {
return (synth(405, "Method not allowed"));
}
if (req.http.X-Cache-Tags) {
ban("obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags);
} else {
ban("req.http.host == " +req.http.host+" && req.url ~ "+req.url);
return (synth(200, "Purged"));
}
return (synth(200, "Purged"));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Set initial grace period usage status
set req.http.grace = "none";
# normalize url in case of leading HTTP scheme and domain
set req.url = regsub(req.url, "^http[s]?://", "");
# collect all cookies
std.collect(req.http.Cookie);
if (req.url ~ "^/admin/" || req.url ~ "/paypal/") {
return (pass);
}
if (req.http.cookie ~ "wordpress_logged_in_") {
return (pass);
}
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") {
# No point in compressing these
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
unset req.http.Accept-Encoding;
}
}
if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") {
set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", "");
set req.url = regsub(req.url, "[?|&]+$", "");
}
if (req.http.Authorization ~ "^Bearer") {
return (pass);
}
return (hash);
}
sub vcl_hash {
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
}
sub vcl_backend_response {
set beresp.grace = 3d;
if (beresp.http.content-type ~ "text") {
set beresp.do_esi = true;
}
if (beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
# cache only successfully responses and 404s that are not marked as private
if (beresp.status != 200 && beresp.status != 404 && beresp.http.Cache-Control ~ "private") {
set beresp.uncacheable = true;
set beresp.ttl = 86400s;
return (deliver);
}
# validate if we need to cache it and prevent from setting cookie
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.set-cookie;
}
if (!beresp.http.cache-control) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
}
return (deliver);
}
sub vcl_deliver {
set resp.http.X-Cache-Age = resp.http.Age;
unset resp.http.Age;
# Avoid being cached by the browser.
if (resp.http.Cache-Control !~ "private") {
set resp.http.Pragma = "no-cache";
set resp.http.Expires = "-1";
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
}
unset resp.http.X-Powered-By;
unset resp.http.Server;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
unset resp.http.X-Frame-Options;
unset resp.http.X-Content-Type-Options;
unset resp.http.X-Xss-Protection;
unset resp.http.Referer-Policy;
unset resp.http.X-Permitted-cross-domain-policies;
}
sub vcl_hit {
if (obj.ttl \>= 0s) {
return (deliver);
}
set req.http.grace = "unlimited (unhealthy server)";
return (deliver);
}
include "all-vhosts.vcl";
Nginx 所有 WordPress 站點的 Vhost
server {
listen 80;
listen \[::\]:80;
listen 443 ssl http2;
listen \[::\]:443 ssl http2;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name www.test.in;
return 301 https://test.in$request_uri;
}
server {
listen 8080;
listen \[::\]:8080;
server_name yourdomain.in www1.yourdomain.in;
{{root}}
try_files $uri $uri/ /index.php?$args;
index index.php index.html;
location \~ .php$ {
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_param HTTPS "on";
fastcgi_param SERVER_PORT 443;
fastcgi_pass 127.0.0.1:{{php_fpm_port}};
fastcgi_param PHP_VALUE "{{php_settings}}";
}
if (-f $request_filename) {
break;
}
}
server {
listen 80;
listen \[::\]:80;
listen 443 ssl http2;
listen \[::\]:443 ssl http2;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name yourdomain.in www1.yourdomain.in;
{{root}}
{{nginx_access_log}}
{{nginx_error_log}}
if ($scheme != "https") {
rewrite ^ https://$host$uri permanent;
}
location \~ /.well-known {
auth_basic off;
allow all;
}
{{settings}}
location \~/.git {
deny all;
}
location \~/(wp-admin/|wp-login.php) {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
proxy_max_temp_file_size 0;
proxy_connect_timeout 7200;
proxy_send_timeout 7200;
proxy_read_timeout 7200;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
location / {
{{varnish_proxy_pass}}
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header X-Varnish;
proxy_redirect off;
proxy_max_temp_file_size 0;
proxy_connect_timeout 720;
proxy_send_timeout 720;
proxy_read_timeout 720;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
location \~\* ^.+.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf|map)$ {
add_header Access-Control-Allow-Origin "\*";
expires max;
access_log off;
}
if (-f $request_filename) {
break;
}
}
一旦我們為 Ghost 添加另一個 vcl 文件,這就完美了,我們得到 ghost cms 的 503 后端獲取錯誤。(wordpress 仍然可以正常工作)。Ghost 在 3021 端口上運行。 清漆端口 6081
幽靈VCL
vcl 4.0;
import std;
backend ghost {
.host = "127.0.0.1";
.port = "3021";
}
acl purge {
"127.0.0.1";
}
# first vcl_recv block handles the cache purging
sub vcl_recv {
set req.backend_hint = ghost;
return (hash);
if (req.url \~ "/rebuild/purge") {
if (client.ip !\~ purge) {
return (synth(405, "Method Not Allowed"));
}
ban("req.http.host == yourdomain.you");
return(synth(200, "Cache cleared"));
}
}
# second vcl_recv block handles the actual caching
sub vcl_recv {
if (req.url \~ "/assets" || req.url \~ "/content/images") {
return (hash);
} else {
return (pass);
}
}
sub vcl_backend_response {
if (bereq.url \~ "/assets" || bereq.url \~ "/content/images") {
set beresp.http.cache-control = "public, max-age=259200";
set beresp.ttl = 3d;
return (deliver);
}
}
sub vcl_deliver {
# nothing here
}
幽靈虛擬主機
proxy_cache_path /tmp/nginx_ghost levels=1:2 keys_zone=ghostcache:600m max_size=100m inactive=24h;
server {
listen 80;
listen \[::\]:80;
listen 443 ssl http2;
listen \[::\]:443 ssl http2;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name $yourdomain;
{{root}}
{{nginx_access_log}}
{{nginx_error_log}}
if ($scheme != "https") {
rewrite ^ https://$host$uri permanent;
}
location \~ /.well-known {
auth_basic off;
allow all;
}
{{settings}}
index index.html;
location / {
proxy_pass http://127.0.0.1:6081/;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
\# Remove cookies which are useless for anonymous visitor and prevent caching
proxy_ignore_headers Set-Cookie Cache-Control;
proxy_hide_header Set-Cookie;
\# Add header for cache status (miss or hit)
add_header X-Cache-Status $upstream_cache_status;
proxy_cache ghostcache;
\# Default TTL: 1 day
proxy_cache_valid 1d;
\# Cache 404 pages for 1h
proxy_cache_valid 404 1h;
\# use conditional GET requests to refresh the content from origin servers
proxy_cache_revalidate on;
proxy_buffering on;
\# Allows starting a background subrequest to update an expired cache item,
\# while a stale cached response is returned to the client.
proxy_cache_background_update on;
\# Bypass cache for errors
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_pass_request_headers on;
proxy_max_temp_file_size 0;
proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
# No cache + keep cookies for admin and previews
location \~ ^/(ghost/|p/) {
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 https;
proxy_pass http://127.0.0.1:{{app_port}};
}
# Bypass ghost for static assets
location ^\~ /assets/ {
root /home/$yourpath/htdocs/$yourpath/content/themes/$yourtheme;
}
# Bypass ghost for original images but not resized ones
location ^\~ /content/images/(!size) {
root /home/$yourpath/htdocs/$yourpath;
}
}
當涉及多個應用程序時,我們需要有關如何處理多個 vcl 文件的幫助。 我們已經嘗試了一切,但似乎沒有任何效果。
清漆版本 (varnish-7.1.1)
有兩種方法可以讓事情井井有條:
有關 VCL 標簽的教程,請參閱https://varnish-cache.org/docs/trunk/users-guide/vcl-separate.html 。
這個想法是將多個 VCL 文件加載到varnishd
程序中,並為每個 VCL 文件分配一個 label。 然后是一個主 VCL 配置,它了解各種標准並將加載正確的子配置。
這是一個示例實現:
vcl 4.1;
import std;
# We have to have a backend, even if we do not use it
backend default { .host = "127.0.0.1"; }
sub vcl_recv {
# Normalize host header
set req.http.host = std.tolower(req.http.host);
if (req.http.host ~ "^(www.)?domain.ext$") {
return (vcl(wordpress));
}
if (req.http.host == "ghost.domain.ext") {
return (vcl(ghost));
}
return (synth(302, "http://www.domain.ext"));
}
sub vcl_synth {
if (resp.status == 301 || resp.status == 302) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
}
使用以下命令,您可以為 WordPress 和 Ghost 加載 2 個單獨的 VCL 文件,同時標記它們:
varnishadm vcl.load vc_wordpress /path/to/wordpress.vcl
varnishadm vcl.load vc_ghost /path/to/ghost.vcl
varnishadm vcl.label wordpress vc_wordpress
varnishadm vcl.label ghost vc_ghost
只要有一個了解標簽的主 VCL 配置,您就可以在單個 Varnish 實例上托管多個網站的 VCL 配置
另一種方法是通過 VCL 包含,它在啟動時將包含文件中的代碼直接粘貼到占位符中。
這是同一個示例,但使用 include 而不是標簽進行了重構:
vcl 4.1;
import std;
# We have to have a backend, even if we do not use it
backend default { .host = "127.0.0.1"; }
sub vcl_recv {
# Normalize host header
set req.http.host = std.tolower(req.http.host);
if (req.http.host ~ "^(www.)?domain.ext$") {
include "wordpress.vcl";
}elseif (req.http.host == "ghost.domain.ext") {
include "ghost.vcl";
} else {
return (synth(302, "http://www.domain.ext"));
}
}
sub vcl_synth {
if (resp.status == 301 || resp.status == 302) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
}
我個人更喜歡標簽,因為在各種 VCL 配置之間有更好的隔離。
當需要更改時,您可以更改單個 VCL 配置,而不必為所有網站重新加載配置。
缺點是您必須確保子配置始終存在。 重新啟動varnishd
會清除這些配置。
一種避免這種情況的方法是在varnishd
中指定-I
運行時參數。 -I
指向包含將在啟動時執行的 CLI 命令的文件。 這樣您就可以填充標記的子配置,而不會在重啟后丟失它們。
使用 include 簡單很多,但隔離度較低。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.