Drupal 6 Hosting With nginx And PHP-FastCGI On Ubuntu 9.10

Drupal is a great CMS but is a bit hefty when you host it on bargain-basement shared hosting, and virtual private servers are great but memory-constrained at the low-end. Apache can be a big offender when it comes to resource usage, so a nice alternative is nginx, a fast, light-weight and efficient http server that supports PHP via PHP-FastCGI. So this is a pretty slick setup for hosting Drupal, and I've taken a few different howtos and forum posts to put together this guide, which should have all you need in one stop, including a working URL rewrite config.

If you're on a VPS, your hosting provider will do the operating system and OpenSSH server installation. For those who are doing this on your own computer or VM, rather than re-hash Falko's excellent server installation guide, I'm going to send you there first for steps 1 through 3:

The Perfect Server - Ubuntu 9.10 [ISPConfig 3]

Ok, so the next thing we're going to do is become root. Type:

sudo su -l

Next, we're going to remove the requirement to type your password each time you use sudo. Feel free to skip this step if you like:

visudo

If it asks, I use nano as a text editor, and I'll continue to use it. Feel free to replace this with your own text editor of choice.

Change the line:

%admin ALL=(ALL): ALL

to

%admin ALL=NOPASSWD: ALL

And save and exit with Ctrl-w and Ctrl-x.

Next we're going to install the requisite software. Install the following packages with the command:

aptitude install openssh-server nginx mysql-client mysql-server imagemagick php5 php5-cgi php5-cli php5-common spawn-fcgi php5-gd php5-imagick php5-imap php5-mysql

The installation is going to bring up a window asking you to create root password for MySQL. Enter it here. We'll need to use that password towards the end of this howto.

There are a few other packages you may want as well, for additional PHP features. You can install them with:

aptitude install php-auth php-pear php5-curl php5-idn php5-mcrypt php5-memcache php5-mhash php5-ming php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl mcrypt

Now, the default settings for these programs are pretty good, but there's a few changes we should make. First is nginx:

nano /etc/nginx/nginx.conf

And modify the following lines to start with:

worker_processes  3;
...
keepalive_timeout 10; ...

You as you get a bit more familiar with the the load and resources, you'll want to refine these further. Let's also modify the memory usage of PHP. When you're uploading images or especially video in Drupal, your upload size, execution time, and memory usage may prevent your uploads. So we're going to increase these sizes. Ideal values depend entirely on the memory available on your server. This is what I used on my VPS with 340MB RAM.

nano /etc/php5/cgi/php.ini
; Maximum allowed size for uploaded files.
upload_max_filesize = 50M
...
; Maximum size of POST data that PHP will accept.
post_max_size = 50M
...
;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;
max_execution_time = 120     ; Maximum execution time of each script, in seconds
max_input_time = 60 ; Maximum amount of time each script may spend parsing request data
;max_input_nesting_level = 64 ; Maximum input variable nesting level
memory_limit = 128M      ; Maximum amount of memory a script may consume (16MB)

Nginx passes php files to PHP-FastCGI for execution, so we need to create a couple scripts to launch PHP-FastCGI. To do so, type the following:

nano /usr/bin/php-fastcgi

and paste the following script:

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

Next, we need to make the script executable:

chmod a+x /usr/bin/php-fastcgi

The second script is an init script to call our previous script on boot. Type:

nano /etc/init.d/php-fastcgi

and paste the following script:

#!/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 set this as executable as well, and set it to execute on startup.

chmod 755 /etc/init.d/php-fastcgi
update-rc.d php-fastcgi defaults
service php-fastcgi start

Next let's create the home folders for your websites and set a few permissions. I prefer the /srv to /var/www but this is entirely a matter of preference. From here on, whenever you see example.com, update it to your settings.

mkdir -p /srv/www/www.example.com/public_html
mkdir /srv/www/www.example.com/logs
chown -R www-data:www-data /srv/www/www.example.com

Next, we create an nginx configuration for out site.

nano /etc/nginx/sites-available/www.example.com

And paste:

server {
    listen   80;
#   server_name _   # catch-all
    server_name example.com www.example.com;
    access_log /srv/www/www.example.com/logs/access.log;
    error_log /srv/www/www.example.com/logs/error.log;
    root   /srv/www/www.example.com/public_html;
    index  index.php;
    location / {
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php?q=$1 last;
        }
    }
    # serve static files directly
    location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico)$ {
        rewrite ^/favicon.ico$ /sites/default/themes/mytheme/favicon.ico break;
        access_log        off;
        expires           30d;
    }
    # If you use the Imagecache module, you'll need to update the location and enable this directive
    #location ^~ /sites/default/files/imagecache/ {
    #    index  index.php index.html;
    #    # assume a clean URL is requested, and rewrite to index.php
    #    if (!-e $request_filename) {
    #        rewrite  ^/(.*)$  /index.php?q=$1  last;
    #        break;
    #    }
    #}
    location ~ \.php$ {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME  /srv/www/www.example.com/public_html$fastcgi_script_name;
    }
}

Next, we enable the configuration:

cd /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/www.example.com

And lets reload nginx.

service nginx restart

Before going further, let's test out nginx and PHP.

nano /srv/www/www.example.com/public_html/index.php

Paste in the following code:

<? echo phpinfo(); ?>

And let's browse to your site. If your DNS isn't set up yet, you could add

12.34.56.78    example.com www.example.com

to your /etc/hosts on your Linux or OS X host, or to your c:\windows\system32\drivers\etc\hosts file in Windows, which will allow you to access your server by domain name.

So browse to http://www.example.com and ensure it works. If it does, we'll go on to install Drupal.

First thing we do is download and untar the files. This was the most recent when I downloaded it. Make sure you get the latest version 6.

cd /srv/www/www.example.com/public_html
wget http://ftp.drupal.org/files/projects/drupal-6.16.tar.gz
tar zxvf drupal-6.16.tar.gz

And let's move them into the right place and clean up a bit.

mv drupal-6.16/* .
rm -r drupal-6.16 drupal-6.16.tar.gz

Next, we have to set up a configuration file, as well as create a files directory.

cd sites/default/
cp default.settings.php settings.php
chown www-data:www-data settings.php
chmod 775 settings.php
mkdir files
chown www-data:www-data files
chmod 775 files

Drupal needs a MySQL database as well, so let's create one here:

mysql -u root -p
CREATE DATABASE drupaldb;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON drupaldb.* TO 'drupaluser'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON drupaldb.* TO 'drupaluser'@'localhost.localdomain' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
quit;

Now browse to http://www.example.com

Choose Install Drupal in English

Then enter the information for the database you just created.

Step through, name your site and create the Administrator account.

Drupal uses a cron entry to perform maintenance and check for updates. Let's add that while we're at the terminal.

crontab -e

And add the following entry:

0   *   *   *   *   wget -O - -q -t 1 http://www.example.com/cron.php

Now, no Drupal setup is complete without at least the Admin Menu module.

cd /srv/www/www.example.com/public_html/sites/all
mkdir modules
cd modules
wget http://ftp.drupal.org/files/projects/admin_menu-6.x-1.5.tar.gz
tar zxvf admin_menu-6.x-1.5.tar.gz

You can then enable the module in the Modules menu. And there you go, you've got a Drupal installation working.

Now, there's a few more things to do that I'm not going to detail in this howto, but ought to be done. The first thing missing is any sort of e-mail setup. The second is locking down the server for production use. Otherwise, you're good to go.

 

References:

Share this page:

7 Comment(s)