Table of Contents
Nginx installation and configuration on Debian
debian http nginx php cgi
This article describes the installation and configuration of Nginx on Debian. We will cover basic configuration and CGI management for PHP and C/Perl.
Nginx
The installation of nginx is pretty straighforward:
# aptitude install nginx
This creates the configuration directory into /etc/nginx. As usual with Debian, the main configuration file nginx.conf includes another repository for the virtual hosts: /etc/nginx/sites-enabled.
By default, this directory contains a virtual host that we're going to reuse for our configuration.
PHP 5 & Spawn-fcgi
Spawn-fcgi is a daemon that will call the php5-cgi program every time is receive a request on a socket.
It is initially part of the lighttpd project, but is also available alone in debian:
# apt-cache show spawn-fcgi Package: spawn-fcgi Priority: extra Section: web Installed-Size: 96 Maintainer: Jeremy Lal <kapouer@melix.org> Architecture: i386 Version: 1.6.3-1 Depends: libc6 (>= 2.1) Filename: pool/main/s/spawn-fcgi/spawn-fcgi_1.6.3-1_i386.deb Size: 13210 MD5sum: b2c2bc467e22d3ed01e9d134ba1b2c33 SHA1: 312bd971908cddeb7f06d12520f105de86379f42 SHA256: 50dc996d1c7219dc71ebb546bcdc47569b95e39793f7ad6ae35884d9151b42b9 Description: A fastcgi process spawner spawn-fcgi allows fcgi processes to be separated from web server process : * Easy creation of chmoded socket. * Privilege separation without needing a suid-binary, or running a server as root. * You can restart your web server and the FastCGI applications without restarting the others. * You can run them in different chroot()s. * Running your FastCGI applications doesnâ??t depend on the web server you are running, which allows for easier testing of/migration to other web servers. Homepage: http://redmine.lighttpd.net/projects/spawn-fcgi Tag: implemented-in::c, qa::low-popcon, role::program
So, let's install it, along with php5-cgi and some of its components:
# apt-get install spawn-fcgi php5-cgi php5-imap php5-gd php5-sqlite
<note tip>If your distribution doesn't ship spawn-fcgi, you can download the latest version of the source code from the official website and build it with a simple “./configure && make”. The binary is then located in the src/ subfolders, just copy spawn-fcgi in /usr/bin/ and you're done !</note>
Launch spawn-fcgi on port 9000
Spawn-fcgi will listen on tcp port 9000 and receive requests from nginx. To do so, we need to launch spawn-fcgi will the following command :
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -g www-data /usr/bin/php5-cgi
It then creates a new process that listens on port 9000 and is attributed to user www-data (same as nginx).
minideb:/# netstat -tpan |grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 21621/php5-cgi minideb:/# ps -edf|grep php www-data 21621 1 0 17:24 ? 00:00:04 /usr/bin/php5-cgi root 21869 21803 0 18:05 pts/1 00:00:00 grep php
You might want to set up an init script in /etc/init.d/php5cgi and link it for runtime in /etc/rc2.d. Below is the one I use:
#!/bin/bash COMMAND=/usr/local/bin/spawn-fcgi NAME=php5-cgi ADDRESS=127.0.0.1 PORT=9000 USER=www-data GROUP=www-data PHPCGI=/usr/bin/php5-cgi KILL=/bin/kill case "$1" in start) start-stop-daemon --start \ --exec $COMMAND -- -a $ADDRESS -p $PORT \ -u $USER -g $GROUP -f $PHPCGI -P /var/run/$NAME.pid|| true echo -n "$NAME started with pid " cat /var/run/$NAME.pid echo ;; stop) if [ -e /var/run/$NAME.pid ] then $KILL `cat /var/run/$NAME.pid` rm /var/run/$NAME.pid echo "$NAME stopped" else echo "$NAME is not running, no pid file in /var/run/" fi ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 ;; esac exit $RETVAL
PHP5-CGI configuration for Nginx
So, now that we have PHP in FastCGI mode ready, we need to tell nginx how to handle those php files.
Let's open this /etc/nginx/sites-enables/defaults virtual host and modify a few lines that are, for now, commented out.
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
Test the configuration before restarting the server :
# /etc/init.d/nginx configtest Testing nginx configuration: the configuration file /etc/nginx/nginx.conf syntax is ok configuration file /etc/nginx/nginx.conf test is successful nginx.
And then restart it with :
# /etc/init.d/nginx restart Restarting nginx: the configuration file /etc/nginx/nginx.conf syntax is ok configuration file /etc/nginx/nginx.conf test is successful nginx.
Great, now we create the file /var/www/nginx-default/index.php with the classic phpinfo() inside :
<?php phpinfo(); ?>
Just open your favorite browser (links2, of course) and open the page :
$ links2 http://192.168.1.20:80/index.php phpinfo() (p1 of 17) PHP Logo PHP Version 5.2.11-1 System Linux minideb 2.6.26-2-486 #1 Sun Jun 21 04:15:19 UTC 2009 i686 Build Date Sep 20 2009 12:24:16 Server API CGI/FastCGI Virtual Directory Support disabled Configuration File /etc/php5/cgi (php.ini) Path Loaded Configuration File /etc/php5/cgi/php.ini Scan this dir for /etc/php5/cgi/conf.d additional .ini files /etc/php5/cgi/conf.d/gd.ini, /etc/php5/cgi/conf.d/imap.ini, additional .ini files /etc/php5/cgi/conf.d/pdo.ini, parsed /etc/php5/cgi/conf.d/pdo_sqlite.ini, /etc/php5/cgi/conf.d/sqlite.ini, /etc/php5/cgi/conf.d/suhosin.ini PHP API 20041225 PHP Extension 20060613 Zend Extension220060519 Debug Build no Thread Safety disabled Zend Memory Manager enabled IPv6 Support enabled Registered PHP Streams https, ftps, compress.zlib, compress.bzip2, php, file, data,
It works ;)
FCGI Wrap
If the previous configuration is usefully for PHP websites, you might want to use scripts in differents langages. I personally use FCGI Wrap for C and Perl scripts. However, since it is not available in Debian, you need to build it yourself.
Get the source and build it
fcgiwrap is written by Grzegorz Nosek (gnosek). you can get the latest version from his github page as follow:
# wget http://github.com/gnosek/fcgiwrap/tarball/master # tar -xzvf gnosek-fcgiwrap-ba8c8d9.tar.gz gnosek-fcgiwrap-ba8c8d9/ gnosek-fcgiwrap-ba8c8d9/.gitignore gnosek-fcgiwrap-ba8c8d9/Makefile.in gnosek-fcgiwrap-ba8c8d9/README.rst gnosek-fcgiwrap-ba8c8d9/configure.ac gnosek-fcgiwrap-ba8c8d9/fcgiwrap.c
To build it, you will need the following packages:
# aptitude install autoconf make libfcgi-dev gcc
Now, simply launch the building commands:
# autoconf # ./configure checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o [...] # make gcc -std=gnu99 -Wall -Wextra -Werror -pedantic -O2 -g3 fcgiwrap.c -o fcgiwrap -lfcgi
And you will end up with a nice little binary called fcgiwrap. Just copy this binary into /usr/bin/.
Spawn-fcgi init script for fcgiwrap
The following script must be installed into /etc/init.d/ :
#!/bin/bash COMMAND=/usr/bin/spawn-fcgi NAME=fcgiwrap ADDRESS=127.0.0.1 PORT=9001 USER=www-data GROUP=www-data CGI=/usr/bin/fcgiwrap KILL=/bin/kill case "$1" in start) start-stop-daemon --start \ --exec $COMMAND -- -a $ADDRESS -p $PORT \ -u $USER -g $GROUP -f $CGI -P /var/run/$NAME.pid|| true echo -n "$NAME started with pid " cat /var/run/$NAME.pid echo ;; stop) if [ -e /var/run/$NAME.pid ] then $KILL `cat /var/run/$NAME.pid` rm /var/run/$NAME.pid echo "$NAME stopped" else echo "$NAME is not running, no pid file in /var/run/" fi ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 ;; esac exit $RETVAL
<note important>I assume that you have already installed spawn-fcgi. Otherwise, please go back there </note>
Now, launch the script and check that the socket is listening on TCP port 9001.
# /etc/init.d/spawnfcgiwrap start spawn-fcgi: child spawned successfully: PID: 24818 fcgiwrap started with pid 24818 # netstat -taupen |grep 9001 tcp 0 0 127.0.0.1:9001 0.0.0.0:* LISTEN 0 24109419 24818/fcgiwrap
Good to go, next we need to edit nginx server's configuration.
FCGI Wrap configuration for Nginx
This is very similar to what we did earlier with PHP. Nginx just needs for specific extension in the URI - in this case the files that end with .cgi - and send the requests for those files to the FCGI wrapper.
So, configuration of /etc/nginx/sites-availables/mysite looks like this :
server { listen 80; server_name mysite; [....] location /tcgraph { include /etc/nginx/fastcgi_params; if ($uri ~ "\.cgi$"){ fastcgi_pass 127.0.0.1:9001; } }
Restart the nginx daemon and you're all set.
Test fcgiwrap
The basic perl script below can be used to test your configuration. Put it in your web directory and make sure it's executable.
#!/usr/bin/perl -w use POSIX qw(uname); my $host = (POSIX::uname())[1]; sub print_html() { print "Content-Type: text/html\n\n"; print <<HEADER; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Perl CGI test for $host</title> <meta http-equiv="Pragma" content="no-cache" /> </head> <body> HEADER print "<h1>Perl CGI test for $host</h1>\n"; print "<p>script launched by user $ENV{USER}</p>"; print <<FOOTER; <hr/> </body></html> FOOTER } sub main() { print_html; } main;
Once again, testing with links2 gives the following result:
Perl CGI test for neuromatrice Perl CGI test for neuromatrice script launched by user www-data
Configuration works ! :)