【问题标题】:Nginx reverse proxy to Wordpress on an URINginx 反向代理到 URI 上的 Wordpress
【发布时间】:2017-03-09 10:57:24
【问题描述】:

我有一个 Symfony 2.5.X 应用程序在 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 标头,如果它不存在(或无效),它会强制 301 重定向到 domain.com/news/

现在我尝试了几种不同的方法来让它正常运行。

  • 首先(也是最明显的)将 blog.domain.comroot 指向 /home/webserver-blog/ 并允许 nginx 自然地将请求 URI 传递到子目录 /news .这工作得很好,但它不允许我使用 Wordpress 的永久链接,只能使用查询字符串。它产生的其他奇怪行为实际上是在 HTTP 重定向中暴露 blog.domain.com 如果您调用 /news 而不使用尾部斜杠。这些重定向由我的自定义 index.php 快速处理,但我仍然想避免完全暴露 blog.domain.com
  • 第二种(也是目前非常流行的)方法再次将 blog.domain.comroot 直接指向 Wordpress 的目录 /home/webserver-blog/news/ 并欺骗所有静态请求带有location ~* ^/news/(wp-content|wp-admin) 指令的文件将其根目录向上一级。这对永久链接和静态文件都有效,但同样 - /news/wp-login.php 给了我无限重定向到 itself/news/wp-admin/ 实际上下载 index.php 文件而不是解析它(发送为 @987654334 @)

我完全没有想法...任何帮助将不胜感激。

【问题讨论】:

    标签: wordpress symfony redirect nginx reverse-proxy


    【解决方案1】:

    我想我设法提出了一个马马虎虎的解决方案。远非完美或干净,但是......好吧,它有效。

    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?$1 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/ 是另一个直接存储在 /home/webserver-blog/ 中的 index.php 文件:

    <?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';
    

    丑陋...但有效。 我仍然很高兴听到更好的解决方案。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-15
      • 2017-09-06
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多