简体   繁体   English

使用 NGINX 作为 apache 的反向代理时,Wordpress 永久链接返回 404

[英]Wordpress Permalinks return 404 when using NGINX as a reverse proxy to apache

I am trying to get NGINX to reverse proxy & provide SSL Termination for a WordPress site running on Apache at port 8086. I want NGINX to handle the static files, and proxy only PHP requests to Apache.我正在尝试让 NGINX 反向代理并为在 Apache 上运行的 WordPress 站点提供 SSL 终止,端口为 8086。我希望 NGINX 处理静态文件,并且只代理对 Apache 的 PHP 请求。

I have been successful in getting this to work using standard links.我已经成功地使用标准链接让它工作。 (ie https://example.com/?post=274 works correctly) (即https://example.com/?post=274工作正常)

When I enable permalinks of any kind, the home page will load, as will wp-admin, but https://example.com/what-we-do/ fails.当我启用任何类型的永久链接时,主页将加载,wp-admin 也会加载,但https://example.com/what-we-do/失败。

Looking at the NGINX logs, I see查看 NGINX 日志,我看到了

2018/05/23 09:36:40 [error] 7472#0: *1 "/var/www/example.com/live_site/what-we-do/index.php" is not found (2: No such file or directory), client: xxx.xxx.xxx.xxx, server: example.com, request: "GET /what-we-do/ HTTP/2.0", host: "example.com", referrer: "https://example.com/?post=274"

So NGINX is attempting to look for /permalink/index.php as a static path/file instead of passing to apache.所以 NGINX 试图寻找 /permalink/index.php 作为静态路径/文件,而不是传递给 apache。 Any thoughts on how to get this to work?关于如何让它发挥作用的任何想法?

My NGINX Config looks like:我的 NGINX 配置看起来像:

upstream example_apache {
    ip_hash;
    server 127.0.0.1:8086;
}

server {
# HTTP/HTTPS Server Block
# General Config
    listen                      [::]:80;
    listen                      80;
    listen                      [::]:443 http2 ssl;
    listen                      443 http2 ssl;
    server_name                 example.com
                                www.example.com;

    root                        /var/www/example.com/live_site;
    access_log                  /var/log/nginx/access-example.com.log main;
    error_log                   /var/log/nginx/error-example.com.log;
    index                       index.php;

#SSL Cert Configuration
# Check SSL config at https://www.ssllabs.com/ssltest/
    ssl_prefer_server_ciphers   on;
    ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                 "ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH DHE-RSA-CHACHA20-POLY1305 EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4 !SEED !CAMELLIA";
    ssl_session_cache           shared:SSL:100m;
    ssl_session_timeout         180m;
    ssl_dhparam                 /var/www/certs/dh4096.pem;

    ssl_certificate             /var/www/certs/lets_encrypt/web01.example.com/web01.example.com.fullchain.secp384r1.cer;
    ssl_certificate_key         /var/www/certs/lets_encrypt/web01.example.com/web01.example.com.secp384r1.key;
    ssl_certificate             /var/www/certs/lets_encrypt/web01.example.com/web01.example.com.fullchain.rsa4096.cer;
    ssl_certificate_key         /var/www/certs/lets_encrypt/web01.example.com/web01.example.com.rsa4096.key;

# Enable HSTS #Deploy in stages to prevent extended loss to site.
    add_header                  Strict-Transport-Security "max-age=300; includeSubdomains;"; #300s-5min TTL Testing
    #add_header                 Strict-Transport-Security "max-age=604800; includeSubdomains;"; #1week TTL Testing
    #add_header                 Strict-Transport-Security "max-age=2592000; includeSubdomains;"; #1month TTL Testing
    #add_header                 Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; #10886400s-126days Min for Preload
    #add_header                 Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; #63072000s-2years Production Value

# OCSP Configuration
    ssl_trusted_certificate     /var/www/certs/lets_encrypt/web01.example.com/web01.example.com.fullchain.secp384r1.cer;
    ssl_stapling                on;
    ssl_stapling_verify         on;
    resolver                    8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout            10s;

# LetEncrypt webroot alias
    location /.well-known/acme-challenge/ {
        alias /var/www/le_root/.well-known/acme-challenge/;
    }
# www to non-www rewrite
# Redirect to the correct place, if needed
    set $https_redirect 0;
    if ($server_port = 80) { set $https_redirect 1; }
    if ($host ~ '^www\.') { set $https_redirect 1; }
    if ($https_redirect = 1) {
        return 301 https://example.com$request_uri;
    }

# Wordpress entry point
    location / {
        #Try                    file dir    index.php else 404
        try_files               $uri $uri/ /index.php?$args =404;

        #All Files except for *.php
        location ~ .+(?<!\.php)$ {
            location ~ ^[^.]+\.[^.]+$ {
                expires         max;
                add_header      Cache-Control public;
                break;
            }
        }

        #Only *.php files
        location ~ \.php$ {
            proxy_set_header    X-Real-IP           $remote_addr;
            proxy_set_header    Host                $host;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto   $scheme;
            proxy_pass_header                       Set-Cookie;

            proxy_set_header    SSL_PROTOCOL        $ssl_protocol;
            proxy_set_header    SSL_CLIENT_CERT     $ssl_client_cert;
            proxy_set_header    SSL_CLIENT_VERIFY   $ssl_client_verify;
            proxy_set_header    SSL_SERVER_S_DN     $ssl_client_s_dn;

            proxy_pass                              http://example_apache;
        }
    }
}

Since this issue isnt even getting to the proxy pass part, and appears to be strictly NGINX related (that I can tell), the following doesnt apply.由于这个问题甚至没有涉及代理通行证部分,而且似乎与 NGINX 严格相关(我可以说),因此以下内容不适用。 But someone will be wondering, or it may help others stumbling on this question to know the apache config side as well.但是有人会想知道,或者它可能会帮助其他在这个问题上绊倒的人也了解 apache 配置方面。

My apache has an .htaccess file containing:我的 apache 有一个 .htaccess 文件,其中包含:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

And my wp-config.php has:我的 wp-config.php 有:

// If WordPress is behind reverse proxy
// which proxies https to http
if ( (!empty( $_SERVER['HTTP_X_FORWARDED_HOST'])) ||
 (!empty( $_SERVER['HTTP_X_FORWARDED_FOR'])) ) {

$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];

$_SERVER['HTTPS'] = 'on';
}

And my apache config has:我的 apache 配置有:

<VirtualHost *:8086>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/example.com/live_site
ServerName  example.com
ServerAlias www.example.com


ErrorLog ${APACHE_LOG_DIR}/example.com.error.log
CustomLog ${APACHE_LOG_DIR}/example.com.access.log combined

Alias "/.well-known/acme-challenge/" "/var/www/le_root/.well-known/acme-challenge/"

<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
<Directory /var/www/example.com/live_site>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
</Directory>

</VirtualHost>

I should also note, when I connect directly to Apache I can see all of the page permalinks correctly.我还应该注意,当我直接连接到 Apache 时,我可以正确地看到所有页面的永久链接。 (ie http://127.0.0.1:8086/what-we-do/ works correctly) (即http://127.0.0.1:8086/what-we-do/工作正常)

NGINX version 1.13.9 NGINX 版本 1.13.9
Apache 2.4.33 mpm_prefork阿帕奇 2.4.33 mpm_prefork
PHP version 7.1 PHP 版本 7.1

Any thoughts or help getting NGINX to correctly proxy permalinks to apache would be greatly appreciated!任何想法或帮助让 NGINX 正确代理到 apache 的永久链接将不胜感激!

Enable or check if mod_rewrite is enabled with this command启用或检查是否使用此命令启用了 mod_rewrite

sudo a2enmod rewrite sudo a2enmod 重写

I received this same error when I was migrating my Prod environment to Docker, using NGINX, but I was not reverse proxying for Apache.当我使用 NGINX 将我的 Prod 环境迁移到 Docker 时,我收到了同样的错误,但我没有为 Apache 进行反向代理。 My error was the same, though.不过,我的错误是一样的。

The reason was that I had to change the wp_options to match my new local Port and URL.原因是我必须更改wp_options以匹配我的新本地端口和 URL。

SELECT * FROM wp_options WHERE option_name='siteurl' OR option_name='home'; will show you the current URL that your WordPress Config is trying to navigate to.将显示您的 WordPress 配置尝试导航到的当前 URL。 But since you've created a Proxy and now have your WordPress site behind a different port or URL, you might need to change these values.但是由于您已经创建了一个代理并且现在您的 WordPress 站点位于不同的端口或 URL 后面,您可能需要更改这些值。

When you execute that command, you will receive a list of the two URLs that your site is using as your prefix.当您执行该命令时,您将收到您的站点用作前缀的两个 URL 的列表。 If it's showing the URL of the Proxy, this probably won't work.如果它显示代理的 URL,这可能不起作用。

I then modified the URLs to match the location of the NEW backend URL + Port.然后我修改了 URL 以匹配新后端 URL + 端口的位置。 In your case, you will have to likely change it to match the port and url BEHIND the proxy, not the URL of the proxy itself.在您的情况下,您可能必须更改它以匹配代理后面的端口和 url,而不是代理本身的 URL。

Modifying these values inside my wp-config.php did NOT WORK.在我的wp-config.php中修改这些值不起作用。 eg例如

 define('WP_HOME','http://local.www.greenhousetreatment.com:8080');
 define('WP_SITEURL','http://local.www.greenhousetreatment.com:8080');

THIS DID NOT WORK FOR ME.这对我不起作用。

I had to manually use the command above in SQL, then UPDATE those values to match both the PORT and the URL of the website.我必须在 SQL 中手动使用上面的命令,然后更新这些值以匹配 PORT 和网站的 URL。 Normally in reverse proxies, you will type in the Proxy URL, it will then hit your service IP, and port.通常在反向代理中,您将输入代理 URL,然后它将访问您的服务 IP 和端口。 Your service IP and PORT does what it needs to do, as it does not care at all about the proxy.您的服务 IP 和 PORT 完成了它需要做的事情,因为它根本不关心代理。 It doesn't even know about the proxy.它甚至不知道代理。

Are you sure your wp_options match the actual service URL and PORT, and not the Proxy URL?你确定你的wp_options匹配实际的服务 URL 和端口,而不是代理 URL?

I hope this could shed some light.我希望这可以提供一些启示。

I'm having the same problem today, and my setup just like yours, what i did to solve this;我今天遇到了同样的问题,我的设置和你的一样,我做了什么来解决这个问题;

modify the nginx config and just add/move the index index.php from server block into location / block.修改 nginx 配置,只需将index index.php从服务器块添加/移动到location /块。

Here is the example as I comment on the index index.php at server block then add it into location block.这是我在服务器块中评论index index.php然后将其添加到位置块中的示例。

server {
   ...
   root                        /var/www/example.com/live_site;
   access_log                  /var/log/nginx/access-example.com.log main;
   error_log                   /var/log/nginx/error-example.com.log;
   #index                       index.php; ##REMOVE THIS ONE 
   ...
# Wordpress entry point
     location / {
        index index.php index.html ##THEN ADD HERE
        #Try                    file dir    index.php else 404
         try_files               $uri $uri/ /index.php?$args =404;
       ...
}

also don't forgot to check the .htaccess ensure it is for WordPress permalink, or can just go to wordpress setting then save the permalink setting to Post name .也不要忘记检查.htaccess确保它适用于 WordPress 永久链接,或者可以转到 wordpress 设置然后将永久链接设置保存到Post name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM