Nginx 反向代理到 URI 上的 Wordpress
Nginx reverse proxy to Wordpress on an URI
我有一个 Symfony 2.5.X 应用程序 运行ning 在 nginx 服务器上。我将其命名为domain.com.
该服务器中的 /news URI 被配置为远程机器的反向代理,我再次在 nginx 服务器上 运行 Wordpress 博客。我将其命名为blog.domain.com.
domain.com的配置是这样的:
server {
listen 80;
server_name domain.com;
set $project_path /home/webserver/prod.domain.com;
root $project_path/web;
error_log /home/webserver/prod.domain.com/app/logs/nginx_error.log;
access_log /home/webserver/prod.domain.com/app/logs/nginx_access.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Reverse-proxy all /news calls to remote machine
location ~ /news?(.*) {
access_log off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Host blog.domain.com; # without it it doesn't work
#proxy_set_header Host $http_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 http;
proxy_set_header X-Custom-Secret 6ffe3dba7213c678324a101827aa3cf22c;
proxy_redirect off;
proxy_buffering off;
#proxy_intercept_errors on;
proxy_pass http://blog.domain.com:80;
break;
}
# Default URLs
location / {
try_files $uri /app.php$is_args$args;
}
# Error pages (static)
#error_page 403 /errorpages/403.html;
error_page 404 /errorpages/404.html;
#error_page 405 /errorpages/405.html;
error_page 500 501 502 503 504 /errorpages/5xx.html;
# Don't log garbage, add some browser caching
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
add_header Pragma "public";
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
try_files $uri /app.php?$query_string;
}
location ~* ^.+\.(css|js)$ {
expires modified +1m;
add_header Pragma "private";
add_header Cache-Control "private";
etag on;
try_files $uri /app.php?$query_string;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess, .htpasswd and .git
location ~ /\.(ht|git) {
deny all;
}
# Parse PHP
location ~ ^/(app|app_dev|config)\.php(/|$) {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_pass php;
}
}
blog.domain.com的配置是这样的:
server {
listen 80;
server_name blog.domain.com;
root /home/webserver-blog/news;
access_log /home/webserver-blog/logs/http_access.log;
error_log /home/webserver-blog/logs/http_error.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Default URLs
location / {
# This never gets parsed as / is reserved for our main server
}
location ~* ^/news/(wp-content|wp-admin) { # without this directive I didn't have any static files
root /home/webserver-topblog/;
}
location ~* ^/news {
try_files $uri $uri/ /index.php?args;
}
# Don't log garbage
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess or .htpasswd
location ~ /\.ht {
deny all;
}
# Disallow logs
location ~ ^/logs/.*\.(log|txt)$ {
deny all;
}
# Parse PHP
location ~ \.php$ {
#if (!-e $request_filename) { rewrite / /index.php last; }
try_files $uri =404;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
}
如您所知,我的 Wordpress 位于 /home/webserver-blog/news/
。我在 Wordpress 中有一个稍微修改过的 index.php 文件,用于检查 X-Custom-Secret
header,如果它不存在(或无效),它会强制 301 重定向到 域。 com/news/
现在我已经尝试了几种不同的方法来正确地运行获得它。
- 首先(也是最明显的)是将 博客的
root
指向 domain.com 到 /home/webserver-blog/
并允许 nginx 自然地将请求 URI 传递到子目录 /news
。这工作得很好,但它不允许我使用 Wordpress 的永久链接,只能使用查询字符串。它产生的其他奇怪行为实际上是在 HTTP 重定向中公开 blog.domain.com 如果您调用 /news
时没有尾部斜杠。我的习惯 index.php 很快处理了这些重定向,但我仍然想避免完全暴露 博客。domain.com。
- 第二种(和pretty-much当前)方法再次指向博客的
root
。domain.com's directly to Wordpress'目录, /home/webserver-blog/news/
并用 location ~* ^/news/(wp-content|wp-admin)
指令欺骗所有对静态文件的请求,指向它的根目录上一层。这对永久链接和静态文件都有效,但同样 - /news/wp-login.php
给我无限重定向到 本身 ,而 /news/wp-admin/
实际上下载 index.php 文件解析它(将其作为 application/octet-stream
发送)
我完全没有想法...任何帮助将不胜感激。
我想我想出了一个马马虎虎的解决方案。远非完美或干净,但......好吧,它有效。
blog.domain.com的配置:
server {
listen 80;
server_name blog.domain.com;
root /home/webserver-blog;
access_log /home/webserver-blog/logs/http_access.log;
error_log /home/webserver-blog/logs/http_error.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Default URLs
location ~* ^/news$ {
rewrite ^ $scheme://domain.com/news/ permanent; # ** HARDCODED production url
break;
}
location / {
try_files $uri $uri/ @redir;
}
location @redir {
rewrite ^/news/(.*)$ /news/index.php? last;
}
# Don't log garbage
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess or .htpasswd
location ~ /\.ht {
deny all;
}
# Disallow logs
location ~ ^/logs/.*\.(log|txt)$ {
deny all;
}
# Parse PHP
location ~ \.php$ {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_pass php;
}
}
所以诀窍是我仍然在文件系统目录上操作,而不是花哨的所有方式重写和重定向。 news/
仍然是文件系统中的一个物理目录,它通过 nginx 的 location /
指令读取。以前在尝试不使用斜杠访问时暴露 blog.domain.com 域的问题似乎是本机 nginx 的行为——它看到一个目录,它在末尾添加一个斜杠;由于它的 server_name
设置为 blog.domain.com,我们开始吧。硬编码生产 URL 并将该规则放在首位几乎解决了问题。
@redir
位置再次很好地启用了 Wordpress 的永久链接。
为了防止人们直接访问 http://blog.domain.com/,我在整个设置中添加了另外一个东西,即存储的另一个 index.php
文件直接在 /home/webserver-blog/
:
<?php
/*
* domain.com redirector
*/
$production = 'http://domain.com/news/';
// Redirect nicely
if(isset($_SERVER['REQUEST_URI']) and $_SERVER['REQUEST_URI'] !== '/') {
$target = sprintf('%s%s', $production, preg_replace('/^\//', null, $_SERVER['REQUEST_URI']));
header('Location: ' . $target);
}
else header('Location: ' . $production);
...并且,如前所述,在 Wordpress 的原始 index.php
:
之上有几行
<?php
/*
* wordpress loader
*/
$production = 'http://domain.com/news/';
// Allow only reverse-proxied requests
if(!isset($_SERVER['HTTP_X_CUSTOM_SECRET']) or $_SERVER['HTTP_X_CUSTOM_SECRET'] !== md5('your-md5encoded-text-in-proxy_set_header-X-Custom-Secret')) {
die(header('Location: ' . $production));
}
require_once dirname(__FILE__) . '/index-wp-org.php';
丑陋...但有效。
我仍然很高兴听到更好的解决方案。 :)
我有一个 Symfony 2.5.X 应用程序 运行ning 在 nginx 服务器上。我将其命名为domain.com.
该服务器中的 /news URI 被配置为远程机器的反向代理,我再次在 nginx 服务器上 运行 Wordpress 博客。我将其命名为blog.domain.com.
domain.com的配置是这样的:
server {
listen 80;
server_name domain.com;
set $project_path /home/webserver/prod.domain.com;
root $project_path/web;
error_log /home/webserver/prod.domain.com/app/logs/nginx_error.log;
access_log /home/webserver/prod.domain.com/app/logs/nginx_access.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Reverse-proxy all /news calls to remote machine
location ~ /news?(.*) {
access_log off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Host blog.domain.com; # without it it doesn't work
#proxy_set_header Host $http_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 http;
proxy_set_header X-Custom-Secret 6ffe3dba7213c678324a101827aa3cf22c;
proxy_redirect off;
proxy_buffering off;
#proxy_intercept_errors on;
proxy_pass http://blog.domain.com:80;
break;
}
# Default URLs
location / {
try_files $uri /app.php$is_args$args;
}
# Error pages (static)
#error_page 403 /errorpages/403.html;
error_page 404 /errorpages/404.html;
#error_page 405 /errorpages/405.html;
error_page 500 501 502 503 504 /errorpages/5xx.html;
# Don't log garbage, add some browser caching
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
add_header Pragma "public";
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
try_files $uri /app.php?$query_string;
}
location ~* ^.+\.(css|js)$ {
expires modified +1m;
add_header Pragma "private";
add_header Cache-Control "private";
etag on;
try_files $uri /app.php?$query_string;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess, .htpasswd and .git
location ~ /\.(ht|git) {
deny all;
}
# Parse PHP
location ~ ^/(app|app_dev|config)\.php(/|$) {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_pass php;
}
}
blog.domain.com的配置是这样的:
server {
listen 80;
server_name blog.domain.com;
root /home/webserver-blog/news;
access_log /home/webserver-blog/logs/http_access.log;
error_log /home/webserver-blog/logs/http_error.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Default URLs
location / {
# This never gets parsed as / is reserved for our main server
}
location ~* ^/news/(wp-content|wp-admin) { # without this directive I didn't have any static files
root /home/webserver-topblog/;
}
location ~* ^/news {
try_files $uri $uri/ /index.php?args;
}
# Don't log garbage
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess or .htpasswd
location ~ /\.ht {
deny all;
}
# Disallow logs
location ~ ^/logs/.*\.(log|txt)$ {
deny all;
}
# Parse PHP
location ~ \.php$ {
#if (!-e $request_filename) { rewrite / /index.php last; }
try_files $uri =404;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
}
如您所知,我的 Wordpress 位于 /home/webserver-blog/news/
。我在 Wordpress 中有一个稍微修改过的 index.php 文件,用于检查 X-Custom-Secret
header,如果它不存在(或无效),它会强制 301 重定向到 域。 com/news/
现在我已经尝试了几种不同的方法来正确地运行获得它。
- 首先(也是最明显的)是将 博客的
root
指向 domain.com 到/home/webserver-blog/
并允许 nginx 自然地将请求 URI 传递到子目录/news
。这工作得很好,但它不允许我使用 Wordpress 的永久链接,只能使用查询字符串。它产生的其他奇怪行为实际上是在 HTTP 重定向中公开 blog.domain.com 如果您调用/news
时没有尾部斜杠。我的习惯 index.php 很快处理了这些重定向,但我仍然想避免完全暴露 博客。domain.com。 - 第二种(和pretty-much当前)方法再次指向博客的
root
。domain.com's directly to Wordpress'目录,/home/webserver-blog/news/
并用location ~* ^/news/(wp-content|wp-admin)
指令欺骗所有对静态文件的请求,指向它的根目录上一层。这对永久链接和静态文件都有效,但同样 -/news/wp-login.php
给我无限重定向到 本身 ,而/news/wp-admin/
实际上下载 index.php 文件解析它(将其作为application/octet-stream
发送)
我完全没有想法...任何帮助将不胜感激。
我想我想出了一个马马虎虎的解决方案。远非完美或干净,但......好吧,它有效。
blog.domain.com的配置:
server {
listen 80;
server_name blog.domain.com;
root /home/webserver-blog;
access_log /home/webserver-blog/logs/http_access.log;
error_log /home/webserver-blog/logs/http_error.log;
charset utf-8;
client_max_body_size 65m;
# Some extra speed
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Default URLs
location ~* ^/news$ {
rewrite ^ $scheme://domain.com/news/ permanent; # ** HARDCODED production url
break;
}
location / {
try_files $uri $uri/ @redir;
}
location @redir {
rewrite ^/news/(.*)$ /news/index.php? last;
}
# Don't log garbage
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
# Disallow .htaccess or .htpasswd
location ~ /\.ht {
deny all;
}
# Disallow logs
location ~ ^/logs/.*\.(log|txt)$ {
deny all;
}
# Parse PHP
location ~ \.php$ {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_pass php;
}
}
所以诀窍是我仍然在文件系统目录上操作,而不是花哨的所有方式重写和重定向。 news/
仍然是文件系统中的一个物理目录,它通过 nginx 的 location /
指令读取。以前在尝试不使用斜杠访问时暴露 blog.domain.com 域的问题似乎是本机 nginx 的行为——它看到一个目录,它在末尾添加一个斜杠;由于它的 server_name
设置为 blog.domain.com,我们开始吧。硬编码生产 URL 并将该规则放在首位几乎解决了问题。
@redir
位置再次很好地启用了 Wordpress 的永久链接。
为了防止人们直接访问 http://blog.domain.com/,我在整个设置中添加了另外一个东西,即存储的另一个 index.php
文件直接在 /home/webserver-blog/
:
<?php
/*
* domain.com redirector
*/
$production = 'http://domain.com/news/';
// Redirect nicely
if(isset($_SERVER['REQUEST_URI']) and $_SERVER['REQUEST_URI'] !== '/') {
$target = sprintf('%s%s', $production, preg_replace('/^\//', null, $_SERVER['REQUEST_URI']));
header('Location: ' . $target);
}
else header('Location: ' . $production);
...并且,如前所述,在 Wordpress 的原始 index.php
:
<?php
/*
* wordpress loader
*/
$production = 'http://domain.com/news/';
// Allow only reverse-proxied requests
if(!isset($_SERVER['HTTP_X_CUSTOM_SECRET']) or $_SERVER['HTTP_X_CUSTOM_SECRET'] !== md5('your-md5encoded-text-in-proxy_set_header-X-Custom-Secret')) {
die(header('Location: ' . $production));
}
require_once dirname(__FILE__) . '/index-wp-org.php';
丑陋...但有效。 我仍然很高兴听到更好的解决方案。 :)