Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to serve wordpress 3 multisite with nginx, and this is my nginx conf

server {
    listen 80;
    index index.html;
    access_log /usr/local/var/log/nginx/lc.wp.access.log;
    error_log /usr/local/var/log/nginx/lc.wp.error.log debug;

    location / {
        root /usr/local/www/playground/php/wordpress/;
        autoindex on;
        index  index.html index.htm index.php;
        rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=$1 last;
        try_files $uri $uri/ @rewrite;

    location @rewrite {
        rewrite ^.+?(/wp-.*) $1 last;
        rewrite ^.+/?(/.*\.php)$ $1 last;
        rewrite ^(.+)$ /index.php?q=$1 last;

    location ~* ^.+\.(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$
        root /usr/local/www/playground/php/wordpress/;
        rewrite ^/.*(/wp-.*/.*\.(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js))$ $1 last;
        rewrite ^.*/files/(.*(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js))$/wp-includes/ms-files.php?file=$1 last;
        expires 30d;

    location ~ \.php {
        root /usr/local/www/playground/php/wordpress/;
        include /usr/local/etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

I create a subsite "sub1", then amazing happens:

if i visit below url, it works normally

if i visit

server told me 404 not found

curl -I\?post_type\=post
HTTP/1.1 404 Not Found
Server: nginx/1.0.2
Date: Thu, 16 Jun 2011 10:25:11 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.3.5

if i disable php parse (comment php part), and set

rewrite ^.+?(/wp-.*) $1 redirect;

server 302 moved normally, and told me to save post-new.php file.

a bit crazy now. T_T

share|improve this question
I'm not surprised you can't figure this out after toking for four hours! ;) Sorry, I couldn't resist. – Eduardo Ivanec Jun 16 '11 at 10:33
Please don't anyone edit this :) – Chopper3 Jun 16 '11 at 10:36
What's on your error.log when you try with the rewrite on? If you don't see anything helpful add this to your config file: rewrite_log on; and try again. – Eduardo Ivanec Jun 16 '11 at 10:38
the error.log is empty!!! that's the craziest part. add rewrite_log on still no luck :( – limboy Jun 16 '11 at 10:44
come on, may be i'm stupid, can anyone point out the reason? – limboy Jun 16 '11 at 10:47
up vote 2 down vote accepted

What you posted is really messy. Nginx processes location directives in a specific order, and only matches one (unless rewritten). Stop toke'n for a bit, erase what you have, and try this:

server {
    listen       80;
    index index.php index.html;
    access_log /usr/local/var/log/nginx/lc.wp.access.log;
    error_log /usr/local/var/log/nginx/lc.wp.error.log debug;

    root /usr/local/www/playground/php/wordpress/;

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

    location @wordpress {
        rewrite ^/([_0-9a-zA-Z-]+/)?files/(.+) /wp-includes/ms-files.php?file=$2 last;
        rewrite ^/([_0-9a-zA-Z-]+/)?wp-admin$ /$1wp-admin/ permanent;
        rewrite ^/[_0-9a-zA-Z-]+/(wp-(content|admin|includes).*) /$1 last;
        rewrite ^/[_0-9a-zA-Z-]+/(.*\.php)?$ /$1 last;
        rewrite .* /index.php last;

    location ~ \.php$ {
        if (!-e $request_filename) {
            rewrite ^/[_0-9a-zA-Z-]+/(wp-(content|admin|includes).*) /$1 last;
            rewrite ^/[_0-9a-zA-Z-]+/(.*\.php)?$ /$1 last;
            rewrite .* /index.php last;
            return 404;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
share|improve this answer
it works, thank you~ – limboy Jun 16 '11 at 23:55
and I found the problem of my origin nginx config. like you said, order matters – limboy Jun 17 '11 at 0:11

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.