How to configure nginx to run Kohana on Ubuntu

As a web developer I’ve been using Apache for a long long time. Recently though, I’ve started to move away from Apache in favor of nginx (pronounced “engine-X”). It’s not that I really need its power, it’s just that I wanted to learn something new to break my box.

It’s fairly simple to set up and get nginx running with FastCGI and MySQL on Ubuntu - a very well-written tutorial can be read on HowtoForge, which should take you less than 15 minutes for everything. In this article therefore I will only write about how to configure nginx to actually run a Kohana-powered site, with virtual host and rewriting and such. If you’re not familiar with Kohana, take a look at my article here.

The prerequisites

  • I have my Kohana-power site located under /home/phoenixheart/www/my-kohana/ directory with proper permission set (owner being www-data, that is).
  • nginx has been set up properly and listening on port 80, with the configuration directory being /etc/nginx/
  • I want my site to be locally accessible via my-kohana.dev. Any requests to www.my-kohana.dev should be permanently redirected to my-kohana.dev - which is also called “force non-www”.
  • I want to have neat URL rewriting without “index.php”, for example index.php?controller=product&function=get&id=1 should be rewritten into /product/get/1
  • I also want that all existing files and directories under the root directory are accessible, except Kohana’s system directories system, application, and modules. Any attempt to access system files and directories(beginning with dots, like .htaccess or .settings) should be disallowed also.

All clear. So let’s do it!

Set up the virtual host

The way nginx handles virtual hosts is totally different from Apache, as we can expect. Instead of using .conf files to declare and configure the hosts, nginx, when started, additionally scans through the configuration folder (/etc/nginx in our case) to find (if any) configuration files under 2 directories: sites-available and sites-enabled. So under /etc/nginx/sites-available, create a file called my-kohana.dev with the following content:

server {
    listen   80;
    server_name my-kohana.dev;
    access_log /home/phoenixheart/www/log/my-kohana/access.log; # remember to create this file
    error_log /home/phoenixheart/www/log/my-kohana/error.log; # and this file
    location / {
	root   /home/phoenixheart/www/my-kohana;
	index  index.php;
    }
    location ~ \.php$ {
	fastcgi_pass   127.0.0.1:9000;
	fastcgi_index  index.php;
	fastcgi_param  SCRIPT_FILENAME  /home/phoenixheart/www/my-kohana$fastcgi_script_name;
	include        fastcgi_params;
    }
}

Of course, this is just the basis configuration for the site to get up and running. To continue, we must create a host entry. Open /etc/hosts and add this line:

127.0.0.1	my-kohana.dev www.my-kohana.dev

If this was Apache, we would be good enough to restart the webserver to see the result. But like I said, nginx is different. For nginx to properly recognize and serve our site, we must enable the site by creating a symlink of the configuration file under sites-enabled. We do that as follow:

<code>ln -s /etc/nginx/sites-available/my-kohana.dev /etc/nginx/sites-enabled/my-kohana.dev</code>

Now, let’s restart nginx. Open Terminal and type:

<code>sudo /etc/init.d/nginx restart</code>

The result should be as followed:

<code>Restarting nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
configuration file /etc/nginx/nginx.conf test is successful
nginx.</code>

If you receive any “failure” response, chance is some typos in the configuration.

Now, http://my-kohana.dev should be accessible via the browser (Note that, if Kohana complains about the logs folder inaccessible, try properly setting its owner to www-data). Next step is tweaking the configuration a bit to serve our needs.

Tweak it up

Force non-www

To force non-www, open sites-available/my-kohana.dev and add these lines at the top:

server {
    listen 80;
    server_name www.my-kohana.dev;
    rewrite  ^/(.*)$  http://my-kohana.dev/$1  permanent;
}

This kind of configuration is very similar to that of Apache, so I would assume there’s no need to explain. After a nginx restart, all request to http://www.my-kohana.dev should be silently redirected to http://my-kohana.dev.

Neat URL rewriting

Again, in sites-available/my-kohana.dev, modify the first location block to the following

location / {
    root   /home/phoenixheart/www/my-kohana;
    index  index.php;
    # this is where the rewriting gets done.
    # refer to http://forum.kohanaphp.com/comments.php?DiscussionID=1505 for more info
    rewrite ^(.+)$ /index.php?kohana_uri=$1 last;
}

But wait! We don’t want EVERY requests to be re-written. For example, a request to my-kohana.dev/css/style.css should be kept as-is. Same goes with javascripts and images. In short, if the request is for an existing file or folder, we keep it as-is; else, we route it to index.php using rewriting. To achieve that, modify the configuration above to this:

location / {
    root   /home/phoenixheart/www/my-kohana;
    index  index.php;
    if (-f $request_filename) {
        # translated into "if the request is an existing file, break (do nothing)"
        break;
    }
    if (-d $request_filename) {
        # translated into "if the request is an existing directory, break (do nothing)"
        break;
    }
    # the request is not an existing file or directory
    # this is where the rewriting gets done.
    # refer to http://forum.kohanaphp.com/comments.php?DiscussionID=1505 for more info
    rewrite ^(.+)$ /index.php?kohana_uri=$1 last;
}

Set files and folder accessibilities

Now, we prohibit access to the sensitive stuffs, including kohana system folders, dot files and directories etc. It’s fairly simple with nginx. All we need to do is adding two more location blocks, specific for this purpose:

location ~ /\. {
    return 404;
    # or, if you prefer
    #return 403;
    # or even
    #deny all;
}
location ~* ^/(modules|application|system) {
    return 404;
    # or, if you prefer
    #return 403;
    # or even
    #deny all;
}

The final configuration file should look like this:

server {
    listen 80;
    server_name www.my-kohana.dev;
    rewrite  ^/(.*)$  http://my-kohana.dev/$1  permanent;
}
server {
    listen   80;
    server_name my-kohana.dev;
    access_log /home/phoenixheart/www/log/my-kohana.dev.access.log;
    error_log /home/phoenixheart/www/log/my-kohana.dev.error.log;
    location ~ /\. {
        return 404;
    }
    location / {
        root   /home/phoenixheart/www/my-kohana;
        index  index.php;
        if (-f $request_filename) {
            # translated into "if the request is an existing file, break (do nothing)"
            break;
        }
        if (-d $request_filename) {
            # translated into "if the request is an existing directory, break (do nothing)"
            break;
        }
        # the request is not an existing file or directory
        # this is where the rewriting gets done.
        # refer to http://forum.kohanaphp.com/comments.php?DiscussionID=1505 for more info
        rewrite ^(.+)$ /index.php?kohana_uri=$1 last;
    }
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /home/phoenixheart/www/my-kohana$fastcgi_script_name;
        include        fastcgi_params;
    }
    location ~* ^/(modules|application|system) {
        return 403;
    }
}

After another nginx restart, our Kohana instance should run without any hassles.

Typos? Mistakes? Errors? Let’s hear it in your comment.

  • Wow, this post was awesome, and a huge help in getting my own nginx/kohana setup working. Thanks a lot!

  • I have just got a blog and use about 50 different plugins. Thank you very much for your plugin. It complete my website

  • I think there might be a small but important typo:
     

    rewrite ^(.+)$ /index.php?kohana_uri=$1 last;

     
    Should probably be:
     

    rewrite ^/(.+)$ /index.php?kohana_uri=$1 last;

     
    Notice the slash. I think that without this, kohana was co-opting all the requests, and nginx wasn’t serving up static files! Please correct me if I’m wrong, as this is still very new to me.

  • Hi Drew, right now I’m on a Windows box so can’t check this. I remember that I copied the code from the working configuration, but anyway if it works for you in this way or another way, it’s fine :)

  • Thanks a lot man, this is exactly what I needed!

  • Your configuration for Kohana didn’t work at all for me. Plus Igor Sysoev, the nginx creator, doesn’t recommend this method. I wrote a VirtualHost configuration from scratch that works pretty well: http://vidax.net/blog/en/2010/06/kohana-with-nginx-virtualhost-configuration/
    The static.xxx.com server is not required for normal users, I posted it as an example.
    Thks
     

  • Axel, in what way does that config not work for you?
    I attempted your solution, which only resulted in frustration, and ended up resorting to a working solution very similar to the above configuration.
    If Igor is so against solutions as outlined above, why is that? Can you link us to his post? What is his recommended solution? Can you post *his* solution to what the above config achieves, in a working fashion?

  • Works great - Thanks!
    -Scott
    http://www.dnshat.com

  • Hi intel352, sorry for my late reply, I didn’t see your comment. Actually, your configuration doesn’t work when I try to access “.php” files. For instance, if I call:
    http://my-kohana.dev/contact
    that works well. However, if I call:
    http://my-kohana.dev/contact.php
    I get a “No input file specified.” error.
    Concerning Igor, he doesn’t recommend the use of “-f” and “-d”, that’s what he told me by email when I posted my configuration on the mailing list. The “try_files” functions does the same and seems cleaner.
    Why did my solution resulted to frustration? Wasn’t it working for you? Did you notice I use a “public” directory unlike you?
    Thks
     
    Axel

  • Hi Axel,

    Regarding the “No input file specified” error I would assume there’s something wrong with the fastcgi pass at line 16. Nevertheless, a url ending with .php is rarely seen if we use a framework like Kohana.
    About the -f and -d, you’re right, I was just starting to use nginx then and had very little experience. try_files is much cleaner.

    An

  • It’s very possible that the discrepancies I and other users have seen, are due to versions of Nginx used, as Debian tends to distribute a more recent release (or there are more recent PPAs at least, I believe), whereas Redhat distros are running an ancient version.

  • This is a test.

  • Hi,
    So if I just do plain nginx+php-fpm setup without this kind of configuration, my kohana won’t work? I recently built kohana, nginx and phpfpm. I’m getting tons of errors.
    I noticed that on your configuration above, you used rewrite rules. I don’t have any. Is it required?
    Thanks a lot! I will try this sometime.
    Neil

You can follow any responses to this entry through the RSS 2.0 feed.