nginx try_files, proxy_pass and upstream

I’m building a dockerised testing ‘platform’ for PHP apps – specifically (for the moment) for WordPress. I’m using PHPFarm to serve different versions of PHP on different ports. Using nginx in front, I’ve got much of it working. ( https://github.com/richardtape/testit is the main repo )

The big issue I’m facing now is getting WordPress’s “pretty permalinks” to work. In a standard nginx setup, it’s just a case of something like

Read More
location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}

But in order to be able to have nice urls from the host machine, and in order to have one code base, I’m using something along the following lines:

server {
    listen 80;
    index index.php index.html index.htm;
    server_name 52.spaces.dev;

    location / {

        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    root /var/www;
}

upstream phpfarm_52{
    server phpfarm:8052;
}

This, as it stands, works. (There are 5 more rules similar for this for PHP 5.3, 5.4, 5.5, 5.6 and 7) The home page loads on each of the different server_names from the host machine (and if you output the PHP version on each of them, you can see that you’re getting a different PHP version).

However, the second I switch to an ‘internal’ url (or any non-root i.e. http://52.spaces.dev/about/), I get a 404. I’ve tried something similar to

location / {
    try_files $uri $uri/ /index.php?$args
}

location ~ .php$ {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

I get a redirect loop, depending on a few different ways I’ve tried it’s either just been a series of 301 redirects and the page never loads or an error such as

nginx_1      | 2016/04/08 20:31:29 [error] 5#5: *4 rewrite or internal redirection cycle while processing "/index.php", client: 192.168.99.1, server: 52.spaces.dev, request: "GET /favicon.ico HTTP/1.1", host: "52.spaces.dev", referrer: "http://52.spaces.dev/"

I’m stuck. I’m also pretty new to nginx configuration (which may be obvious) so I might well be doing something completely wrong and/or dumb. Any suggestions?

Related posts

1 comment

  1. The issue you’re experiencing with the redirect loop in your question is that basically every request, even for static files tries to route via your index.php?$args block.

    I see 2 possible solutions here. First, if you are willing to implement the nginx setup with a single nginx instance, look at this thread: NGINX try_files with multiple named locations and this blog post http://linuxplayer.org/2013/06/nginx-try-files-on-multiple-named-location-or-server

    What needs to happen, is you need to first test if the resource is present on the upstream as is (i.e., doesn’t return 404). If it does, then you serve it as is. If it does not, then you would be calling the rewrite block which tries to put it as a parameter to index.php. So you would end up with something like this (sorry, I don’t really have a chance to test this, but hopefully it gives an idea):

    location / {
        try_files $uri $uri/ @phpproxy;
    }
    
    location @phpproxy {
        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_intercept_errors on;
        recursive_error_pages on;
        error_page 404 = @rewrite_proxy;
    }
    
    location @rewrite_proxy {
        rewrite ^/(.*)$ /index.php?$1 break;
        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    

    The second solution (that I would personally prefer) is to front every upstream with its own nginx. Then the top nginx which is fronting all others will have a much cleaner structure with simple proxy_pass’s (+ maybe some static content) and that’s it. It will also cut down on the request round-trip, since you wouldn’t need to resolve 404’s coming from the upstreams.

Comments are closed.