Home > Around Rails (with Rubies below) > nginx + Rails (through Passenger) on different Rubies + PHP, all this on Amazon AWS

nginx + Rails (through Passenger) on different Rubies + PHP, all this on Amazon AWS

Hi everybody!

It’s been quite a long time since my last post… I have lots to do, I’m working on a startup project and I’ve now another blog on which I have to write. I do not spend so much time developing, and almost not any more for Cocoa…

Due to my project I’ve been switching to web application technologies, and since I’m looking in the startup ecosystem, I’ve been looking at Ruby On Rails. After having played a little with Heroku, I wanted to start with a more customized hosting experience, so I’m now testing Amazon AWS service, through their free 1-year tier (allowing a sufficient cloud hosting for my purpose).

However, since I found the road quite long to reach a working config (I’m really newbie as sysadmin), I put all the things I went through on an Evernote page, and now I’m sharing them with you. It’s raw, I’ll try to refine all this with the time, but it may help nonetheless. And feel free to ask for help, I’ll do what I can ūüėČ


First of all, setup the user and group to use with the server and other processes (that will be Passenger, PHP FastCGI…) :

groupadd www
useradd -d /var/www -s /bin/bash -g www www

The following version may be more secure, or maybe not, maybe it’s generally useless to have home directory and shell, but we will need to be able to su as the www user later in our Passenger Standalone init script, so we’d better choose the previous useradd proposition… The following one is only kept for reference.

useradd -d /dev/null -s /etc -g www www

This is now what we’ll be installing:

  • Nginx, with common options, SSL capability, PHP support and Passenger for Rails.
  • Passenger Standalone to serve Rails app with esoteric configurations (not the main one to be used by Passenger integrated with nginx).
  • Ruby Enterprise Edition

Install nginx with both PHP and Passenger support involves going through Passenger installation process, which compiles and setup nginx by itself, but providing it with the necessary options, in our case:

  • the common options we want to have,
  • PHP support through fast-cgi thanks to fgm.

The rest is already handled by the install (as SSL and the pcre library).

    • Download nginx source code.
    • Follow Passenger installation as described on http://www.modrails.com/install.html (easy way), and when the installer prompts you to, answers you want to customize your Nginx installation. You will customize this way:
      • provide the location of the nginx source code you downloaded and extracted,
      • specify an installation path for nginx, I chose /usr/local/nginx (nginx default’s, but not Passenger’s),
      • add options to nginx configuration:

--user=www --group=www --with-http_sub_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_realip_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/nginx/tmp/client_body_temp --http-proxy-temp-path=/var/nginx/tmp/proxy_temp --http-fastcgi-temp-path=/var/nginx/tmp/fastcgi_temp --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/nginx/log/error.log --http-log-path=/var/nginx/log/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock

      • These options are the remaining ones proposed by the tutorial you can find here, which is well done : (for French speaking persons however)! ). It mainly provides path for nginx work files and add the fastcgi support to integrate with PHP through FPM.
  • After that, create the nginx config file as indicated in the tutorial and add the lines indicated by the Passenger at the end of the installation. The config file will be waiting in /etc/nginx/nginx.conf

Now nginx should be installed. You should make a link to the binary in /usr/sbin for example (to allow the system to find it). Give it a try with : sudo nginx, and try in your browser your server’s public IP, you should see a message about Nginx… If this works, add nginx to the init.dto have it started when your server launches. For this:

  • create a nginx script in /etc/init.d (for example with emacs), and copy the content provided on this page :
  • be sure to change the provided script to match the location where you installed nginx
  • you’ll need the functions file for init.d, you can use the sample one on this page
  • now you should be able to start nginx through /etc/init.d/nginx start (be sure to set your permissions correctly to be able to execute the script)

Get PHP with nginx (haaaaaard to find…)

Found the solution in here

  • install spawn-fcgi: yum install spawn-fcgi
  • Create the init script according to the previous tutorial (just edit it to change from php5-cgi to php-cgi, because it is installed this way on the AWS AMI distrib package).
  • Start your fast-cgi service (/etc/init.d/php-fcgi start) and configure it to be started with the server:
  • chkconfig --add php-fcgi
  • chkconfig php-fcgi on
  • Update nginx configuration file. Use this (based on my config, the only combination I found to work – used to had a “No input file specified error…”).

server {

   server_name http://www.example.com;
root /var/www/example.com;location / {
index index.php     index.html index.htm;
}
   location ~ \.php$ {
      fastcgi_pass  localhost:9000;
fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME /var/www/work.jili.fr$fastcgi_script_name;
include /etc/nginx/fastcgi_params;

   }
}

There are things to do in the /etc/nginx/fastcgi_params file too… So be sure it contains the following…

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with –enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

* Be sure to check your permissions. I used www as user and group for everything, so all my served stuff is under this user:group, and I start my nginx server and the spawn-fcgi with it too…
* You’ll like to have a SysV init script to start your Spawn FCGI for PHP at server launch. You can use this one. Be sure to change the user:group with whatever you’re using.
#!/bin/sh#
# php-fcgi   Start and stop FastCGI processes
#
# chkconfig:   Р80 20
# description: Spawn FastCGI scripts to be used by web servers

### BEGIN INIT INFO
# Provides:       php-fcgi
# Required-Start: $remote_fs $syslog
# Required-Stop:  $remote_fs $syslog
# Default-Start:  2 3 4 5
# Default-Stop:   0 1 6
# Short-Description: PHP5 FastCgi Spawned processes
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

COMMAND=/usr/bin/spawn-fcgi
ADDRESS=127.0.0.1
PORT=9000
USER=www
GROUP=www
PHPCGI=/usr/bin/php-cgi
PIDFILE=/var/run/fastcgi-php.pid
RETVAL=0

PHP_FCGI_MAX_REQUESTS=500
PHP_FCGI_CHILDREN=2

start() {
echo -n $”Starting $PHPCGI: ”
export PHP_FCGI_MAX_REQUESTS PHP_FCGI_CHILDREN
$COMMAND -a $ADDRESS -p $PORT -u $USER -g $GROUP -f $PHPCGI -P $PIDFILE
retval=$?
echo
return $retval
}

stop() {
echo -n $”Stopping $PHPCGI: ”
/usr/bin/killall -9 php-cgi
retval=$?
echo
return $retval
}

case “$1” in
start)
start
RETVAL=$?
;;
stop)
stop
RETVAL=$?
;;
restart|reload)
stop
start
RETVAL=$?
;;
*)
echo “Usage: fastcgi {start|stop|restart}”
exit 1
;;
esac
exit $RETVAL

Installing Passenger Standalone instances for dedicated-environment apps

You may want to run an app which requires a specific environment, maybe older than the one you’re using everyday (e.g. Redmine which runs on Rails 2). Or you want to dedicate a production environment for your app. For this need, you can use Passenger Standalone and configure it to be served by nginx.

Finally, you’ll like to have you Passenger Standalone instances started with the server too. BEWARE NGINX WILL NOT START IF LAUNCHED AFTER PASSENGER SA

I could do with this script, but you can probably use another one… Be sure however to add the
# chkconfig – 86 14
line (you may change the numbers to match your configuration), to make sure redmine starts after nginx…


#!/bin/bash                                                                     #
# chkconfig: - 86 14
### BEGIN INIT INFO
# Provides:          myapp passenger in standalone
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# X-Interactive:     true
# Short-Description: Start/stop de-fra.com web site
### END INIT INFO

#PATH=/sbin:/usr/sbin:/bin:/usr/bin
#GEM_HOME=/usr/local/rvm/gems/ruby-1.8.7-p302
RVM=rvm
PASSENGER=passenger
ADDRESS=127.0.0.1
PORT=3000
ENVIRONMENT=production
APP=”/var/www/railsapps/redmine”
USER=www
RVM_GEMSET=ree@rails2passengerSA
USER=www
SET_PATH=”cd $APP; $RVM use $RVM_GEMSET;”
CMD=”$SET_PATH $PASSENGER start -a $ADDRESS -p $PORT -e $ENVIRONMENT -d”
CMD_STOP=”$SET_PATH $PASSENGER stop -p $PORT”

#. /lib/lsb/init-functions

case “$1” in
start)
echo “Starting myapp passenger”
echo $CMD
su – $USER -c “$CMD”
;;
stop)
echo “Stopping myapp passenger”

cd $APP
su – $USER -c “$CMD_STOP”
;;
*)
echo “Usage: $0 start|stop” >&2
exit 3
;;
esac

Using unicorn reverse-proxied through Nginx

Good tutorial on: http://blog.sietch-tabr.com/index.php/post/2010/04/03/Faire-tourner-des-applications-ruby-on-rails-avec-nginx-et-unicorn (French)

The following part is kept for reference, but not necessary if you follow the previous guidelines…
Installing Nginx (NOT NECESSARY IF YOU’RE INSTALLING PASSENGER, IT WILL DO IT BY ITSELF)
Commands will need a sudo before, or just log in a bash as root with sudo bash

* Doing it from source
* need to install GCC, make first : sudo yum install gcc make
* get the pcre library source : http://sourceforge.net/projects/pcre/files/pcre/
* get nginx source (naturally): http://wiki.nginx.org/Install#Source_Releases
* in nginx folder:
* ./configure –user=www –group=www –with-http_sub_module –with-http_flv_module –with-http_gzip_static_module –with-http_stub_status_module –with-http_realip_module –http-log-path=/var/log/nginx/access.log –http-client-body-temp-path=/var/nginx/tmp/client_body_temp –http-proxy-temp-path=/var/nginx/tmp/proxy_temp –http-fastcgi-temp-path=/var/nginx/tmp/fastcgi_temp –conf-path=/etc/nginx/nginx.conf –error-log-path=/var/nginx/log/error.log –http-log-path=/var/nginx/log/access.log –pid-path=/var/run/nginx.pid –lock-path=/var/run/nginx.lock –with-pcre=/home/ec2-user/pcre-8.12/ –with-http_ssl_module
* be sure to adjust the path to your pcre lib source
* make
* make install
* Now nginx should be installed. You should make a link to the binary in /usr/sbin for example (to allow the system to find it).
* Give it a try with : sudo nginx, and try in your browser your server’s public IP, you should see a message about Nginx…
* If this works, add nginx to the init.d to have it started when your server launches. For this:
* create a nginx script in /etc/init.d (for example with emacs), and copy the content provided on this page : http://articles.slicehost.com/2009/2/2/centos-adding-an-nginx-init-script
* be sure to change the provided script to match the location where you installed nginx
* you’ll need the functions file for init.d, you can use the sample one on this page: http://bash.cyberciti.biz/guide//etc/init.d
* now you should be able to start nginx through /etc/init.d/nginx start (be sure to set your permissions correctly to be able to execute the script)
* Important thing, we should now setup user/group and permission correctly for more security. Nginx can run with any user, but we’ll dedicate one to web services. We’ll name it www.
Installing Phusion Passenger for Nginx

* Log in bash as root with sudo bash to make life easier.
* Install rvm.
* You can use the quick install: https://rvm.beginrescueend.com/.
* Try to verify the type rvm | head -1 thing works as expected (it does for me, but I dont really know how…). Check on¬† https://rvm.beginrescueend.com/rvm/basics if needed.
* You’ll need RVM to have a nice install of Ruby, since the one installed with the Amazon AWS image does not make gem install Passenger works (seems to lacks some Ruby files…).
* Some dependencies to install REE :
* yum install gcc-c++ patch redline-devel
* You should have a look to RVM doc to know what you can do: different rubies, gemsets… Maybe create a gemset to host ree with passenger, it will enable you to keep your gems to the strict necessary while trying other configurations later.
* Now install REE. Thanks to rvm, it should be as simple as rvm install ree (can look at https://rvm.beginrescueend.com/interpreters/ree/)
* Once this is done, install passenger. Follow instructions http://www.modrails.com/install.html. It is well explained and the installer is really well done: self configuring, it did all by itself for me (even what I had already done ūüė¶
* If you followed the installer instructions to the end (and add necessary lines to your nginx config file), you should be able to deploy your ruby apps now.
Bonus: Nginx to serve PHP too (useful to manage your MySQL DB with phpMyAdmin)

* http://download.pureftpd.org/docs/configuration_nginx_php.pdf (from this forum http://forum.ovh.com/showthread.php?t=39114)

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: