Sunday, January 27, 2008

Serving PHP5 with Nginx on Ubuntu 7.10 (Gutsy)

There are lots of tutorials out there to setup PHP with Nginx. I'm probably just retarded, but none of them got me to a working system. A detail left out of one, a configuration file left out of another, etc.

What follows is exactly what I did to get Nginx to serve PHP5 on a fresh Slicehost VPS slice running Ubuntu 7.10. Hopefully it will help someone else.

NOTE: The following commands assume that you have already setup a user account with sudo privileges and are executing the commands as that user, NOT as root.

Update your system and install basic tools required

> sudo aptitude update -y
> sudo locale-gen en_GB.UTF-8
> sudo /usr/sbin/update-locale LANG=en_GB.UTF-8
> sudo aptitude safe-upgrade -y
> sudo aptitude full-upgrade -y
> sudo aptitude install build-essential -y
Install MySQL
> sudo aptitude install mysql-server mysql-client libmysqlclient15-dev -y
Install PHP5
> sudo aptitude install php5-cli php5-cgi php5-mysql php5-xcache -y
Note: Xcache is installed at this point and available for you to setup, but by default is not turned on.

Install Nginx
> sudo aptitude install nginx -y
Go to your IP address and you should now recieve the message "Welcome to nginx!"

FastCGI Parameter Configuration

We will place all of our fastcgi parameters in a single file which we can include in as necessary.
> sudo vim /etc/nginx/fastcgi_params
This will be a new empty file, add the following and save:
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;

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;
Nginx Configuration
> sudo vim /etc/nginx/sites-available/default
This is a pre-existing file. Find the part that looks similar to the following and edit it as so and save:
location ~ \.php$ {
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;
  include /etc/nginx/fastcgi_params;
}
We need to remember to restart Nginx so that it picks up our configuration changes.
> sudo /etc/init.d/nginx stop
> sudo /etc/init.d/nginx start
Spawn-fcgi

We still need a script to start our fast cgi processes. We will extract one from Lighttpd.
> mkdir ~/sources
> cd ~/sources
> wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.bz2
> tar -xvjf lighttpd-1.4.18.tar.bz2 
> cd lighttpd-1.4.18
> ./configure
> make
> sudo cp src/spawn-fcgi /usr/bin/spawn-fcgi
Let's get automated!
> sudo touch /usr/bin/php-fastcgi
> sudo vim /usr/bin/php-fastcgi
This is a new empty file, add the following and save:
#!/bin/sh
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -f /usr/bin/php5-cgi
Next...
> sudo touch /etc/init.d/init-fastcgi
> sudo vim /etc/init.d/init-fastcgi
This is also a new empty file, add the following and save:
#!/bin/bash
PHP_SCRIPT=/usr/bin/php-fastcgi
RETVAL=0
case "$1" in
start)
$PHP_SCRIPT
RETVAL=$?
;;
stop)
killall -9 php
RETVAL=$?
;;
restart)
killall -9 php
$PHP_SCRIPT
RETVAL=$?
;;
*)
echo "Usage: php-fastcgi {start|stop|restart}"
exit 1
;;
esac
exit $RETVAL
We need to change some permissions to make this all work.
> sudo chmod 755 /usr/bin/php-fastcgi
> sudo chmod 755 /etc/init.d/init-fastcgi
Create a Test File
> sudo vim /var/www/nginx-default/index.php
Let's just print out the information page for our PHP installation.
<?php echo phpinfo(); ?>
Start It Up
> /etc/init.d/init-fastcgi start
Now go to your IP address/index.php and you should see the PHP info page displayed.  

Set To Startup Automatically Upon Reboot
> sudo update-rc.d init-fastcgi defaults
You might want to test and make sure that it actually starts up upon reboot...
> sudo reboot
Final Words
If you think I have done anything stupid in the way this is setup, you may very well be right! Please leave a comment with a suggestion on how to improve the setup.

You probably will want to look into configuring Nginx for VirtualHosts, which is not considered in this post.

Credits
Much of this information was taken from the excellent post: How To Install A Complete LEMP (Linux - EnginxX (Nginx HTTP SERVER) - Mysql - PHP) Server (Not LAMP...) On Ubuntu/Debian, which got me about 90% there.

21 comments:

  1. Need to add a "make" command between:

    > ./configure
    > sudo cp src/spawn-fcgi /usr/bin/spawn-fcgi

    should read:

    > ./configure
    > make
    > sudo cp src/spawn-fcgi /usr/bin/spawn-fcgi

    ReplyDelete
  2. Good howto, thanks a lot. I couldn't get it to work at the last step, i.e. when spawn-fcgi is started error says a switch is missing? It hanged there. I ended up reinstalling 7.10.

    Also what's that '-y' switch for when installing mysql and php. I didn't use that when installing my LAMP.

    ReplyDelete
  3. I tryed your tutorial twice. I keep getting "No Input File Specified" error. Any ideas?

    ReplyDelete
  4. Thanks for the credit about my LEMP howto. i didn't know people found it so useful.

    ReplyDelete
  5. I don't know if this will help the people running into script errors but in the nginx configuration section this line was getting cutoff until I reduced my font size a couple notches:

    fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;

    I caught that right away and everything worked off the bat for me.

    ReplyDelete
  6. Thanks for this, a set of instructions which actually worked, from start to finish. I think nginx would do well to make this whole process easier, because nginx+PHP could easily take over from Apache+PHP in lots of cases.

    ReplyDelete
  7. Awesome. Thank you very much for these instructions. I got over eager and tried to compile the latest version of Lighttpd (1.4.19) but for some reason "./configure" does not spit out a "make" file, in turn making me want to pull my hair out.

    Since we only need the "spawn-fcgi" from it I just used your exact instructions and it worked. Now my server is happy, and so am I.

    ReplyDelete
  8. Like some of the others said, thanks. This works like a dream. Cheers!

    ReplyDelete
  9. agreed, this is a really really good tutorial

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Thanks a lot for this great howto.

    The fastcgi process are there after a reboot.

    The only problem I found is that i am unable to use the init-fastcgi script to stop or restart the fastcgi processes.

    /etc/init.d/init-fastcgi stop
    php: no process killed

    ReplyDelete
  12. Hi,
    Very good tutorial. Is there someone to explain how to create a correct virtual host following that guide ?

    Thanks

    Carlo

    ReplyDelete
  13. Thanks so much for making a great concise article on how to get this all working...

    Really appreciate it!

    ReplyDelete
  14. For those of you having problems getting the init script to start or stop you may need to change the killall -9 php to killall -9 php-cgi depending on your situation. Do a ps aux to see all the running processes and find out exactly what name your PHP processes are running as.

    Also, you don't have to run the Touch command to create the file before opening Vim. Just telling Vim to open a file name will create that file automatically if it doesn't exist.

    Thanks for the tutorial by the way, it really helped.

    ReplyDelete
  15. As gexla said you could need to use killall -9 php-cgi or (for php5 process) killall -9 php5-cgi

    ReplyDelete
  16. Thanks. I followed this for my Ubuntu 8.04, nginx, Slicehost VPS slice. But I'm getting that dreaded "No input file specified" error when a php file is loaded (see e,g, http://petersavich.com/Duck/Predictions/predictions.php). I tried setting cgi.force_reload = 0 in /etc/php5/cgi/php.ini per some suggestions on Google. But that didn't help. Any suggestions? Thanks.

    ReplyDelete
  17. Re my comment above, I finally figured it out. That "fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;" line in the nginx config file needs to point to the root directory of your own site, not to the nginx-default one (if you're using this on your own site). So when I changed /var/www/nginx-default to /path/to/my/root/directory, this all worked. Thanks much again.

    ReplyDelete
  18. @sfong regarding the missing switch error... I ran into this problem and realized that the php-fastcgi script is only two lines, though it appears as three lines in the tutorial due to word-wrapping in HTML. If you copy and paste the two lines verbatim into your terminal, you will get the following:

    #!/bin/sh
    /usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -f /usr/bin/php5-cgi

    The earlier error came from a mistaken carriage return after the -f option.

    Hope that helps,
    -Sam

    ReplyDelete
  19. Thanks for your article , I followed you step by step and the server runs well ,but the phpinfo() function shows none word about MYSQL,the mysql_connect() function return error : function not found .
    php5-mysql module had been installed . Any help ?
    Thanks

    ReplyDelete
  20. Works just perfect ...

    but just used the latest NGINX source with all these ...
    Keep the good work going :)

    ReplyDelete