FAQ

Page Discussion History

Difference between revisions of "WordPress"

(Non-root try_files to URL redirect: Added $args as its essential for wordpress plugin which add there own query_vars)
(Rewrite rules for Multisite: Added complete rewrite rules for WordPress multisite with Nginx's X-Accel-Redirect and map)
Line 82: Line 82:
  
  
=== Rewrite rules for Multisite ===
+
== Rewrite rules for Multisite ==
[http://codex.wordpress.org/Create_A_Network WordPress Multisite] requires permalinks and redirection to existing PHP files, thus we have to remove the blog name from the URLs.
+
[http://codex.wordpress.org/Create_A_Network WordPress Multisite] can be used in multiple ways. Most notably "subdirectories" mode and "subdomains" mode.
 +
 
 +
Nginx provides 2 special directive: [http://wiki.nginx.org/XSendfile X-Accel-Redirect] and [http://wiki.nginx.org/HttpMapModule#map map]. Using these 2 directives, one can eliminate performance hit for static-file serving on WordPress multisite network.
 +
 
 +
=== Rewrite rules for Multisite using subdirectories ===
  
 
<geshi lang="nginx">
 
<geshi lang="nginx">
location / {
+
map $uri $blogname{
    error_page 404 = @wp;
+
~^(?P<blogpath>/[^/]+/)files/(.*) $blogpath ;
 +
}
  
    location ~* \.(php|inc)$ {
+
map $blogname $blogid{
# Forbid PHP on upload dirs
+
default -999;
        if ($uri ~ "uploads") {
+
            return 403;
+
        }
+
  
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+
#Ref: http://wordpress.org/extend/plugins/nginx-helper/
        fastcgi_intercept_errors on;
+
#include /var/www/wordpress/wp-content/plugins/nginx-helper/map.conf ;
        include fastcgi_params;
+
}
        fastcgi_pass php;
+
    }
+
  
 +
server {
 +
server_name example.com ;
 +
 +
root /var/www/example.com/htdocs;
 +
index index.php;
 +
 +
location ~ ^(/[^/]+/)?files/(.+) {
 +
try_files /wp-content/blogs.dir/$blogid/files/$2 /wp-includes/ms-files.php?file=$2 ;
 +
access_log off; log_not_found off; expires max;
 +
}
 +
 +
#avoid php readfile()
 +
location ^~ /blogs.dir {
 +
internal;
 +
alias /var/www/example.com/htdocs/wp-content/blogs.dir ;
 +
access_log off; log_not_found off; expires max;
 +
}
 +
 +
if (!-e $request_filename) {
 +
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
 +
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
 +
rewrite ^(/[^/]+)?(/.*\.php) $2 last;
 +
}
 +
 +
location / {
 +
try_files $uri $uri/ /index.php?$args ;
 +
}
 +
 +
location ~ \.php$ {
 +
try_files $uri =404;
 +
include fastcgi_params;
 +
fastcgi_pass php;
 +
}
 +
 +
#add some rules for static content expiry-headers here
 
}
 
}
 +
</geshi>
  
# Rewrite rules. Blog name must be removed.
+
=== Rewrite rules for Multisite using subdomains ===
location @wp {
+
  
# Redirect to files
+
<geshi lang="nginx">
  rewrite ^(/[^/]+/)?files/(.+) /wp-includes/ms-files.php?file=$2 last;
+
map $http_host $blogid {
 +
    default      -999;
  
# Match only one section
+
    #Ref: http://wordpress.org/extend/plugins/nginx-helper/
  rewrite ^(/[^/]+)?(/wp-.*) $2 last;
+
    #include /var/www/wordpress/wp-content/plugins/nginx-helper/map.conf ;
  rewrite ^(/[^/]+)?(/.*\.php) $2 last;
+
  
# Send everything else to index.php (permalinks)
+
}
  rewrite ^/(.*)$ /index.php?q=$1 last;
+
 
 +
server {
 +
server_name example.com *.example.com ;
 +
 
 +
root /var/www/example.com/htdocs;
 +
index index.php;
 +
 
 +
location / {
 +
try_files $uri $uri/ /index.php?$args ;
 +
}
 +
 
 +
location ~ \.php$ {
 +
try_files $uri =404;
 +
include fastcgi_params;
 +
fastcgi_pass php;
 +
}
 +
 
 +
#WPMU Files
 +
        location ~ ^/files/(.*)$ {
 +
                try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1 ;
 +
                access_log off; log_not_found off;      expires max;
 +
        }
 +
 
 +
#WPMU x-sendfile to avoid php readfile()
 +
location ^~ /blogs.dir {
 +
internal;
 +
alias /var/www/example.com/htdocs/wp-content/blogs.dir;
 +
access_log off; log_not_found off; expires max;
 +
}
  
 +
#add some rules for static content expiry-headers here
 
}
 
}
 
</geshi>
 
</geshi>
 +
 +
==== Notes ====
 +
map section can be completed manually or using a wordpress plugin [1].
 +
 +
= References =
 +
* [http://wordpress.org/extend/plugins/nginx-helper/ Nginx Helper Plugin for map]
 +
* [http://rtcamp.com/series/wordpress-nginx-tutorials/ WordPress-Nginx Tutorials]

Revision as of 12:43, 19 October 2012

Nginx works perfectly well with a wide variety of applications, and WordPress is certainly one of them. NginX's configuration language is very powerful and straightforward if one is familiar with it, but often people coming from other servers are not sure how things work in NginX and just copy and paste whatever they see from a blog that seems to fill their needs. Everyone, especially people new to NginX, should check out the nginx.org documentation for an overview of how things work and should be done in NginX.

Contents

Abridged basic setup

Hopefully you have read the documentation above and maybe worked on setting up a virtual server or two in Nginx already - if not there are a few notes below, but you should still read the documentation.

First we setup a named upstream for our php, which allows us to abstract the backend and easily change the port or add more backends. After that, we setup our virtual host configuration for domain.tld.

# Upstream to abstract backend connection(s) for php
upstream php {
        server unix:/tmp/php-cgi.socket;
        server 127.0.0.1:9000;
}
 
server {
        ## Your website name goes here.
        server_name domain.tld;
        ## Your only path reference.
        root /var/www/wordpress;
        ## This should be in your http block and if it is, it's not needed here.
        index index.php;
 
        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }
 
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
 
        location / {
                # 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/ /index.php?$args;
        }
 
        location ~ \.php$ {
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include fastcgi.conf;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
        }
 
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                log_not_found off;
        }
}

With this configuration we should be able to serve wordpress very easily. Once you setup your backend (php-cgi or php-fpm) should work perfectly.

Location Strategies

There are many ways to declare your locations in your configuration that allow you to do basically whatever you want with your URLs. Usually, people want to have "pretty" URLs that hide the query strings and script files. Here are a few different strategies based on different goals. Here we are defining locations that should be used to replace the basic locations above in order to achieve the desired results.

Non-root try_files to URL redirect

If you want to serve WordPress as a sub directory, you will want to make the following changes (relative to the above configuration).

        location /wordpress {
                try_files $uri $uri/ /wordpress/index.php?$args;
        }
 
        location ~ \.php$ {
                fastcgi_split_path_info ^(/wordpress)(/.*)$;
        }

Pre-0.8.30 fastcgi settings

If you are using a version below 0.8.30, you will want to add this to your fastcgi_params file.

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


Rewrite rules for Multisite

WordPress Multisite can be used in multiple ways. Most notably "subdirectories" mode and "subdomains" mode.

Nginx provides 2 special directive: X-Accel-Redirect and map. Using these 2 directives, one can eliminate performance hit for static-file serving on WordPress multisite network.

Rewrite rules for Multisite using subdirectories

map $uri $blogname{
	~^(?P<blogpath>/[^/]+/)files/(.*)	$blogpath ;
}
 
map $blogname $blogid{
	default -999;
 
	#Ref: http://wordpress.org/extend/plugins/nginx-helper/
	#include /var/www/wordpress/wp-content/plugins/nginx-helper/map.conf ;
}
 
server {
	server_name example.com ;
 
	root /var/www/example.com/htdocs;
	index index.php;
 
	location ~ ^(/[^/]+/)?files/(.+) {
		try_files /wp-content/blogs.dir/$blogid/files/$2 /wp-includes/ms-files.php?file=$2 ;
		access_log off;	log_not_found off; expires max;
	}
 
	#avoid php readfile()
	location ^~ /blogs.dir {
		internal;
		alias /var/www/example.com/htdocs/wp-content/blogs.dir ;
		access_log off;	log_not_found off; expires max;
	}
 
	if (!-e $request_filename) {
		rewrite /wp-admin$ $scheme://$host$uri/ permanent;	
		rewrite ^(/[^/]+)?(/wp-.*) $2 last; 
		rewrite ^(/[^/]+)?(/.*\.php) $2 last; 
	}
 
	location / {
		try_files $uri $uri/ /index.php?$args ;
	}
 
	location ~ \.php$ {
		try_files $uri =404;
		include fastcgi_params;
		fastcgi_pass php;
	}
 
	#add some rules for static content expiry-headers here
}

Rewrite rules for Multisite using subdomains

map $http_host $blogid {
    default       -999;
 
    #Ref: http://wordpress.org/extend/plugins/nginx-helper/
    #include /var/www/wordpress/wp-content/plugins/nginx-helper/map.conf ;
 
}
 
server {
	server_name example.com *.example.com ;
 
	root /var/www/example.com/htdocs;
	index index.php;
 
	location / {
		try_files $uri $uri/ /index.php?$args ;
	}
 
	location ~ \.php$ {
		try_files $uri =404;
		include fastcgi_params;
		fastcgi_pass php;
	}
 
	#WPMU Files
        location ~ ^/files/(.*)$ {
                try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1 ;
                access_log off; log_not_found off;      expires max;
        }
 
	#WPMU x-sendfile to avoid php readfile()
	location ^~ /blogs.dir {
		internal;
		alias /var/www/example.com/htdocs/wp-content/blogs.dir;
		access_log off;	log_not_found off;	expires max;
	}
 
	#add some rules for static content expiry-headers here
}

Notes

map section can be completed manually or using a wordpress plugin [1].

References