Moving my Catalyst Apps from Apache/FCGI to Nginx/Starman
Recently I had to move all my projects to a new server and decided to give Nginx and Starman a chance.
The Nginx config is rather simple.
my Catalyst Application is located at /var/www/MyApp
server {
listen 80;
server_name myapp.at *.myapp.at;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://unix:/var/www/MyApp/myapp.socket:/;
}
location /static {
root /var/www/MyApp/root;
expires 30d;
}
}
Nginx expects the Catalyst Application to listen on the socket /var/www/MyApp/myapp.socket.
Here is my initd script that takes care of starting and stopping the starman processes. (/var/www/MyApp/myapp.starman.initd)
#!/usr/bin/env perl
use warnings;
use strict;
use Daemon::Control;
my $app_home = '/var/www/MyApp';
my $program = '/var/www/perl5/perlbrew/perls/perl-5.16.2/bin/starman';
my $name = 'MyApp';
my $workers = 1;
my $pid_file = $app_home . '/myapp.pid';
my $socket = $app_home . '/myapp.socket';
Daemon::Control->new({
name => $name,
lsb_start => '$nginx',
lsb_stop => '$nginx',
lsb_sdesc => $name,
lsb_desc => $name,
path => $app_home . '/myapp.starman.initd',
user => 'www-data',
group => 'www-data',
directory => $app_home,
program => "$program -Ilib myapp.psgi --workers $workers --listen $socket",
pid_file => $pid_file,
stderr_file => $app_home . '/myapp.out',
stdout_file => $app_home . '/myapp.out',
fork => 2,
})->run;
Check out Daemon::Control, it's a really helpful CPAN module that eases the creation of init scripts. Let's create the initd script.
./myapp.starman.initd get_init_file > /etc/init.d/cat-myapp
You want the starman processes to survive a reboot, so let's install to runlevels
update-rc.d cat-myapp defaults
Now reload Nginx and start your starman processes and you should be good to go.
I just started using this kind of config, so any problems wouldn't surprise me too much.
Great to read that more people are deciding towards the nginx/Starman combo. Recently we started moving the first Catalyst applications to new virtual machines and also used nginx and Starman.
We added a couple of things for optimization and convenience:
* CSS and JS are each combined into a single file at deployment time. These files are delivered statically by nginx
* Thumbnails based on uploaded files are cached when first requested and delivered by nginx if available
* Static resources like images are also directly delivered by nginx
* We added a maintenance mode presenting a maintenance page to most users and allows to test the backend for assorted people. We found nginx's geo module being a great way to do this.
In order to avoid to install perl modules globally, we decided to use the usual (but ugly) case-statement-driven /etc/init.d script as a shell script instead of perl. But Daemon::Control results in a much shorter and more maintainable script. I think about borrowing your idea :-)
I run debian wheezy and usually have a perlbrew perl for each user. (user 'www-data' for production, user 'david' for development)
The perls are "managed" with git. This allows for easy undo if an update introduces problems.
I do not want to install any perl modules for my root account either (needed for a initd script that uses Daemon::Control as you pointed out) but since Daemon::Control is available as a debian package (aptitude install libdaemon-control-perl) I am happy with this solution for now.
Any benchmarks? Difference in memory usage?
A followup on the stability of this setup would be nice...
I'm also trying to ditch Apache in some cases.
Nope.
Benchmark and other comparison metrics sure would be nice to have. Perhaps if I find some time in 2013 I will put something together. But there might be some data available in the internets.
http://www.wikivs.com/wiki/Apache_vs_nginx
https://timmehosting.de/blog/benchmark-nginx-12-vs-apache-24-statische-dateien-drupal-typo3
And this just elaborates a bit on a similiar case. http://www.matt-peters.com/blog/?p=35
I use this:
https://github.com/int80/puppet-psgi/blob/master/templates/psgi_initscript.erb
Hi Wolfgang,
I'd love to see a copy of your nginx config, can you post it on github or similar?
specifically how to serve css, js, etc via nginx and not hit starman
thanks
There is something missing in my nginx config which results in the following error msg.
Use of uninitialized value in string eq at /var/www/perl5/perlbrew/perls/perl-5.16.2/lib/site_perl/5.16.2/Catalyst.pm line 2787.
probably some config that passes the originating IP to the starman worker.
more info tomorrow.
UPDATE: https://blogs.perl.org/users/davewood/2013/01/nginx-fastcgi-vs-starman-erratum.html