Migrate from Apache to nginx (and keep rewrites intact)
nginx is a very fast and very lightweight web server that can handle static HTML blazingly fast, and does very well with dynamic (PHP) content as well. In fact the very site your viewing is running atop of nginx. nginx isn’t ideal for every server, and can’t handle SVN or WebDAV among other protocols. But for your average site running PHP, Ruby or Django, nginx is choice.
The trouble was that I have lots of site (like this one!) that rely on a myriad of rewrite rules and logic to direct users properly. Because we lose the mod_rewrite provided by apache, we need to tell nginx about our rewrite rules.
Luckily the logic is very similar, and all expression based as before…
create domain specific configuration
The first step is creating directories for each site you want to customize. Any file within this directory will be read into configuration when nginx starts or reloads.
/home/my_user/nginx/edwardawebb.com/wordpress.conf
Harvest those .htaccess files
next we turn to our existing rules as a launch pad for our new rewrite logic.
your apache rule (from .htaccess)
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
your new nginx config (into wordpress.conf)
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?url=$1 last;
}
Note the similarity!
” if the path they are looking for does not exist, give them this path instead. ”
The differences are subtle but important. Apache assumed absolute paths in the created path, so index.php would be /index.php – but nginx does not make that assumption, so we need to explicitly include the root /.
Got more rules to rewrite?
I am actually finding nginx’s logic based syntax much easier to master than Apache’s. You can specify rules for specific domains or servers, and use many variables including the user agent and
http://nginx.org/en/docs/http/converting_rewrite_rules.html
http://wiki.nginx.org/NginxConfiguration
Reload nginx
For any changes to take affect you will need to force nginx to reload.
sudo /etc/init.d/nginx reload
If you still have questions maybe it is because you have not read the page here – but please post your thoughts!
Your example can be simplified significantly and it appears you are using old WordPress .htaccess rules. Use ‘try_files’ wherever possible because “if is evil” under nginx.
Also, be aware that bad configurations in nginx can and likely will introduce security vulnerabilities into your website. nginx is a proxy server first and a web server second, so it defaults to the assumption that files may not necessarily exist on the host it is running on and a simple regular expression can cause havoc. An example of this:
http://forum.nginx.org/read.php?2,88845
Took them way too long to come up with a reasonable solution to the problem. And, if you read through the conversation, people today are still getting bitten by the issue. As an added bonus, it doesn’t look like there will ever be a solution to the problem because it isn’t fixable and Igor isn’t interested in fixing it.
@james
Thanks for the info!
I took a look at my config files and should be ok, runninga pretty recent version.
As for simplifying the wordpress script,i would love to hear more, perhaps am example.
Eddie: the try_files directive just gives nginx a fallback in case the request URI is invalid. Basic syntax would be something like this, based on your example:
try_files $uri $uri/ /index.php?url=$uri&$args;