Sep 132013
 

This is an article of mine first published on Wazi.

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.



How to verify if you are using mod_rewrite in Apache with PHP

If you dont know if you your website is using mod_rewrite or not, and you want to do a further check you can use this approach:

1) In your document root,the directory where you have all your html files, add (or modify if it already exists) a file with name .htaccess that must contains these lines:

    // Tell PHP that the mod_rewrite module is ENABLED.
    SetEnv HTTP_MOD_REWRITE On

2) In your document root add a second file, with name check_rewrite.php with the following content:

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 open your browser at the url http://yourservername.com/check_rewrite.php, you should see if mod_rewrite is enabled or not.

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

  • Replace the word “RewriteRule” from Apache configuration (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. Please note that in Apache the directives could be wrote in a .htaccess file in your document root or in the virtual host file configuration. usually they are located in /etc/apache2/sites-enabled (Debian/Ubuntu) or /etc/httpd/conf.d/ (Centos, RedHat)
In Nginx the rewrite are located in the server section of your virtualhost, usually they are located in /etc/nginx/sites-enabled (Debian/Ubuntu) or /etc/nginx/conf.d/ (Centos, RedHat).

Rewrite rule to change a domain

Sometimes you want to rewrite a URL adding (or removing) “www.”, this happen sometime when you have first published your website without www and after sometimes you want to change the main url, but you don’t want to lose all the link that are coming from search engines and other websites. For example, you could rewrite all the URLs that arrive at linuxaria.com to www.linuxaria.com. In Apache mod_rewrite you would have 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 be necessary if you change blog platform and you want to move from Wordpess to Jekill or other “static CMS” product.
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.


Popular Posts:

flattr this!

  One Response to “How to convert Apache rewrites for nginx”

  1. Nginx rewrite rule for WordPress permalinks


    location / {
    try_files $uri $uri/ /index.php?$args;
    }

 Leave a Reply

(required)

(required)


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>