Archive for the ‘ nginx ’ Category

Possible bug or config problem

In my previous post, I ran through a short tutorial on using nginx as a front-end web proxy for your Catalyst application running on a Starman / PSGI webserver. I just uncovered a problem, and I can’t tell if it’s a configuration problem on my end, or an actual bug…

If I have a GET request, like so : ‘/widgets//view’ or a POST request ‘widgets//update’ for a new `widget`, my double forward slash is being omitted and instead, Catalyst is instead handling my request as ‘/widgets/view’ or ‘widgets/update’ and the response is a 404 page not found error. (Note, for an already existing widget, the double forward slash would be replaced with a primary key identifier of the current `Widget` : /widgets/1542151/view’, etc).

Running Apache + FastCGI, the default catalyst HTTP server, or Starman (via localhost:5000 requests) do not yield this error. Which leads me to believe this problem is stemming from my nginx web proxy. Probably some sort of configuration problem on my part.

To test, I will start an instance of the catalyst web server in place of the starman server (should be an easy change, start the catalyst server and change the port number in my web proxy to 3000 instead of 5000)…

UPDATE :

HERE

Basically, change the proxy_pass from http://localhost:5000/ to http://localhost:5000

HOWTO : nginx, Starman / Plack and Catalyst

In this short tutorial, I will demonstrate how to use nginx as a frontend web proxy and Starman as a backend web server running a Catalyst application.

It assumes you already know about PSGI, Catalyst, nginx and how to install all the required libraries and perl modules.

Requirements :

First, we’ll configure nginx to run as our lightweight http server.  (If you require SSL, please make sure your ./configure command includes the –with-http_ssl_module option and that you have the openssl and pcre libraries already installed)

I’m going to require a ssl connection with a self signed certificate (you can follow the instructions here on how to set that up). I will also be redirecting all http requests to https via the web server (which is the best way to handle this).

In your nginx directory (mine was installed at /usr/local/nginx) edit your conf/nginx.conf file :

... (params)
http {
... (params, default server, etc)
  server {
    listen 80;
    server_name   myapp.example.com;
    location / {
      rewrite         ^/(.*)$ https://myapp.example.com/$1 permanent;
    }
  }

  server {
    listen        443 ssl;
    server_name   myapp.example.com;
    gzip on;
    ssl_certificate /usr/local/nginx/conf/server.crt;
    ssl_certificate_key /usr/local/nginx/conf/server.key;
    #you may need or want to set additional ssl parameters (cipher, etc)

    location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Port 443; #this is important for Catalyst Apps!
      proxy_pass http://localhost:5000; #changed from http://localhost:5000/ which was causing double forward slash problems in the url
    }

  location /static {
    root /data/users/MyApp/root;
    expires 30d;
  }
}

This assumes that your static content will be servered by nginx and not your Catalyst App, and that when you start your starman server, you’ll be using port 5000.

To get your Catalyst up and running using Starman, install the Plack and Starman via cpanminus as well as the Catalyst::Engine::PSGI module for PSGI integration. Once all of your modules are installed, you’ll need to create a app.psgi file.  You can do so manually, or via the script/app_create.pl command in your Catalyst App directory.

As I found out here from my own answer, when using a front-end web proxy, you’ll need to add a small bit of information to your .psgi file (Catalyst::Engine::PSGI docs), here’s an example of mine :

#!/usr/bin/env perl
use strict;
use warnings;

use Plack::Builder;
use MyApp;

MyApp->setup_engine('PSGI');
my $app = sub { MyApp->run(@_) };

builder {
 enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' } 
        "Plack::Middleware::ReverseProxy";
 $app;
};

If your instance of nginx is running on a different server, you may need to set this configuration variable in your Catalyst App (doesn’t hurt to add it regardless of your situation) :

MyApp->config(using_frontend_proxy => 1)

Start starman (currently defaults to 5 processes and port 5000) :
$ starman script/erp.psgi

Start nginx
$ sudo /usr/local/nginx/sbin/nginx

At this point, all of your http://myapp.example.com requests should be automatically redirected to https://myapp.examples.com. Nginx should be handling all of your static content used by your Catalyst app, and as long as Starman is running in the background on port 5000, your requests and responses should be handled accordingly and in a timely manner! 😉

In a production production environment, you may want to tweak some of your settings in the nginx.conf file and then create a startup script for both nginx and your Starman server. I also haven’t touched on any of the logs associated with Starman / Plack and your Catalyst app, or how to handle the ip addresses (nginx if forwarding the $remote_addr as `X-Real-IP` in the header) for access / error logs…