Home » Planet Ubuntu, Ubuntu Tutorials

Setting up a LEMP Stack (Linux, Nginx, MySQL, PHP5) on Ubuntu 9.04

29 April 2009 16,320 views 17 Comments

After using Lighttpd for a couple of months, I wasn’t really happy with it, so I have decided to move from Lighttpd to Nginx, which is another open-source lightweight web server. In this tutorial, I am going to go over setting up Nginx, MySQL, and PHP5 on an Ubuntu server.

1. Install Nginx

aptitude install nginx

For some reason Nginx does not start automatically when it is installed, so we need to start Nginx.

/etc/init.d/nginx start

Now we want to make sure that Nginx installed properly. Open your web browser and point it to your servers IP address. If all is working fine you should see a page that says “Welcome to nginx!”

2. Install MySQL

aptitude install mysql-server mysql-client

3. Install PHP5

aptitude install php5-cgi php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl php5-json

Now edit /etc/php5/cgi/php.ini

nano /etc/php5/cgi/php.ini

and add:

cgi.fix_pathinfo = 1

to the end of the file.

4. Install Lighttpd

I know.. Your saying “but I wanted Nginx!” The reason we are installing Lighttpd is because Nginx does not come with a FastCGI package, and there isn’t a standalone package yet. So we are going to install Lighttpd, disable it, and use spawn-fcgi from the Lighttpd package.

aptitude install lighttpd

You will get an error message saying that port 80 is already in use. That’s fine because we don’t care about running Lighttpd anyway. Now we will remove Lighttpd from our servers startup:

update-rc.d -f lighttpd remove

5. Setup spawn-fcgi

Since we are going to use spawn-fcgi to handle PHP, we need to set it up to start when our server starts and make an init script so that we can control the processes. For starters, create the init script:

nano /etc/init.d/php-fastcgi

and add the following code to it and save it:

#! /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

There is no editing needed for the code above. Now we need to make it executable.

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

Now we will create the configuration file for spawn-fcgi:

nano /etc/default/php-fastcgi

and add:


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


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


# Environment variables, which are processed by PHP


In this file, you can change the FCGI_PORT, PHP_FCGI_CHILDREN, and PHP_FCGI_MAX_REQUESTS. If you change the port, make sure to note what you change it to because we will need it for later. Now, we want to make sure that spawn-fcgi starts when the server starts:

update-rc.d php-fastcgi defaults

6. Configure Nginx and your default vhost

For help with configuring Nginx beyond just the default configuration, please refer to the Nginx Wiki. We are now going to configure the default vhost so that we can verify that PHP is working with Nginx.


In the default vhost, change the following lines to look like this:

server_name _; location ~ \.php$ { fastcgi_pass; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name; include fastcgi_params; }

What we did here was changed the server_name to accept all incoming requests, uncommented the location stanza and defined where Nginx needs to look for spawn-fcgi. If you changed the port above in the /etc/default/php-fastcgi file, then you need to change the port on the fastcgi_pass line as well. On the line fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;, you need to change /var/ww/nginx-default to match your web root. On the line include fastcgi_params; you need to add a space between the include and the fastcgi_params as there is a bug in the default configuration and that space was omitted. Once you save the default-vhost, you need to restart Nginx.

/etc/init.d/nginx restart

Now we will create an info.php file in your web root:

nano /var/www/nginx-default/info.php

Add the following code and save the file:


Now in your web browser, pull up the newly created file (http://your-ip/info.php). You should see information about the version of PHP that you are running.

Note: When I installed Nginx, it did not start automatically, however it was setup to start when the server booted. I have heard stories of users having issues with Nginx starting automatically when the server boots. If Nginx does not start when you boot your server, run the following command which will make it start on boot:

update-rc.d nginx defaults


Nginx Wiki
Nginx, PHP and a PHP FastCGI daemon init script
Installing Nginx With PHP5 And MySQL Support On Ubuntu 8.10

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)


  • links for 2009-05-01 « Bloggitation said:

    […] Setting up a LEMP Stack (Linux, Nginx, MySQL, PHP5) on Ubuntu 9.04 (tags: nginx linux ubuntu php sysadmin) Comments (0) […]

  • Observer said:

    Hello cJ,

    I have one remark. I used your installation guide, which words great but i have made one minor alteration:
    file /etc/default/php-fastcgi

    Change this to FCGI_HOST= when php-fastcgi fails to run/start.


  • Ryan said:

    Nice tutorial!

    Followed it exactly, but I am getting 502 errors. Is there a common culprit?

  • How to configure nginx + php5 + mysql on debian 5 lenny | Admins eHow said:

    […] : ChrisJohnston.org VN:F [1.2.3_620]please wait…Rating: 0.0/10 (0 votes […]

  • James D Kirk said:

    Hey there, CJ. Realizing that it has bee a while since you posted this tutorial, am trusting you’re still monitoring it. I’ve gone through and had success up to the point of testing the connection of the php-fastcgi. Oh, I did install spawn-fcgi via apt-get now that it is available as a package to Ubuntu. There was no error messages, and all continued to flow right with your tutorial, so not sure if that is a challenge, but guessing (hoping!) not.

    I have inserted your code for checking the php connection into the default vhost, however, when I check the browser for the phpinfo file (info.php) I’m getting the standard 404 page. If I remove too much stuff from the default sites available page, I get nothing coming for the home page either.

    Any help or directive pointers would be great. I could post the vhost config file if needed. Thanks for your time.

  • James D Kirk said:

    Hey Chris,
    I was able to get php loaded and operating. I followed a similar tutorial located over at HowTo Forge, Installing Nginx With PHP5 And MySQL Support On Ubuntu 8.10

    Down about halfway through the page, you come to the similar install you talked about regarding the install of lighttpd and it’s removal. Just past that:

    To start a PHP FastCGI daemon listening on port 9000 on localhost and running as the user and group www-data, we run the following command:

    /usr/bin/spawn-fcgi -a -p 9000 -u www-data -g www-data -f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid

    I followed those commands through to the end of task #4 and php cranked right up on my new Jaunty install.

    Thanks for the message, CJ, and the tutorial!

  • Jason B said:

    Thanks James D Kirk!

    I had the same prob and added your command to /etc/rc.local and all runs perfectly

    Good tutorial!


  • the_guv said:

    nice Chris .. how’s it running?

    one thing that kinda puts me off this method is that there’s no long term support with Jaunty. why did you go with that and not Heron LTS, out of interest?

    you may be interested to take a look at my method, which is very different, configured really to host multi sites. also, it has fastCGI working without the Lighty workaround .. well, that is to say, using different workarounds πŸ˜‰

    would be splendid to compare notes. also, have you by any chance done any benchmarking?

  • Stephen Crosby said:

    I’m considering trying something like this. I’ve heard you can get much better performance if you use php-fpm. Have you tried it?

  • zone said:

    Thanks Chris for your excellent how-to.

  • Mac said:

    Hello there!

    Awesome tutorial: you achieved exactly what I would like to… but I got a problem I can’t manage to work around, maybe you can give me some hint? πŸ™‚

    I am running RC of 9.10 and I followed the instructions to the letter, nginx works just fine (html files are properly managed), but I am struggling with the php part. Indeed all that I can achieve is to get a “502 Bad Gateway” error anytime I try to reach an index.php file (http://localhost or http://localhost/index.php give the same result).

    In other forums I read about checking if php is running with “ps ax | grep php”. It seems to me that might be the problem then, as the result is “2986 pts/1 S+ 0:00 grep php”.

    I tried to manually fire up php via “/etc/init.d/php-fastcgi start”, but even after that (the console does not report any error) the above mentioned ps/grep combintation does not report any php process running.

    Is there anything I am missing in the picture? Any help or pointer in the right direction would be greatly appreciated.

    Many thanks in advance for your time,

  • Mac said:

    Sorry guys… didn’t reach the page with the comments on it, and only when I posted I saw the already-existing thread…

    The Jams D Kirk command solved my problem too! πŸ™‚

    Thanks a lot for the precious how-to,

  • Christians dagbok – 2009-12-30 | En sur karamell said:

    […] Shared Setting up a LEMP Stack (Linux, Nginx, MySQL, PHP5) on Ubuntu 9.04 | chrisjohnston.org. […]

  • Sami said:

    thanks Chris for the tuto, even if i had a 503 error.

    fixed thanks to James D Kirk πŸ™‚

  • Ron said:

    Hi ..i’ve followed he tutorial exactly but i cant open http://my-ip/info.php. what do you mean by:

    On the line fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;, you need to change /var/www/nginx-default to match your web root.

Leave your response!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar.