Magento Performance: Nginx Installation

Nginx web server is an amazing solution for high loaded web resources.

Nginx powers many high-visibility sites, such as Facebook, Netflix, Hulu, Pinterest, WordPress.com, Instagram, Groupon, Zappos, etc. Today 100 Million sites run Nginx.

In this article we will configure production server for a single domain, working on Nginx only with fast PHP process manager (PHP-FPM) and MySQL. Operating system is Linux CentOS 6. Also you will find here Magento compatible Nginx configuration.

So, first of all let’s make sure we have no Apache in our environment.

Disable Apache run on server boot

# service httpd stop
# chkconfig --levels 2345 httpd off

Or simply remove it including old PHP engine

# yum remove httpd* php*

Adding the remi and epel repositories

# yum install yum-priorities -y
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

Conducting nginx installation

# yum install nginx

Configuring the nginx service to start after the reboots

# chkconfig --level 345 nginx on

Web user

Our web user is www-data. Don’t forget to add it to your system.

# groupadd www-data
# useradd  -d /var/www/html -G www-data www-data

The web files and web directories should belong to this user

# cd /var/www/html
chown -R www-data:www-data .  

PHP-FPM Installation

Installing PHP-FPM and it’s modules from remi repository

# yum --enablerepo=remi install php php-fpm php-gd php-mysql php-mbstring php-xml php-mcrypt

Configuring PHP-FPM to launch automatically after the server reboot

chkconfig --level 345 php-fpm on

PHP-FPM configuration

We should add the correct web user and it’s group to the /etc/php-fpm.d/www.conf config file. Replace default user and group with ‘www-data’, like this:

; RPM: apache Choosed to be able to access some dir as httpd

user = www-data

; RPM: Keep a group allowed to write in log dir.

group = www-data

Now, open your php.ini file, look for short_open_tag and enable it:

# vi /etc/php.ini

short_open_tag = On

Magento compatible Nginx configuration

Nginx configuration file - nginx.conf, usually located in /etc/nginx/nginx.conf

Here we will configure our domain, PHP-FPM engine, web server properties and so on.

Magento should be installed into the webroot directory: /var/www/html

Please, do not forget to change your server_name. I’ve marked the important moments, you should check, with bold.

That’s what we need:

# Specify user for the nginx processes
user  www-data; 


worker_processes  2; ## it’s should be equal to your server CPU cores quantity. 


error_log   /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;


pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
    use epoll;
       }


http   {
    index index.html index.php; 
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
        
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
                                          
    #log_format error403  '$remote_addr - $remote_user [$time_local] '
    #                 '$status "$request"  "$http_x_forwarded_for"';                                          
        
    server_tokens       off;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    


    ## Gzip helps to decrease your pages weight
    gzip                on;
    gzip_vary           on;
    gzip_proxied        any;
    gzip_types          text/css application/x-javascript;
    gzip_buffers        16 8k;
    gzip_comp_level     8;
    gzip_min_length     1024;


    #ssl_session_cache shared:SSL:15m;
    #ssl_session_timeout 15m;
   
    keepalive_timeout   10;


    ##server block
        
        server {   
    listen 80; ## Web server port
    #listen 443 ssl;
    server_name [domain_name.com] [www.domain_name.com]; ## Place your domain name here
        
    access_log  /var/log/nginx/access_mydomain.log  main;
    
       #port_in_redirect off; 
        
    ####################################################################################
    ## SSL CONFIGURATION


       #ssl_certificate     /etc/ssl/certs/www_server_com.chained.crt; 
       #ssl_certificate_key /etc/ssl/certs/server.key;


       #ssl_protocols             SSLv3 TLSv1 TLSv1.1 TLSv1.2;
       #http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
       #http://serverfault.com/questions/417512/disable-deflate-compression-in-nginx-ssl
       #ssl_ciphers               AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH;
       #ssl_ciphers               RC4:HIGH:!aNULL:!MD5:!kEDH;
       #ssl_prefer_server_ciphers on;


    ####################################################################################
   
    ## Server maintenance block. insert dev ip 1.2.3.4 static address www.whatismyip.com
    #if ($remote_addr !~ "^(1.2.3.4|1.2.3.4)$") {
        #return 503;
        #}
        
    #error_page 503 @maintenance;        
    #location @maintenance {
        #rewrite ^(.*)$ /error_page/503.html break;
        #internal;
        #access_log off;
        #log_not_found off;
        #}


    ####################################################################################


    ## 403 error log/page
    #error_page 403 /403.html;
    #location = /403.html {
        #root /var/www/html/error_page;
        #internal;
        #access_log   /var/log/nginx/403.log  error403;
        #}


    ####################################################################################
    
    ## Main Magento location
    location / {
        try_files $uri $uri/ @handler;
        }
                
    ####################################################################################
 
    ## These locations would be hidden by .htaccess normally, protected
    location ~ (/(app/|includes/|/pkginfo/|var/|errors/local.xml)|/\.svn/|/.hta.+) {
        deny all;
        #internal;
        }


   ####################################################################################
# This section allows you specify which IP-addresses can access your admin and downloader areas, replace 1.2.3.4 and 1.2.3.5 with your IPs. 
   
    #location /downloader/  {
        #allow 1.2.3.4;
        #allow 1.2.3.5;
        #deny all;
        #rewrite ^/downloader/(.*)$ /downloader/index.php$1;
        #}
    #location /admin  {
        #allow 1.2.3.4;
        #allow 1.2.3.5;
        #deny all;
        #rewrite / /@handler;
        #}   


    ####################################################################################


    ## Images, scripts and styles set far future Expires header
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
        }


    ####################################################################################


    ## Main Magento location
    location @handler {
        rewrite / /index.php;
       }
 
    location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
        rewrite ^(.*.php)/ $1 last;
        }


    ####################################################################################
    
    ## Execute PHP scripts
    location ~ .php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_send_timeout 1800;
        fastcgi_read_timeout 1800;
        fastcgi_connect_timeout 1800;
        ## Store code with multi domain
        #fastcgi_param  MAGE_RUN_CODE $storecode;
        ## Default Store code
        fastcgi_param  MAGE_RUN_CODE default; 
        fastcgi_param  MAGE_RUN_TYPE store; ## or website;
        include        fastcgi_params; ## See /etc/nginx/fastcgi_params
        }
    }
}

Starting nginx server and PHP-FPM

To start nginx server and PHP-FPM launch the following commands

# /etc/init.d/nginx start
# /etc/init.d/php-fpm start

MySQL installation

Launch MySQL installation

# yum install mysql-server

Configuring MySQL to start with other services after the boot

# chkconfig --levels 345 mysqld on

Start MySQL

# /etc/rc.d/init.d/mysqld start

Creating MySQL root user password

# /usr/bin/mysqladmin -u root password '[new_pass]'

Well, the work is almost finished. You can configure your server hostname if it’s necessary: #hostname [domain_name.com]

Upload your files to web root /var/www/html, upload your MySQL dumps and have fun.

Further reading