Nginx Setup – Basic Configuration, Memcache, PHP-FPM

In this blog post we will see how to do basic nginx configuration and setup memcache with it. There are various guides showing how to install nginx so i will not cover that part.

Basic Nginx Configuration

One you have installed nginx the configuration files are located at

/etc/nginx/nginx.conf 
/etc/nginx/conf.d/default.conf

To start of first you need to setup the nginx.conf file, which is a global configuration for all your websites inside nginx.

Below is my configuration file, with explanation is comments. Remove comments in your final config file.

user  nginx;   
#the user under which nginx will run
worker_processes  8;  
#basically no of workers nginx will run. Can be equal to number of cores your server has. 
# but if you require further detailed explanation you can good about it. 

error_log  /var/log/nginx/error.log error;   
#error file location
pid        /var/run/nginx.pid;   
#nginx server pid file


events {
    worker_connections  2048;  
#no of connection nginx will take per worker. In case of low end server set to 1024.
#worker_processes * worker_connections is roughly equal to the total number simultaneous users/connection your #nginx server will handle 
}


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

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request_uri" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    #log format

    access_log  /var/log/nginx/access.log  main;
    #global access log file location

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;
    # keepalive timeout

    tcp_nodelay        on;

    # below are all gzip optmizations i.e to send all responses in gzip compression
    gzip  on;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_proxied any;
    gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
    gzip_buffers 16 8k;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    include /etc/nginx/conf.d/*.conf;
    # location of config files which has further configurations
}

Next we have the default.conf file where will make configuration per website. Will show a very basic config for nginx using php-fpm. I have found it better to use php-fpm that use apache to server php files.

server {
    listen       80;  
#port to list
    server_name  yourdomainname.com;
#user website domain


    access_log  /var/log/nginx/log/yourdomain.access.log  main;
#optional domain specific access log file

    location / {
        root   /home/etech/public_html/yourfiles;
#location of all your files
        index  index.php index.html index.htm;
#default file to server. this is location of your website files
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
#above showing default nginx error pages

#below configuration to server php files
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;

        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_read_timeout 100;   #php timeout variable

        fastcgi_param   PATH_TRANSLATED     $document_root$fastcgi_path_info;
        fastcgi_param   PATH_INFO         $fastcgi_path_info;

        fastcgi_param SCRIPT_FILENAME /home/etech/public_html/yourfiles/$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny  all;
    }
}

For above to work you need to have php-fpm installed as well.

Setting up Basic HTTP Authentication

First you need to create a .htpasswd file, do you using this command

htpasswd -c .htpasswd etech

or you can generate using many online generators.

Next for the folder for which you need authentication write the config below.
Below is for the config for URL www.yourdomain.com/pma

location /pma{
        auth_basic "Restricted";
        auth_basic_user_file /home/etech/.htpasswd;
    }

Setting up Memcache with Nginx

Setting up memcache with nginx is quite tricky, but if integrated properly you will see 100x increase in speed. The most important things to consider while implement memcache with nginx is
1. You cannot put data in memcache using nginx, for that you need to change your application code i.e in php.
2. The nginx generates memcache key based on URL, and since memcache key limit is 256 characters you might get an nginx 400 error in case of long urls. So its better to apply memcache, only to specific url/location instead of whole website.
3. If you have different designs for your mobile and desktop website, but they run on the same urls, you will have to make change to your memcache key based on user agent.
4. Since you won’t want to show cached pages to your logged in customer, you would need to set a cookie for logged in users. So if your using session based login management, you need to change to cookie based. For the below configuration, i am using “auth” cookie during login.

Based on the above here is the configuration below.

    set $cache_flags "-"; 
    #memcache key variable which we will use later

    if ($http_cookie ~* "(auth)" ) {
        set $cache_flags "${cache_flags}A";
    }
    #check if user is logged in, append A to cache_flag

    if ($http_user_agent ~* "(2.0 MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo Wii|Nitro|Nokia|Opera Mini|Palm|PlayStation Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows CE|WinWAP|YahooSeeker/M1A1-R2D2|NF-Browser|iPhone|iPod|Mobile|BlackBerry9530|G-TU915 Obigo|LGE VX|webOS|Nokia5800)" ) {
        set $cache_flags "${cache_flags}Mob";
    }
## check if user is from mobile, add Mob to the cache key
    if ($request_method != GET) {
       set $cache_flags "R";
    }
## if the request is POST or PUT, add R

    if ($request_uri ~* /search) {
       set $cache_flags $request_uri;
    }
## only apply to urls with "search"
    if ($request_uri ~* /catalog) {
       set $cache_flags $request_uri;
    }
## only apply to urls with "catalog"

location ~ \.php$ {
        add_header ng_block_4 true;
## adding this header just for debugging, to see if this block is processed 

        set $memcached_key "$cache_flags";
        memcached_pass 127.0.0.1:11211;
        default_type text/html;
        add_header X-Header-Genie-Cache true;
        add_header X-Header-Genie-Flags $cache_flags;
## above headers to check if page is processed through memcache and what is the cache ##key name
        error_page 404 = @fallback;
## if no memcache key is found, process @fallback location
    }

    location @fallback  {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;

        add_header X-Header-NoCache-Flags $cache_flags;
## if not processed through memcache add this flag in header
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_read_timeout 30000000;

        fastcgi_param   PATH_TRANSLATED     $document_root$fastcgi_path_info;
        fastcgi_param   PATH_INFO         $fastcgi_path_info;

        fastcgi_param SCRIPT_FILENAME /home/etech/public_html/yourfiles/$fastcgi_script_name;
        include        fastcgi_params;
    }

Next you need to set data into memcache in your php code. You need to use REQUEST_URI as memcache key. Rest of the code will depend on your application logic.

$memCacheKey = $_SERVER['REQUEST_URI'];

Nginx Debugging using headers

Nginx config file is divided into block’s based on location. In a large application there might be many location(s) and to debug how the code flows you need to add headers to debug.
E.g below to see if the below rewrite is working or not, I have add ng_block6 header.

location /search/ {
        add_header ng_block_5 true;
        rewrite ^/search/(.*)/(.*)/index.php?query_id=$2 last;
}

Below is a screenshot of the same. You can see this header using firebug or chrome debugger (inspect element).
Untitled

Nginx redirect all www to no-www url

In case you want your domain to always open without www. e.g
www.yourdomain.com to yourdomain.com then use below configuration

## redirect www to nowww
    if ($host = 'www.yourdomain.com' ) {
         rewrite  ^/(.*)$  http://yourdomain.com/$1  permanent;
    } 

Nginx rewrite

In apache you write rewrite in .htaccess files, but in nginx you need to directly write them in the config file itself.

Here are few rewrites below and their translation to nginx config file

.htaccess rewrite

RewriteRule ^search_small/(.*)/(.*)  index.php?query_id=$2&frame=1 [L,NC]

nginx rewrite

location /search_small/ {
       add_header ng_block_11 true;   #just to debug
       rewrite ^/search_small/(.*)/(.*)  /index.php?query_id=$2&frame=1 last;
}

nginx rewrite

location /search/ {
        add_header ng_block_6 true;
        rewrite ^/search/lowest-price-of-(.*)/(.*)  /search/$1/$2 permanent;
    }

as per documentation

last: stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI;
permanent: returns a permanent redirect with the 301 code.

  • guest

    Just to make sure people aren’t hacked immediately after using this, add some lines that block the downloading of the config files… with that setup your local.xml file is available for everyone.