Nginx + PHP-FPM + HHVM

What the heck are you talking about?

The workshop you were waiting for

Created by Javi M. / @javiyt

Code can be found at: bitbucket.org/javiyt/workshop_nginx

What's nginx?

  • Web server
  • Reverse proxy
  • mail proxy server
  • High performance

What's nginx?

Features

  • Multiplatform
  • Serve static files
  • Reverse proxying with cache
  • Support for FastCGI, uwsgi, SCGI and memcached
  • Modular architecture
  • SSL and TLS support
  • Event driven architecture

What's nginx?

Features

  • Fast configuration reloading
  • 3xx-5xx error codes redirection
  • Rewrite module using regexp
  • HTTP referer validation
  • Embedded Perl
  • FLV and MP4 streaming

What's nginx?

Who's using it?

  • Wordpress
  • Github
  • Facebook
  • Pinterest
  • Airbnb
  • Eventbrite
  • and many more

What's nginx?

What modules are available?

First exercise

Install and basic configuration

Install nginx and check the basic configuration parameters

            
                sudo aptitude install nginx
            
            
                user www-data;
                worker_processes 4;
                pid /run/nginx.pid;

                events {
                    worker_connections 768;
                }

                http {

                    sendfile on;
                    tcp_nopush on;
                    tcp_nodelay on;
                    keepalive_timeout 65;
                    types_hash_max_size 2048;

                    include /etc/nginx/mime.types;
                    default_type application/octet-stream;

                    access_log /var/log/nginx/access.log;
                    error_log /var/log/nginx/error.log;

                    gzip on;
                    gzip_disable "msie6";

                    include /etc/nginx/conf.d/*.conf;
                    include /etc/nginx/sites-enabled/*;
                }
            
        

Second exercise

Virtual host configuration

  • Create a virtual host pointing to /vagrant/www
  • Configure the vhost to serve only static files
  • Disable default host
  • Enable your host
  • Reload nginx configuration

Third exercise

404 custom page

  • Create a 404 page under /vagrant/www
  • Configure the vhost to serve the 404 page
  • Reload nginx configuration

Fourth exercise

Configuration by location

  • Create a folder called "aliastest" under /vagrant/www
  • Configure the vhost to serve the aliastest when accessing test folder
  • Reload nginx configuration

PHP-FPM

Lot of letters without meaning

  • FPM: FastCGI Process Manager
  • Enhances FastCGI
  • PHP server daemon
  • Specific UID/GID

PHP-FPM

Lot of letters without meaning II

  • chroot
  • Control number of processes
  • Different PHP versions installed on same machine
  • Communication via sockets
  • Status checker

PHP-FPM: Why?

  • Improve security
  • Scales easily
  • Runs on any webserver: nginx, lighttpd, cherokee, ...
  • Request can be cached on the webserver side
  • Each process has its own configuration

Fifth exercise

Installing PHP-FPM

            
                sudo aptitude install php5-fpm
            
        
            
                ;;;;;;;;;;;;;;;;;;;;;
                ; FPM Configuration ;
                ;;;;;;;;;;;;;;;;;;;;;

                ;include=/etc/php5/fpm/*.conf

                ;;;;;;;;;;;;;;;;;;
                ; Global Options ;
                ;;;;;;;;;;;;;;;;;;

                [global]
                pid = /var/run/php5-fpm.pid
                error_log = /var/log/php5-fpm.log
                syslog.facility = daemon
                log_level = debug
                process.max = 128

                ;;;;;;;;;;;;;;;;;;;;
                ; Pool Definitions ;
                ;;;;;;;;;;;;;;;;;;;;
                include=/etc/php5/fpm/pool.d/*.conf
            
        

Sixth exercise

Configuring a pool

  • Edit /etc/php5/fpm/pool.d/www.conf
  • Set configuration for the pool:
    • to run on port 9001
    • to allow access only for localhost
    • chroot to /vagrant/www
    • set some environment variables

Sixth exercise

Configuring a pool (Solution)

            
                [www]
                user = www-data
                group = www-data

                listen = 127.0.0.1:9001
                listen.allowed_clients = 127.0.0.1

                pm = dynamic
                pm.max_children = 5
                pm.start_servers = 1
                pm.min_spare_servers = 1
                pm.max_spare_servers = 1
                pm.process_idle_timeout = 10s;
                pm.max_requests = 500

                pm.status_path = /fpm-status

                access.log = /var/log/php-fpm/$pool.access.log
                slowlog = /var/log/php-fpm/$pool.log.slow

                request_slowlog_timeout = 10s;

                chroot = /vagrant/www/
                chdir = /

                catch_workers_output = yes

                security.limit_extensions = .php

                env[HOSTNAME] = $HOSTNAME
                env[PATH] = /usr/local/bin:/usr/bin:/bin
                env[TMP] = /tmp
                env[TMPDIR] = /tmp
                env[TEMP] = /tmp
                env[PHP_ENVIRONMENT] = 'development'

                php_flag[display_errors] = off
                php_admin_value[memory_limit] = 32M
                php_admin_value[error_log] = /var/log/php-fpm/$pool.error.log
            
        
            
                /etc/init.d/php5-fpm restart
                mkdir /var/log/php-fpm/
            
        

Seventh exercise

Configuring nginx to use PHP

  • Edit vagrant host
  • Add the location to connect to the pool when accessing a PHP file

Seventh exercise

Configuring nginx to use PHP (Solution)

            
                server {
                    listen 80 default_server;
                    listen [::]:80 default_server ipv6only=on;

                    root /vagrant/www;
                    index index.html index.htm index.php;
                    error_page 404 /404.html;

                    server_name localhost;

                    location / {
                        try_files $uri $uri/ =404;
                    }

                    location /test {
                        alias /vagrant/www/aliastest/;
                    }

                    location ~ php/.*\.php$ {
                        fastcgi_index   index.php;
                        fastcgi_pass    127.0.0.1:9001;
                        include /etc/nginx/fastcgi_params;
                        fastcgi_param   SCRIPT_FILENAME    $fastcgi_script_name;
                        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
                    }
                }
            
        
http://localhost:8080/php/info.php

Eighth exercise

Configuring nginx to access PHP-FPM status page

  • Edit vagrant host
  • Add the location to connect to the status page of the desired pool

Eighth exercise

Configuring nginx to access PHP-FPM status page (Solution)

            
                location ~ ^/fpm-status$ {
                    access_log off;
                    include /etc/nginx/fastcgi_params;
                    fastcgi_pass 127.0.0.1:9001;
                }
            
        
http://localhost:8080/fpm-status

Ninth exercise

Configuring nginx to load balancing PHP-FPM

  • Create a pool identical to the one existing running on port 9002
  • Create an environment variable to identify the pools
  • Add upstream configuration to access two different pools

Ninth exercise

Configuring nginx to load balancing PHP-FPM (Solution)

            
                upstream cluster_php {
                    server 127.0.0.1:9001;
                    server 127.0.0.1:9002;
                }
            
        
            
                location ~ php/.*\.php$ {
                    try_files $uri =404;
                    fastcgi_index   index.php;
                    fastcgi_pass    cluster_php;
                    include /etc/nginx/fastcgi_params;
                    fastcgi_param   SCRIPT_FILENAME    $fastcgi_script_name;
                    fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
                }
            
        
http://localhost:8080/php/info.php

HHVM

The virtual machine for PHP

  • Virtual machine based on JIT compilation
  • Run PHP 5.4+ or Hack code
  • Developed by Facebook
  • Can be use with FCGI-enabled webserver
http://hhvm.com/

HHVM

HipHop features

  • Available for *nix systems (Linux/OS X) Windows support in development
  • Extension for major databases connection available
  • Extensions can be written using PHP/C++ or both

Tenth exercise

Installing HHVM

Follow the instructions you can find on HHVM wiki page
            
                wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -
                echo deb http://dl.hhvm.com/ubuntu trusty main | sudo tee /etc/apt/sources.list.d/hhvm.list
                sudo apt-get update
                sudo apt-get -y install hhvm
                sudo /usr/share/hhvm/install_fastcgi.sh
                sudo /etc/init.d/hhvm restart
            
        

Eleventh exercise

Configuring HHVM

  • Create a new folder hhvm in /vagrant/www
  • Add a PHP file inside it
  • Configure in your virtual host the access to that folder using the HHVM server

Eleventh exercise

Configuring HHVM (Solution)

            
                location ~ hhvm/.*\.(hh|php)$ {
                    fastcgi_keep_conn on;
                    fastcgi_pass   127.0.0.1:9000;
                    fastcgi_index  index.php;
                    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include        fastcgi_params;
                }
            
        
            
                sudo /usr/share/hhvm/install_fastcgi.sh
                sudo /etc/init.d/hhvm restart
                sudo /etc/init.d/nginx restart
            
        

Bonus Exercise

Image filter configuration

  • Configure a location to resize images on fly
  • The URL should be something like (width)/(height)/(image file)
  • Check image filter documentation for more information
  • Image quality should be set to 75

Bonus Exercise

Image filter configuration (Solution)

            
                location ~ img/(?<width>[0-9]+)/(?<height>[0-9]+)/(?<filename>.*) {
                    alias /vagrant/www/$filename;
                    image_filter resize $width $height;
                    image_filter_jpeg_quality 75;
                }