Nginx & Apache Cannot get try_files to work with permalinks

tcherokee asked:

I have been working on this for the past two weeks not and for some reason I cannot seem to get nginx’s try_files to work with my wordpress permalinks. I am hoping someone will be able to tell me where I am going wrong and also hopefully tell me if I made any major errors with my configurations as well (I am an nginx newbie… but learning 🙂 ).

Here are my Configuration files


user www-data;
worker_processes 4;
pid /var/run/;

events {
    worker_connections 768;
    # multi_accept on;

http {

    # Basic Settings

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging Settings

    # Defines the cache log format, cache log location
    # and the main access log location.
    log_format cache '***$time_local '
            '$upstream_cache_status '
            'Cache-Control: $upstream_http_cache_control '
            'Expires: $upstream_http_expires '
            '$host '
            '"$request" ($status) '
            '"$http_user_agent" '

    access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;


server {
    listen 123.456.78.901:80; # IP goes here.
    #root /var/www/;
    index   index.php;

## -> (301 - Permanent)
    if ($host !~* ^(www|dev))
            rewrite ^/(.*)$ $scheme://www.$host/$1 permanent;

# Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# All media (including uploaded) is under wp-content/ so
    # instead of caching the response from apache, we're just
    # going to use nginx to serve directly from there.
    location ~* ^/(wp-content|wp-includes)/(.*)\.(jpg|png|gif|jpeg|css|js|m$
            root    /var/www/;

# Don't cache these pages.
    location ~* ^/(wp-admin|wp-login.php)
        proxy_pass http://backend;

location / {
    if ($http_cookie ~* "wordpress_logged_in_[^=]*=([^%]+)%7C") {
            set $do_not_cache 1;
    proxy_cache_key "$scheme://$host$request_uri $do_not_cache";
    proxy_cache main;
    proxy_pass http://backend;
    proxy_cache_valid 30m; # 200, 301 and 302 will be cached.
    # Fallback to stale cache on certain errors.
    # 503 is deliberately missing, if we're down for maintenance
    # we want the page to display.
    #try_files $uri $uri/ /index.php?q=$uri$args;
    #try_files $uri =404;
    proxy_cache_use_stale error

# Cache purge URL - works in tandem with WP plugin.
#        location ~ /purge(/.*) {
#           proxy_cache_purge main "$scheme://$host$1";
#        }

# No access to .htaccess files.
    location ~ /\.ht {
            deny  all;

} # End server


    # Gzip Configuration.
    gzip on;
    gzip_disable msie6;
    gzip_static on;
    gzip_comp_level 4;
    gzip_proxied any;
    gzip_types text/plain


# Set proxy headers for the passthrough
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_max_temp_file_size 0;

    client_max_body_size       10m;
    client_body_buffer_size    128k;

    proxy_connect_timeout      90;
    proxy_send_timeout         90;
    proxy_read_timeout         90;

    proxy_buffer_size          4k;
    proxy_buffers              4 32k;
    proxy_busy_buffers_size    64k;
    proxy_temp_file_write_size 64k;
    add_header X-Cache-Status $upstream_cache_status;


upstream backend {
        # Defines backends.
        # Extracting here makes it easier to load balance
        # in the future. Needs to be specific IP as Plesk
        # doesn't have Apache listening on localhost.
        server; # IP goes here.


# Proxy cache and temp configuration.
proxy_cache_path /var/www/nginx_cache levels=1:2
                 max_size=1g inactive=30m;
proxy_temp_path /var/www/nginx_temp;

    proxy_cache_key "$scheme://$host$request_uri";
proxy_redirect off;

    # Cache different return codes for different lengths of time
# We cached normal pages for 10 minutes
proxy_cache_valid 200 302  10m;
proxy_cache_valid 404      1m;

The two commented out try_files in location \ of the mydomain config files are the ones I tried. This error I found in the error log can be found below.

 ...rewrite or internal redirection cycle while internally redirecting to "/index.php"

Thanks in advance

My answer:

That looks like a terribly complicated setup.

My first thought is to advise you to get rid of Apache entirely; nginx + php-fpm is perfectly capable of serving your WordPress blog, and most of the WordPress nginx rules you will find expect nginx to be used as the origin server rather than a reverse proxy to Apache.

Now, on with the show…

You can’t use try_files in the same location block where you are passing the request upstream. It would just be ignored since everything is going to the proxy anyway. If you want to make this work, I suggest using a named location. Something like this (off the top of my head):

root /var/www/whatever;

location @apache {
    # proxy directives here

location / {
    try_files $uri $uri/ @apache;

The idea here is that you let nginx handle stuff that nginx can handle first, and then pass everything else upstream.

Of course, add in any additional directives you need, but the idea is to start simple, make sure the basic stuff works, and only then add stuff in to rewrite static page requests, cookies, etc.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.