Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

How to convert Apache rewrites for nginx

  
  
  

Apache is still by far the most widely deployed HTTP server, according to the latest Netcraft web server survey, but nginx has been slowly, steadily gaining market share, thanks to its blazing speed. If you want to try a faster web server and move from Apache to nginx, you'll probably have to change some of your websites' configurations, starting with rewrite directives. To migrate rewrite rules from Apache to nginx, start with these tips and tricks.

The Apache mod_rewrite module provides powerful and sophisticated tools for nearly all types of URL rewriting. It is, however, somewhat complex, and may be intimidating to beginners. In fact, however, rewrite rules are not magical incantations, though to understand them you need some understanding of regular expressions.

Even if you have never heard of mod_rewrite, you may still be using it. Popular applications such as WordPress, Drupal, and Magento are shipped with .htaccess files that contain standard configurations that make these applications work properly, and these usually include one or more rewrites, so to properly move your website to an nginx web server you have to "translate" the Apache mod_rewrite directives into equivalent rules for nginx's HttpRewriteModule.

If you want to see whether your website is using mod_rewrite, you can use this approach:

In your document root, the directory where you have all your HTML files, add a file named .htaccess, or modify it if it already exists, and make sure it contains these lines:

<IfModule mod_rewrite.c>
    // Tell PHP that the mod_rewrite module is ENABLED.
    SetEnv HTTP_MOD_REWRITE On
</IfModule>

Then add a second file in your document root named check_rewrite.php with the following content:

<?php

if (is_mod_rewrite_enabled()) {
  print "The apache module mod_rewrite is enabled.
\n"; } else { print "The apache module mod_rewrite is NOT enabled.
\n"; } /** * Verifies if the mod_rewrite module is enabled * * @return boolean True if the module is enabled. */ function is_mod_rewrite_enabled() { if ($_SERVER['HTTP_MOD_REWRITE'] == 'On') { return TRUE; } else { return FALSE; } } ?>

Now browse to http://yourservername.com/check_rewrite.php, and you can see whether mod_rewrite is enabled.

As general guide you can follow these simply steps to move your rules from Apache to nginx configuration file:

  • Replace the word "RewriteRule" in your Apache configuration files (or .htaccess) with "rewrite"
  • Replace the character "^" with "^/"
  • Replace the options [L] or [QSA,L] with "last;" (every line in nginx configuration files must end with ";")
  • If a rule contains braces – that is, { or } – you have to surround the regular expression with quotation marks.

Let's take a look at some examples. Bear in mind that in Apache directives can be written in a .htaccess file in your document root or in the virtual host file configuration. Usually they are located in /etc/apache2/sites-enabled (if you're running Debian or Ubuntu) or /etc/httpd/conf.d/ (under CentOS or Red Hat). In nginx, however, all the configurations regarding a virtual host, including the rewrite rules, are located in its server section, which is usually /etc/nginx/sites-enabled (Debian/Ubuntu) or /etc/nginx/conf.d/ (CentOS, Red Hat).

Rewrite rule to change a domain

Sometimes you want to rewrite a URL adding (or removing) "www." This might happen if you first published your website without www and later want to change the main URL, but you don't want to lose all the links that are coming from search engines and other websites. So, for example, you could rewrite all the URLs that arrive at linuxaria.com to www.linuxaria.com. In Apache mod_rewrite you would use something similar to these directives:

<Virtualhost>
Servername www.linuxaria.com
ServerAlias linuxaria.com
RewriteCond  %{HTTP_HOST}  linuxaria.com
RewriteRule  (.*)          http://www.linuxaria.com$1
...

The easiest way to achieve the same result with nginx is to create two server sections for your virtualhost. In the one for the domain that you want to redirect, include just a rewrite directive, and in the one for the real website, put all the directives you need for your website. So, for the first server, the one you want to redirect, use:

server {
    listen       80;
    server_name  linuxaria.com;
    return       301 http://www.linuxaria.com$request_uri;
}

And for the second server, the real website:

server {
    listen       80;
    server_name  www.linuxaria.com;
    ...
}

In this example we have not translated the rewrite rules, but rather changed our approach to solve the problem. We'll use the same principle in the next example.

WordPress permalinks

WordPress permalinks are permanent URLs that link to individual blog posts or categories and other lists of blog postings. Other people can use permalinks to link to your articles, or you might use one to send a link to someone in an email message. To produce "pretty" permalinks, WordPress uses mod_rewrite in Apache, and you should put the following standard rules in your .htaccess file if you use Apache (WordPress will not do this automatically):

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

You could translate these statements to "If the requested file is not a real file (!-f) or a directory (!-d), then use the page index.php."

A "literal" translation of these rules for nginx could be:

if (!-f $request_filename){
set $rule_1 1$rule_1;
}
if (!-d $request_filename){
set $rule_1 2$rule_1;
}
if ($rule_1 = "21"){
rewrite /. /index.php last;
}

But this is not an efficient solution with nginx. It's better to change the logic:

if (!-e $request_filename)
    {
        rewrite ^(.+)$ /index.php?q=$1 last;
    }

Here the logic says, "If the requested file doesn't exist (!-e) then use the page index.php." This change allow us to get the same result with fewer lines in the configuration file, because Apache mod_rewrite doesn't have this option, but nginx HttpRewriteModule does.

Modify a URL extension with nginx

Suppose you want to add by default a .html extension to all the URLs of your website, so http://linuxaria.com/myurl would become http://linuxaria.com/myurl.html. This could become necessary if you changed your blog platform, moving from WordPess to Jekyll or another static CMS. In Apache you can get the result with these rules:

RewriteCond %{REQUEST_URI} !^.*\.html$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.html [L,R=301]

The nginx approach is similar to the one that we saw above. First we verify that the URL doesn't already contains .html. Next we verify that the requested filename with the extension .html exists. If it does, we rewrite the URL, adding .html to the end:

location / {
        # break if URI has .html extension
        if ($request_filename ~* ^.+.html$) {
          break;
        }
        # add .html to URI and serve file, directory, or symlink if it exists
        if (-e $request_filename.html) {
          rewrite ^/(.*)$ /$1.html last;
          break;
        }
      }

Useful resources

To learn more about rewrite rules in nginx, read the Nginx HttpRewriteModule documentation page, which provides examples and conditions that you can use in your expressions.

You can also visit two websites that attempt to translate your existing rules for you, though they are not always 100 percent accurate. The htaccess to nginx converter was conceived as a mod_rewrite-to-nginx converter, but it also allows you to convert some other instructions that you might have reason to port from Apache to nginx. A second script to convert Apache htaccess to nginx is much more "literal" in its translation, but can be useful sometimes.

This is just a brief introduction to some common rewrite tasks that you might use on your site and that you'll probably need to consider when migrating from Apache to nginx. Rewrites are powerful, and can be complex, but learning how to use rewrites effectively can save your day, and add functionality to your website without the use of other software.




This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

Very useful. Thanks
Posted @ Sunday, March 31, 2013 11:16 PM by Adrian Hodson
This is a very nice article on Htaccess rewrite i like your article. 
Posted @ Monday, April 15, 2013 7:10 PM by html rgb
I will use a fewer lines in detection: 
 
Changes: 
 
function is_mod_rewrite_enabled() { 
if ($_SERVER['HTTP_MOD_REWRITE'] == 'On') { 
return TRUE; 
} else { 
return FALSE; 


 
To: 
 
function is_mod_rewrite_enabled() { 
return $_SERVER['HTTP_MOD_REWRITE'] == 'On'; 
}
Posted @ Wednesday, April 24, 2013 6:00 AM by shakaran
Hi, I tried to convert this but it did not seem to work: 
 
RewriteEngine On 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*) index.php?MVC=$1 [PT] 
 
<Files ~ "\.tpl$"> 
Order allow,deny 
Deny from all 
</Files> 
 
to: 
 
if (!-e $request_filename){ rewrite ^/(.*) /index.php?MVC=$1;  

 
location ~ \.tpl$ {  
deny all;  

 
I keep getting the error file does not exists, this is not for wordpress, do I need to add something else to make it work? 
 
Thank you for the time
Posted @ Tuesday, May 07, 2013 6:47 AM by laurens
The Apache mod_rewrite module provides powerful and sophisticated tools for nearly all types of URL rewriting. It is, however, somewhat complex, and may be intimidating to beginners. In fact, however, rewrite rules are not magical incantations, though to understand them you need some understanding of regular expressions.This change allow us to get the same result with fewer lines in the configuration file, because Apache mod_rewrite doesn't have this option, but nginx HttpRewriteModule does. 
 
nginx hosting
Posted @ Wednesday, June 26, 2013 3:00 AM by platform
Hi Riccardo! I just wanted to say that I’ve been reading your blog for some time now, and it find it quite inspirational. thanks for share. that save me tons of time.
Posted @ Thursday, August 29, 2013 5:17 AM by Livingsocial Clone
Nice information.keep going good.
Posted @ Thursday, October 31, 2013 2:28 AM by David warner
I want to convert apache rewrite to nginx ,and i can't do it work .this is my rewrite ,can anybody help me ? 
 
RewriteEngine on 
 
# Remove www from URI 
RewriteCond %{HTTP_HOST} www.domain.com$ [NC] 
RewriteRule ^(.*)$ http://domain.com/2014/$1 [R=301,L] 
 
RewriteCond %{REQUEST_URI} /usuario/ [OR] 
RewriteCond %{REQUEST_URI} /noticia/ [OR] 
RewriteCond %{REQUEST_URI} /video/ 
 
RewriteRule ^(.*) rewrite.php?path=$1 [L,QSA] 
Posted @ Thursday, January 09, 2014 9:35 AM by Marcos Paoletti
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics