← All posts

Ubuntu. Development Environment with Nginx+PHP5.3+FPM+MySQL

Illustration for setting up a development environment in Ubuntu

васяц and I were setting up a development environment on our netbooks over the weekend and decided to use PHP 5.3 and PHP-FPM. I decided to install everything in the simplest way possible, so I turn to apt-get first, and only then to building from source. By the way, if you already have any version of PHP installed, remove it first (including libapache2-mod-php5, if you have it).

These instructions also apply to FreeBSD; just use installation from ports instead of “apt-get install”.

Adding a user

First, let’s create the www user and group that Nginx and PHP will run under.


addgroup www
adduser --shell /usr/sbin/nologin --no-create-home --ingroup www --disabled-password --disabled-login www

Installing Nginx

As I said, we’ll take the simplest route:


apt-get install nginx

Now let’s edit /etc/nginx/nginx.conf and add an upstream for php-fpm:


user www www;
worker_processes  1;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include     /etc/nginx/mime.types;
    access_log  /var/log/nginx/access.log;

    sendfile        on;
    keepalive_timeout  65;
    tcp_nodelay        on;

    upstream php-fpm {
        #server 127.0.0.1:9000;
        server unix:/tmp/php-fpm.sock;
    }

    include /etc/nginx/conf.d/*.conf;
}

Now let’s move on to installing PHP.

Installing PHP 5.3 + PHP-FPM

To build php 5.3 + php-fpm, we’ll need to download the php-fpm 5.3 source, but first make sure your version of autoconf is 2.13. People say other versions cause problems. I tried building with a newer version (autoconf 2.59, I think)—and yes, there really are problems. So we’ll install 2.13 specifically:


apt-get install autoconf2.13

Now we need to install bison:


apt-get install bison

Next, libevent from source. Specifically, version 1.4.13 (the older version I had installed wasn’t suitable).
There was a problem while installing libevent—libtoolize was missing… Let’s install libtool first:


apt-get install libtool

And now libevent:


wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
tar -xzvf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./autogen.sh
./configure
make install

All versions of libevent are here.

And finally, let’s build libxml:


wget ftp://xmlsoft.org/libxml2/libxml2-2.7.6.tar.gz
tar -xzvf libxml2-2.7.6.tar.gz
cd libxml2-2.7.6
./configure
make && make install

You may need mysql_config, for example for Sphinx or the MySQL module for PHP; if so, install libmysqld-dev:


apt-get install libmysqld-dev

Now, at last, let’s download php-fpm and run the build script:


svn co http://svn.php.net/repository/php/php-src/branches/PHP_5_3_FPM php_5_3_fpm
cd php_5_3_fpm
./buildconf 

We now have ./configure, and we can specify which options to build PHP with:


./configure --prefix=/usr/local --disable-short-tags --enable-fpm --with-layout=GNU --without-pear \
--enable-mbstring --with-mysql=/usr/bin/mysql_config --with-mysqli=mysqlnd
make && make install

You can read about some PHP options here, and for extensions such as mysqli/mbstring and others, check the “Installation” section of the official documentation, for example mbstring or mysqli.

Many options are enabled by default; you can change this with --disable-all.

Since I installed it in a custom directory, I’ll create a link to my php for convenience:


ln -s /usr/local/bin/php /usr/bin/php

We’ll need a script to control php-fpm, so let’s copy it from the source:


cp php_5_3_fpm/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm

I previously had PHP 5.2.10 installed (from packages), so I still had a php.ini, and I copied it:


cp /etc/php5/apache2/php.ini /usr/local/etc/php.ini

If you don’t know where to put your php.ini, open phpinfo, look at “Configuration File (php.ini) Path”, and put your php.ini there. On restarting, PHP reported some options as deprecated, so I simply commented them out. If you don’t have a php.ini file, you can use mine. There’s nothing special in it; it’s just in case you don’t have this file.

Configuring PHP-FPM

Let’s copy the default config:


cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf

And tidy it up a little:


Address to accept fastcgi requests on.
Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket'
<!--<value name="listen_address">127.0.0.1:9000</value>-->
<value name="listen_address">/tmp/php-fpm.sock</value>
....
<value name="listen_options">

        Set listen(2) backlog
        <value name="backlog">-1</value>

        Set permissions for unix socket, if one used.
        In Linux read/write permissions must be set in order to allow connections from web server.
        Many BSD-derrived systems allow connections regardless of permissions.
        <value name="owner">www</value>
        <value name="group">www</value>
        <value name="mode">0666</value>
</value>
...
<value name="php_defines">
    <!-- <value name="sendmail_path">/usr/sbin/sendmail -t -i</value> -->
    <value name="display_errors">1</value>    
    <value name="error_log">/var/log/php-error.log</value>    
    <value name="log_errors">true</value>
</value>
...
Unix user of processes
<value name="user">www</value>

Unix group of processes
<value name="group">www</value>
...
Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect.
Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+)
Makes sense only with AF_INET listening socket.
<value name="allowed_clients">127.0.0.1</value>

Briefly, here’s what we’re changing:
1. Use a Unix socket rather than TCP
2. Set the user and group to www
3. Send errors to the standard stream and specify the error log file

I’ve already posted this config here.

Problems with MySQLi

MySQLi complained that it couldn’t open the MySQL socket at “/tmp/mysql.sock”. I found the socket path in “/etc/my.cnf”, copied it, and corrected the path in “/usr/local/etc/php.ini”:


mysqli.default_socket = /var/run/mysqld/mysqld.sock

Starting our application server

Let’s add a virtual host to Nginx:


server {
    listen 80;
    server_name test.loc;
    root /www/test/htdocs;

    location / {
        index index.php;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass php-fpm;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

And start our server:


service mysql start
service nginx start
service php-fpm start

As always, it’s all simple! :)

Comments are closed. Read the original discussion in Russian →