3
votes

A situation has come up where server1, running Nginx, will forward all "/" locations to server2, while keeping "/api" and a few others on server1. This is also trying to keep SSL working. Trying to move the WP url from http://test.example.com to https://example.com has the front page load properly, but loading wp-admin gives too many redirects.

Server1 Nginx:

upstream webapp_url {
    server IP:80;
}

server {
        listen 443 ssl;
        server_name www.example.com example.com;
        access_log /var/log/nginx/example.log;

        ssl_certificate /etc/nginx/ssl/example.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;
        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        location /files/ {
                root /home;
                access_log off;
                expires max;
                if ($request_filename !~* ^.*?\.(jpg)|(png)|(gif)|(pdf)){
                        add_header Content-Disposition: "$request_filename";
                }
        }

        location / {
                # proxy_pass http://site_url/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_set_header X-Forwarded-Proto https;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Example "1";
                proxy_pass http://webapp_url/;
        }

This loads the other server fine, homepage and links all work (though mixed content warnings because I'm unable to change it in the admin). WP siteurl and home are both set to the new address.

Server2 Nginx:

server {
    #listen       443 ssl;
    listen 80;
    server_name example.com test.example.com;
    client_max_body_size 30M;
    error_log /var/log/wordpress/error.log info;
    location / {
        root   /home/wordpress;
        try_files $uri $uri/ /index.php?q=$request_uri;
        index index.php  index.html index.htm;
    }

    #ssl_certificate /etc/nginx/ssl/example.crt;
    #ssl_certificate_key /etc/nginx/ssl/example.key;
    #ssl_ciphers RC4:HIGH:!aNULL:!MD5;
    #ssl_prefer_server_ciphers on;

    error_page  404              /404.html;
    location = /404.html {
        root   /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    #
    location ~ \.php$ {
        root           /home/wordpress;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME   $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

Loading /wp-admin/ starts an infinite redirect (to the same url). I've defined it in wp-config.php too:

define('WP_HOME','https://example.com');
define('WP_SITEURL','https://example.com');
1

1 Answers

0
votes

wp-admin checks to see if the connection is secure, otherwise it redirects to the https version of the same URL. In a situation such as yours, this causes a redirect loop.

You need to tell WordPress that the connection is secure.

I notice that you set the appropriate header on server 1 with:

proxy_set_header X-Forwarded-Proto $scheme;

(In your case, the value of $scheme is hard-wired to https).

However, you also need to pass this to WordPress, in the form of an HTTPS parameter, with a value of on.

This is achieved with a map directive (on Server 2):

map $http_x_forwarded_proto $https_flag {
    default off;
    https on;
}
server {
    ...
}

(The map directive is placed within the http block. You can place it just above the server block as shown above. See this document for details)

In addition, add another fastcgi_param to pass the HTTPS parameter to WordPress (on Server 2):

location ~ \.php$ {
    ...
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS $https_flag;
    ...
}