Inveigled By Design

The art of persuasive design

Setting up and Testing Php on Nginx



In the previous article, we set up Nginx with Ruby Enterprise Edition and Passenger support. Now we need to get php running if we want to run wordpress or drupal or other php-based sites. We’ll also add mysql so we have a database back end for these sites

Installing mysql:

This is pretty simple, do the installation:

sudo aptitude install mysql-server mysql-client libmysqlclient15-dev

You will be asked to supply a root password. Make sure you store it so it doesn’t get lost.

Since this is a production server, it should be secured:

sudo mysql_secure_installation

Setting up Php:

First the installation:

sudo aptitude install php5-cgi php5-mysql

Note that if you need to access the php.ini file, it will be located here: /etc/php5/cgi/php.ini


Now we need a few scripts and configuration files. I got these from here, but I’ll post the contents here for completeness.

First the init script:

sudo nano /etc/init.d/php-fastcgi

Copy and paste this in the file:

#! /bin/sh
### BEGIN INIT INFO
# Provides: php-fastcgi
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop php-cgi in external FASTCGI mode
# Description: Start and stop php-cgi in external FASTCGI mode
### END INIT INFO

# Author: Kurt Zankl <[EMAIL PROTECTED]>

# Do NOT "set -e"

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="php-cgi in external FASTCGI mode"
NAME=php-fastcgi
DAEMON=/usr/bin/php-cgi
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
PHP_CONFIG_FILE=/etc/php5/cgi/php.ini

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# If the daemon is not enabled, give the user a warning and then exit,
# unless we are stopping the daemon
if [ "$START" != "yes" -a "$1" != "stop" ]; then
log_warning_msg "To enable $NAME, edit /etc/default/$NAME and set START=yes"
exit 0
fi

# Process configuration
export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
DAEMON_ARGS="-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE"

do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
--background --make-pidfile --chuid $EXEC_AS_USER --startas $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}

do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE > /dev/null # --name $DAEMON
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons donâ^À^Ùt delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac

Now the defaults:

sudo nano /etc/default/php-fastcgi

Copy and paste this into the file:

START=yes

# Which user runs PHP? (default: www-data)

EXEC_AS_USER=www-data

# Host and TCP port for FASTCGI-Listener (default: localhost:9000)

FCGI_HOST=localhost
FCGI_PORT=10005

# Environment variables, which are processed by PHP

PHP_FCGI_CHILDREN=4
PHP_FCGI_MAX_REQUESTS=1000

Note that we’re running php as the www-data user, which is how we configured Nginx.

And now the configuration:

sudo mkdir /etc/nginx
sudo nano /etc/nginx/fcgi.conf

Copy and paste this into the file:

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;

Make the init script executable and start it:

sudo chmod +x /etc/init.d/php-fastcgi
sudo /etc/init.d/php-fastcgi start

Testing php:

Verify that it is running:

sudo ps ax | grep php

Now we want to make sure it starts on reboot:

sudo update-rc.d php-fastcgi defaults 21 23

Just to be sure, test the reboot:

sudo reboot
sudo ps ax | grep php

Make a php info test site:

Often it is useful to be able to view the output of phpinfo(), but it is not something you want to have available on the internet all the time for security reasons. To solve this problem, I made a site with just the phpinfo file that I can enable/disable with scripts.


First, we need to set up our sites directory. People often put their sites in their home directories or in /public_html or various other configurations.


Substitute the path to your sites root folder for “pathToSitesRoot” and your domain name for “yourDomainName”, both without the quotes. Depending on where you want your sites root folder, you may have to set some permissions to make this work.

Make the directory:

mkdir "pathToSitesRoot"
mkdir "pathToSitesRoot"/php."yourDomainName".com/public
mkdir "pathToSitesRoot"/php."yourDomainName".com/log

Now make the file that will display the php information:

nano "pathToSitesRoot"/php."yourDomainName".com/public/index.php

Add this one line to the file and save it:

<?php echo phpinfo(); ?>

Now set up a host for the site in the Nginx sites-available folder:

sudo nano /usr/local/nginx/sites-available/php."yourDomainName".com

Copy and paste this into the file (adjusting your domain name and path to your sites where applicable):

server {
   listen 80;
   server_name php."yourDomainName".com;

   access_log "pathToSitesRoot"/php."yourDomainName".com/log/access.log;
   error_log "pathToSitesRoot"/php."yourDomainName".com/log/error.log;

    location / {
     root "pathToSitesRoot"/php."yourDomainName".com/public;
     index index.html index.htm index.php;

    }

    # .php and .php5 sent to php5
    location ~ .*\.php[345]?$ {
      include /etc/nginx/fcgi.conf;
      fastcgi_pass 127.0.0.1:10005;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME "pathToSitesRoot"/php."yourDomainName".com/public$fastcgi_script_name;
    }
}

Now to test, enable the site in Nginx:

sudo ln -s /usr/local/nginx/sites-available/php."yourDomainName".com /usr/local/nginx/sites-enabled/php."yourDomainName".com

Now restart Nginx to enable the site:

sudo /etc/init.d/nginx restart

You should be able to browse in your web browser to http://php.”yourDomainName”.com and see the php info page. It will tell you what you have installed and the version numbers. I’ve often found this helpful when troubleshooting problems with WordPress and Drupal.


To make it easy to enable and disable the site, create a few scripts. I prefer to store them under my user folder:

cd ~
mkdir scripts
cd scripts

First the enable script:

nano enablephp

Copy and paste this into the file (your domain name where applicable):

# !/bin/sh

ln -s /usr/local/nginx/sites-available/php."yourDomainName".com /usr/local/nginx/sites-enabled/php."yourDomainName".com

/etc/init.d/nginx restart

Now the disable script:

nano disablephp

Copy and paste this into the file (substituting your domain name where applicable):

#! /bin/sh

rm /usr/local/nginx/sites-enabled/php.inveigledsoftware.com
/etc/init.d/nginx restart

Now make the scripts executable:

chmod +x enablephp
chmod +x disablephp

Now you can enable the site with sudo enablephp and disable it with sudo disablephp. Be sure to always execute disablephp when you are done examining the php information to prevent broadcasting your installation information on the internet.


Now with mysql and php running you are ready to install php-based applications like Drupal or WordPress.

One Response to “Setting up and Testing Php on Nginx”

  1. [...] Setting up and Testing Php on Nginx [...]

Leave a Reply

Creative Commons License
Content on this site is licensed under a Creative Commons Attribution-Share Alike 3.0 License
Copyright © 2009 Inveigled Software