Search code examples
wordpressnginxhttp-status-code-404permalinksgunicorn

Wordpress permalinks with 404 on nginx with gunicorn


I have Wordpress running on nginx which also runs gunicorn (to run django). Wordpress should be accessed on the subfolder www.mySite.de/blog/. The main page on this URL can be accessed, but when I open a link to a page (e.g. a page on www.mySite.de/blog/testpage ) then I get 404 errors.

My nginx configuration is as follows:

nginx.conf

#user  nobody;
user nginx nginx;

worker_processes  4;

pid /run/nginx.pid;

error_log /var/log/nginx/error.log debug;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

events {
    worker_connections  1024;
    accept_mutex on; # "on" if nginx worker_processes > 1
    # use epoll; # enable for Linux 2.6+
    # use kqueue; # enable for FreeBSD, OSX    
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

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

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     off;

    #keepalive_timeout  0;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    # Gzip Settings
    gzip on;
    gzip_http_version 1.0;
    gzip_proxied any;
    gzip_min_length 500;
    gzip_disable "MSIE [1-6]\.";
    gzip_types text/plain text/xml text/css
               text/comma-separated-values
               text/javascript application/x-javascript
               application/atom+xml;                

    # Virtual Host Configs
    include /etc/nginx/sites-enabled/*; 

}

production.conf (imported from 'sites-enabled' folder)

upstream production_nginx {# fail_timeout=0 means we always retry an upstream even if it failed
  # to return a good HTTP response (in case the Unicorn master nukes a
  # single worker for timing out).

  # for UNIX domain socket setups:
  server unix:/home/mySite/production/run/gunicorn.sock fail_timeout=0;
}  

upstream production_php {
  server unix:/var/run/php5-fpm.sock;
}

server {
    listen       80;
    server_name  mySite.de 
                 www.mySite.de;
    return       301 https://www.mySite.de$request_uri;
}

server {
    listen       443;
    server_name  mySite.de;
    return       301 https://www.mySite.de$request_uri;
} 

server {
  listen 443 ssl default_server;

  client_max_body_size 4G;
  server_name www.mySite.de;

  ssl_certificate      /etc/ssl/certs/www.mySite.de.crt;
  ssl_certificate_key  /etc/ssl/private/www.mySite.de.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;

  # ~2 seconds is often enough for most folks to parse HTML/CSS and
  # retrieve needed images/icons/frames, connections are cheap in
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;

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

  location /static/ {
      alias   /home/mySite/production/htdocs/static/;
  }

  location /media/ {
      alias   /home/mySite/production/htdocs/media/;
  }  

  location /blog/ {
    alias   /home/mySite/production/htdocs/blog/;
    index   index.php index.html index.htm;
    # This is cool because no php is touched for static content.
    # include the "?$args" part so non-default permalinks doesn't break when using query string
    try_files $uri $uri/ /blog/index.php?q=$uri;

    location ~ \.php$ {
      #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
      fastcgi_split_path_info ^(/blog)(/.*)$;
      fastcgi_intercept_errors on;
      fastcgi_pass production_php;
      fastcgi_index index.php;
      include fastcgi.conf;
    }
  }

  location /favicon.ico {
    alias   /home/mySite/production/htdocs/static/favicon.ico;
    log_not_found off;
    access_log off;
  }    

  # path for static files
  root /home/mySite/production/htdocs/;

  location / {

    # an HTTP header important enough to have its own Wikipedia entry:
    #   http://en.wikipedia.org/wiki/X-Forwarded-For
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # enable this if and only if you use HTTPS, this helps Rack
    # set the proper protocol for doing redirects:
    proxy_set_header X-Forwarded-Proto https;

    # pass the Host: header from the client right along so redirects
    # can be set properly within the Rack application
    proxy_set_header Host $http_host;

    # we don't want nginx trying to do something clever with
    # redirects, we set the Host: header above already.
    proxy_redirect off;

    # set "proxy_buffering off" *only* for Rainbows! when doing
    # Comet/long-poll stuff.  It's also safe to set if you're
    # using only serving fast clients with Unicorn + nginx.
    # Otherwise you _want_ nginx to buffer responses to slow
    # clients, really.
    # proxy_buffering off;

    # Try to serve static files from nginx, no point in making an
    # *application* server like Unicorn/Rainbows! serve static files.
    if (!-f $request_filename) {
          proxy_pass http://production_nginx;
          break;
    }      

  }

  # Error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /home/mySite/production/htdocs;
  }

  pagespeed on;
  pagespeed EnableFilters convert_meta_tags;
  pagespeed EnableFilters collapse_whitespace; # Remove whitespace
  pagespeed EnableFilters combine_javascript; # Merge JS files
  pagespeed EnableFilters rewrite_javascript; # Minimize JS
  pagespeed EnableFilters defer_javascript; # Load important JS first
  pagespeed EnableFilters combine_css; # Merge CSS files
  pagespeed EnableFilters rewrite_css; # Minimize CSS
  pagespeed EnableFilters move_css_to_head; # Move CSS to head
  pagespeed EnableFilters move_css_above_scripts; # Move CSS above JS
  pagespeed EnableFilters prioritize_critical_css; # Load important CSS first
  pagespeed EnableFilters fallback_rewrite_css_urls; # Fallback if CSS could not be parsed  
  pagespeed EnableFilters remove_comments; # Remove comments
  pagespeed FileCachePath /var/ngx_pagespeed_cache;  # Use tmpfs for best results.

  #  Ensure requests for pagespeed optimized resources go to the pagespeed
  #  handler and no extraneous headers get set.
  location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; }
  location ~ "^/ngx_pagespeed_static/" { }
  location ~ "^/ngx_pagespeed_beacon$" { }
  location /ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
  location /ngx_pagespeed_global_statistics { allow 127.0.0.1; deny all; }
  location /ngx_pagespeed_message { allow 127.0.0.1; deny all; }
  location /pagespeed_console { allow 127.0.0.1; deny all; }

  location /mod_pagespeed_example {
    location ~* \.(jpg|jpeg|gif|png|js|css)$ {
      add_header Cache-Control "public, max-age=600";
    }
  }    

}

nginx error log

2014/06/18 00:56:53 [error] 22133#0: *102248 open() "/home/mySite/production/htdocsindex.php" failed (2: No such file or directory), client: 92.227.135.241, server: www.mySite.de, request: "GET /blog/page1 HTTP/1.1", host: "www.mySite.de"

nginx access log

xx.xxx.135.241 - - [18/Jun/2014:01:35:02 +0200] "GET /blog/page1 HTTP/1.1" 404 200 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36"

Questions:

  1. I don't understand, why my configuration makes nginx search for index.php in

    /home/mySite/production/htdocsindex.php 
    

instead of

    /home/mySite/production/htdocs/blog/index.php 

Why is there a slash missing between htdocs and index.php and/or why is the /blog part missing completely?

  1. When i changed the trailing location block of production.conf from

      location /blog/ {
        alias   /home/mySite/production/htdocs/blog/;
    

to this

      location /blog {
        alias   /home/mySite/production/htdocs/blog/;

(removed the trailing slash) I did not get the nginx error page anymore, but then gunicorn and django kicked in an gave me a django 404 page. Why is django kicking in here?

  1. Also using

    try_files $uri $uri/ /blog/index.php?q=$uri&$args;
    

instead of

    try_files $uri $uri/ /blog/index.php?q=$uri;

did not solve the issue. What is wrong up with my configuration and how I can get Wordpress to work with nginx, gunicorn and django?

Thanks a lot, Chris


Solution

  • This is correct rewrites if your wordpress in subfolder (for example blog subfolder).

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

    You have root path it your config

    root /home/mySite/production/htdocs/

    so you can don't use alias in location (if your blog directory located in root folder).