NGINX Multisite Rewrite rules

The Nginx Multisite method outlined below has been tested and will work for subdomain Multisite installs and will also work with the domain mapping plugin.

To simplify the process of making future changes the server files are organized into 3 separate files. The first is nginx.conf which holds the basic configuration and tells the server where to find the vhosts.

nginx.conf

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
 
events {
    worker_connections 1024;
    # multi_accept on;
}
 
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;
    include mime.types;
    default_type  application/octet-stream;
    index index.php index.htm index.html redirect.php;
 
    #Gzip
    gzip  on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_types text/plain text/css application/json application/x-javascript text/xml
                        application/xml application/xml+rss text/javascript;
 
    #FastCGI
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort on;
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    fastcgi_read_timeout 120;
    fastcgi_index  index.php;
 
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
 
    ##
    # Virtual Host Configs
    ##
    include /etc/nginx/sites-enabled/*;  
}

The next file will be the global WordPress include and will hold all our rewrite rules.

wp-multi.conf

error_page 404 = @wordpress;
log_not_found off;
 
location / {
    try_files $uri $uri/ /index.php?$args;
}
 
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
 
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires max;
    log_not_found off;
}
 
rewrite ^/files/(.+) /wp-includes/ms-files.php?file=$1 last;
 
location ^~ /files/ {
    rewrite ^.*/files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
}
 
# Rewrite multisite '.../wp-.*' and '.../*.php'.
if (!-e $request_filename) {
    rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
    rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
}
 
location @wordpress {
        fastcgi_pass php;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        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  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        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;
 
        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;
 
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_NAME /index.php;
}
 
location ~ \.php$ {
    try_files $uri @wordpress;
    fastcgi_index index.php;
    fastcgi_pass php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    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  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        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;
 
        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;
 
        fastcgi_pass 127.0.0.1:9000;
}

The third file is our vhosts. If your using the domain mapping plugin you can include 1 line for each domain mapped site. You can also add additional static sites to this file if needed.

server {
     listen 80;
    #Add a server_name entry for each mapped domain

    server_name star.main-multisite-domain.com *.main-multisite.com;
    server_name mapped-domain.com www.mapped-domain.com;
    server_name mapped-domain-2.com www.mapped-domain-2.com;
    server_name mapped-domain-3.com www.mapped-domain-3.com;
 
    root /srv/www/wordpress/public;
    access_log /srv/www/wordpress/logs/access.log;
    error_log /srv/www/wordpress/logs/error.log;
    index index.php index.html index.htm;
 
        #The Multisite rules are in the include below
    include global-wp-multi.conf;
}
 
#Begin Static Non WP Sites
#Repeat the vhosts below for each additional static site.  Make sure you make each one a root directory
server {
 
    server_name static-non-wp-domain.com www.static-non-wp-domain.com;
    root /srv/www/static-non-wp-domain/public;
 
        error_log /srv/www/static-non-wp-domain/logs/error.log;
    index index.php index.html index.htm;
 
    }

For further reading on using WordPress with Nginx see: WordPress Performance Server – Nginx – Debian “squeeze”

Leave a Comment