Complete guide to Install LEMP with Pagespeed, FastCGI and Naxsi on Ubuntu 16.04

share on:
Install lemp on Ubuntu 16.04

NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. we will Install lemp on Ubuntu 16.04 on our server.

NGINX accelerates content and application delivery, improves security, facilitates availability and scalability for the busiest websites on the Internet.

NGINX is one of a handful of servers written to address the C10K problem. Click here to know more about the C10K problem.

Compiling Nginx with various third party modules requires many steps. Here’s a brief summary of all the steps we will take in this tutorial.

Let’s begin with Backing up of previous Nginx configuration.

 

STEP 1. Backup Previous nginx configuration.

Take a backup of your old Nginx configuration, If you’ve already installed Nginx before removing any previous installation of nginx.

shell> cd /etc/nginx
shell> tar -czvf /root/nginx-dir-org-backup.tar.gz *
shell> sudo apt remove nginx nginx-common nginx-full

 

First of all, Download  the important Packages.

shell> sudo apt-get install libgoogle-perftools-dev libgeoip-dev unzip wget curl -y

 

 

Step 2. Download Latest nginx on Ubuntu 16.04.

We will install latest Nginx-1.11.4 from their official Repository.

  • Install GPG key for Nginx.
shell> wget http://nginx.org/keys/nginx_signing.key

shell> sudo apt-key add nginx_signing.key

 

  • Add following lines at the end of /etc/apt/sources.list file/.
shell> echo "deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx" >>  /etc/apt/sources.list
shell> echo "deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx" >>  /etc/apt/sources.list
shell> sudo apt-get update

 

Now we can download latest Nginx package later .

 

  • Make a new directory named nginx directory within the home directory. we will use it to store the Nginx sources.
shell> mkdir -p /usr/share/nginx && cd /usr/share/nginx

 

  • We will install a package named dpkg-dev. This package provides the development tools required to build and upload Debian source packages.
root@debyum:/usr/share/nginx# sudo apt install dpkg-dev

 

Download Nginx source.

root@debyum:/usr/share/nginx# sudo apt source nginx

 

List of downloaded files.

shell> ls  /usr/share/nginx/
Output:
drwxr-xr-x 10 root root   4096 Sep 28 17:47 nginx-1.11.4
-rw-r--r--  1 root root 133672 Sep 13 16:47 nginx_1.11.4-1~xenial.debian.tar.xz
-rw-r--r--  1 root root   1843 Sep 13 16:47 nginx_1.11.4-1~xenial.dsc
-rw-r--r--  1 root root 949793 Sep 13 16:46 nginx_1.11.4.orig.tar.gz

 

Nginx version here is 1.11.4 (stable). It can be different on your server like 1.11.5 or 6 depending on the latest release at that time.

 

STEP 3. Add Modules in Nginx

We will add few useful third party modules in our Nginx Build.

  • Pagespeed
  • Naxsi Web Application Firewall
  • NGINX_CACHE_PURGE module

Create a Directory to store downloaded modules.

Create a directory to store third party modules which we will download later. we will create a directory named “modules” within /usr/share/nginx .

shell> mkdir /usr/share/nginx/modules && cd /usr/share/nginx/modules

 

Make sure you’re in the right directory.

root@debyum:/usr/share/nginx/modules# pwd
/usr/share/nginx/modules

 

Now Start downloading Modules.

 

************ Download NGINX_CACHE_PURGE module  ************

Nginx module which adds the ability to purge content from FastCGI, proxy, SCGI and uWSGI caches. 
wget https://github.com/FRiCKLE/ngx_cache_purge/archive/master.zip -O nginx_purge_module.zip 
unzip nginx_purge_module.zip

 

 

************ Download NAXSI FIREWALL for NGINX  ************

NAXSI means Nginx Anti XSS & SQL Injection.

It is a third party nginx module, available as a package for many UNIX-like platforms. Nginx with NAXSI can operate as a high-performance standalone WAF.

wget https://github.com/nbs-system/naxsi/archive/master.zip -O naxsi.zip 
unzip naxsi.zip

 

 

************ Download PAGESPEED module for NGINX   ************

The PageSpeed module is an open-source server module that optimizes your site. It automatically applies chosen filters to pages and associated assets, such as style sheets, JavaScript, and HTML files, as well as to images and website cache requirements. To know more about PageSpeed, click here.

NPS_VERSION=1.11.33.4;
wget https://github.com/pagespeed/ngx_pagespeed/archive/release-${NPS_VERSION}-beta.zip -O release-${NPS_VERSION}-beta.zip
unzip release-${NPS_VERSION}-beta.zip
cd ngx_pagespeed-release-${NPS_VERSION}-beta/
wget https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}.tar.gz
tar -xzvf ${NPS_VERSION}.tar.gz

 

A view of modules directory:

root@debyum:/usr/share/nginx/modules/ngx_pagespeed-release-1.11.33.4-beta# cd /usr/share/nginx/modules
root@debyum:/usr/share/nginx/modules# ls -l
total 384
drwxr-xr-x 6 root root   4096 Sep 16 14:56 naxsi-master
-rw-r--r-- 1 root root 218174 Sep 28 17:53 naxsi.zip
-rw-r--r-- 1 root root  16771 Sep 28 17:53 nginx_purge_module.zip
drwxr-xr-x 3 root root   4096 Dec 23  2014 ngx_cache_purge-master
drwxr-xr-x 6 root root   4096 Sep 28 17:50 ngx_pagespeed-release-1.11.33.4-beta
-rw-r--r-- 1 root root 136753 Sep 28 17:49 release-1.11.33.4-beta.zip

 

 

STEP 4. Compile Nginx.

Also, Add these Modules in Compilation Rules of Nginx.

We need to edit our  /usr/share/nginx/nginx-1.11.4/debian/rules  file and also add these lines into it.

root@debyum:/usr/share/nginx/modules# cd /usr/share/nginx/nginx-1.11.4/
root@debyum:/usr/share/nginx/nginx-1.11.4/#
root@debyum:/usr/share/nginx/nginx-1.11.4# vi debian/rules

 

Lines we need to add are as follows.

--add-module=/usr/share/nginx/modules/naxsi-master/naxsi_src/ \
--add-module=/usr/share/nginx/modules/ngx_pagespeed-release-1.11.33.4-beta \
--add-module=/usr/share/nginx/modules/ngx_cache_purge-master

 

Here’s how to do it.

Install lemp on Ubuntu 16.04

 

UPDATE:

In addition, for Nginx version 1.11.5 , Add modules in the section config.env.nginx. like shown in this image below.

 

Install lemp on Ubuntu 16.04
Nginx 1.11.5 edit ubuntu 16.04 rules

 

Again making sure we are in the right directory.

root@debyum:/usr/share/nginx/nginx-1.11.4# pwd
/usr/share/nginx/nginx-1.11.4
root@debyum:/usr/share/nginx/nginx-1.11.4# ls -l
total 712
drwxr-xr-x  6 root root   4096 Sep 28 17:47 auto
-rw-r--r--  1 root root 267603 Sep 13 15:39 CHANGES
-rw-r--r--  1 root root 407789 Sep 13 15:39 CHANGES.ru
drwxr-xr-x  2 root root   4096 Sep 28 17:47 conf
-rwxr-xr-x  1 root root   2481 Sep 13 15:39 configure
drwxr-xr-x  4 root root   4096 Sep 28 17:47 contrib
drwxr-xr-x 13 root root   4096 Sep 28 18:41 debian
drwxr-xr-x  2 root root   4096 Sep 28 17:47 html
-rw-r--r--  1 root root   1397 Sep 13 15:39 LICENSE
-rw-r--r--  1 root root    325 Sep 28 18:09 Makefile
drwxr-xr-x  2 root root   4096 Sep 28 17:47 man
drwxr-xr-x  4 root root   4096 Sep 28 18:12 objs
-rw-r--r--  1 root root     49 Sep 13 15:39 README
drwxr-xr-x  9 root root   4096 Sep 28 17:47 src

root@debyum:/usr/share/nginx/nginx-1.11.4/# sudo apt build-dep nginx

 

Finally, everything is now ready for compilation.

 

IMPORTANT: For server’s with 512 MB RAM : Create Swap Space

we need to make sure we have enough memory for compilation process.

For server’s with 512 MB RAM, you need to add more swap space for compilation process.

root@debyum:/usr/share/nginx/nginx-1.11.4/# cd ..
root@debyum:/usr/share/nginx# sudo install -o root -g root -m 0600 /dev/null /tmp-swap
root@debyum:/usr/share/nginx# dd if=/dev/zero of=/tmp-swap bs=1M count=1024 
root@debyum:/usr/share/nginx# mkswap /tmp-swap 
root@debyum:/usr/share/nginx# swapon /tmp-swap 
root@debyum:/usr/share/nginx# echo "/tmp-swap swap swap auto 0 0" | sudo tee -a /etc/fstab 
root@debyum:/usr/share/nginx# sudo sysctl -w vm.swappiness=10

This will add a swap space of 1 GB in a minute. you can delete it if you want after this setup.

 

STEP 5: Build and install Nginx.

Building Deb Package for Nginx.

shell> sudo dpkg-buildpackage -b

 

It’s a lengthy process and usually takes 10-20 minutes to finish.

 

After it finishes compiling let’s take a look at the /usr/share/nginx directory.

 

root@debyum:/usr/share/nginx# ls -l
total 42164
drwxr-xr-x  2 root root     4096 Sep 28 18:16 html
drwxr-xr-x  5 root root     4096 Sep 28 17:53 modules
drwxr-xr-x 11 root root     4096 Sep 28 18:06 nginx-1.11.4
-rw-r--r--  1 root root     2900 Sep 28 18:15 nginx_1.11.4-1~xenial_amd64.changes
-rw-r--r--  1 root root  7540258 Sep 28 18:14 nginx_1.11.4-1~xenial_amd64.deb
-rw-r--r--  1 root root   133672 Sep 13 16:47 nginx_1.11.4-1~xenial.debian.tar.xz
-rw-r--r--  1 root root     1843 Sep 13 16:47 nginx_1.11.4-1~xenial.dsc
-rw-r--r--  1 root root   949793 Sep 13 16:46 nginx_1.11.4.orig.tar.gz
-rw-r--r--  1 root root 34364586 Sep 28 18:15 nginx-dbg_1.11.4-1~xenial_amd64.deb
-rw-r--r--  1 root root    11584 Sep 28 18:15 nginx-module-geoip_1.11.4-1~xenial_amd64.deb
-rw-r--r--  1 root root    14982 Sep 28 18:15 nginx-module-image-filter_1.11.4-1~xenial_amd64.deb
-rw-r--r--  1 root root    94202 Sep 28 18:15 nginx-module-njs_1.11.4.0.1.2-1~xenial_amd64.deb
-rw-r--r--  1 root root    24230 Sep 28 18:15 nginx-module-perl_1.11.4-1~xenial_amd64.deb
-rw-r--r--  1 root root    13132 Sep 28 18:15 nginx-module-xslt_1.11.4-1~xenial_amd64.deb

 

We only need to install  nginx_1.11.4-1~xenial_amd64.deb package .

For 32-bit system, your package name will be  nginx_1.11.4.1~xenial_i386.deb

 

Also, you can  install some additional modules from this directory for e.g:

nginx-module-geoip_1.11.4-1~xenial_amd64.deb.

 

We can install any .deb package using dpkg with -i flag. Take a closer look at directory ( /usr/share/nginx ).

root@debyum:/usr/share/nginx# cd /usr/share/nginx
root@debyum:/usr/share/nginx# dpkg -i nginx_1.11.4-1~xenial_amd64.deb

 

Also, start the nginx service.

root@debyum:/usr/share/nginx# sudo systemctl start nginx

 

In addition, enable Nginx service to start automatically at reboot.

root@debyum:/usr/share/nginx# sudo systemctl enable nginx

 

Check nginx version.

root@debyum:/usr/share/nginx# nginx -v
nginx version: nginx/1.11.4

 

Check Nginx Configuration arguments used while compiling Nginx.

root@debyum:/usr/share/nginx# nginx -V
.....
.... --add-module=/usr/share/nginx/modules/naxsi-master/naxsi_src --add-module=/usr/share/nginx/modules/ngx_pagespeed-release-1.11.33.4-beta --add-module=/usr/share/nginx/modules/ngx_cache_purge-master

 

The --add-module line shows that NAXSI, Pagespeed and NGINX_CACHE_PURGE module has been successfully installed.

 

In the Next Page, we will Discuss in Detail about how to enable and configure Pagespeed, NAXSI WAF & FastCGI cache with Examples.

 

STEP 6. Configure Pagespeed for Nginx.

PageSpeed is  disabled by default. To configure it, we will create a pagespeed.conf file and then put our pagespeed configuration in that file. After that, we will include that file in our main configuration. This method allows us flexibility and ease while dealing with Nginx configuration.

So, Follow these steps one by one.

1: Create  a folder for Storing Pagespeed cache data.

shell> mkdir -p /var/cache/pagespeed_cache

 

2: Change the ownership

Change the ownership of pagespeed_cache to Nginx user.For example,change it to www-data or apache so that it can be written by Nginx.

check nginx.conf -> user    www-data;

shell> chown -R www-data:www-data /var/cache/pagespeed_cache

 

3: Create a configuration file for PageSpeed.

Here’s an example configuration file for pagespeed.

vi /etc/nginx/pagespeed.conf
    # Pagespeed main settings

    pagespeed on;

    # Needs to exist and be writable by nginx.
    pagespeed FileCachePath /var/cache/pagespeed_cache;

    pagespeed RespectVary on;
    pagespeed LowercaseHtmlNames on;

    # optional
    pagespeed XHeaderValue "Using ngx_pagespeed";

    # filter
    pagespeed RewriteLevel PassThrough;

    # image
    pagespeed EnableFilters rewrite_images,responsive_images_zoom;

    # css
    pagespeed EnableFilters inline_import_to_link;
    pagespeed EnableFilters outline_css;
    pagespeed CssOutlineMinBytes 1000;
    pagespeed EnableFilters combine_css,rewrite_css,rewrite_style_attributes,flatten_css_imports,prioritize_critical_css,sprite_images;
    
    # js
    pagespeed EnableFilters rewrite_javascript,combine_javascript;
    pagespeed UseExperimentalJsMinifier on;
    pagespeed EnableFilters insert_dns_prefetch;

    pagespeed EnableFilters remove_comments;
    pagespeed EnableFilters collapse_whitespace;
    pagespeed EnableFilters elide_attributes;
    pagespeed EnableFilters extend_cache;
    pagespeed EnableFilters trim_urls;

    pagespeed EnableFilters local_storage_cache;

 

4. Include pagespeed.conf  in server{} block of main nginx configuration file (/etc/nginx/nginx.conf) .

server {
    listen 80;
    server_name www.example.com  example.com;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 302 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2 default_server;
    # listen [::]:443 ssl http2 default_server;

    include /etc/nginx/conf-available/ssl.conf;

    include /etc/nginx/pagespeed.conf;

 

Finally, Check the working of Nginx Pagespeed Module.

root@debyum:/etc/nginx# curl -X GET -I http://45.5x.xx.xxx
HTTP/1.1 200 OK
Server: nginx/1.11.5
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Date: Sun, 13 Nov 2016 09:32:01 GMT
X-Page-Speed: Using ngx_pagespeed
Cache-Control: max-age=0, no-cache

 

 

STEP 7. Configure Naxsi for Nginx.

1: First of all, we will create a separate folder for Naxsi.

 shell> mkdir -p /etc/nginx/naxsi

 

2: Copy the naxsi_core.rules into the newly created Naxsi folder.

root@debyum:/etc/nginx# find / -type f -name 'naxsi_core.rules'
 /usr/share/nginx/modules/naxsi-master/naxsi_config/naxsi_core.rules

root@debyum:/etc/nginx# cp /usr/local/src/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/

 

3: Also create a naxsi.rules file.

 vi /etc/nginx/naxsi/naxsi.rules
 LearningMode;
 SecRulesEnabled;
 #SecRulesDisabled;
 DeniedUrl "/RequestDenied";

## Check & Blocking Rules
 CheckRule "$SQL >= 8" BLOCK;
 CheckRule "$RFI >= 8" BLOCK;
 CheckRule "$TRAVERSAL >= 4" BLOCK;
 CheckRule "$EVADE >= 4" BLOCK;
 CheckRule "$XSS >= 8" BLOCK;

include /etc/nginx/naxsi/naxsi_relax.rules;

 

While in learning mode, Naxsi won’t block any requests. It can also be used to configure an attack pattern auto-learn mechanism inside Naxsi.

SecRulesEnabled enables the Naxsi Secure Rules.

DeniedUrl “/RequestDenied” be the returned URL while blocking.

 

Create Whitelisting Rules for allowing legitimate traffic

4: Create a naxsi_relax.rules files.
To prevent Default Naxsi rules from blocking some legitimate traffic on your site we will use a list of rules to allow legitimate traffic without any problem.

In addition, Here are Whitelist rules for WordPress. for more check https://github.com/nbs-system/naxsi-rules/blob/master/wordpress.rules

 

vi /etc/nginx/naxsi/naxsi_relax.rules
 # WordPress naxsi rules

### HEADERS
 BasicRule wl:1000,1001,1005,1007,1010,1011,1013,1100,1101,1200,1308,1309,1310,1311,1315 "mz:$HEADERS_VAR:cookie";
 # xmlrpc
 BasicRule wl:1402 "mz:$HEADERS_VAR:content-type";

simple BODY (POST)
 BasicRule wl:1001,1015,1009,1311,1310,1101,1016 "mz:$URL:/|$BODY_VAR:customized";


 # comments
 BasicRule wl:1000,1010,1011,1013,1015,1200,1310,1311 "mz:$BODY_VAR:post_title";
 BasicRule wl:1000 "mz:$BODY_VAR:original_publish";
 BasicRule wl:1000 "mz:$BODY_VAR:save";
 BasicRule wl:1008,1010,1011,1013,1015 "mz:$BODY_VAR:sk2_my_js_payload";
 BasicRule wl:1001,1009,1005,1016,1100,1101,1310 "mz:$BODY_VAR:url";
 BasicRule wl:1009,1100,1101 "mz:$BODY_VAR:referredby";
 BasicRule wl:1009,1100,1101 "mz:$BODY_VAR:_wp_original_http_referer";
 BasicRule wl:1000,1001,1005,1008,1007,1009,1010,1011,1013,1015,1016,1100,1101,1200,1302,1303,1310,1311,1315,1400 "mz:$BODY_VAR:comment";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:redirect_to";
 BasicRule wl:1000,1009,1315 "mz:$BODY_VAR:_wp_http_referer";
 BasicRule wl:1000 "mz:$BODY_VAR:action";
 BasicRule wl:1001,1013 "mz:$BODY_VAR:blogname";
 BasicRule wl:1015,1013 "mz:$BODY_VAR:blogdescription";
 BasicRule wl:1015 "mz:$BODY_VAR:date_format_custom";
 BasicRule wl:1015 "mz:$BODY_VAR:date_format";
 BasicRule wl:1015 "mz:$BODY_VAR:tax_input%5bpost_tag%5d";
 BasicRule wl:1015 "mz:$BODY_VAR:tax_input[post_tag]";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:siteurl";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:home";
 BasicRule wl:1000,1015 "mz:$BODY_VAR:submit";


 # news content matches pretty much everything
 BasicRule wl:0 "mz:$BODY_VAR:content";
 BasicRule wl:1000 "mz:$BODY_VAR:delete_option";
 BasicRule wl:1000 "mz:$BODY_VAR:prowl-msg-message";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:_url";
 BasicRule wl:1001,1009 "mz:$BODY_VAR:c2c_text_replace%5btext_to_replace%5d";
 BasicRule wl:1200 "mz:$BODY_VAR:ppn_post_note";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:author";
 BasicRule wl:1001,1015 "mz:$BODY_VAR:excerpt";
 BasicRule wl:1015 "mz:$BODY_VAR:catslist";
 BasicRule wl:1005,1008,1009,1010,1011,1015,1315 "mz:$BODY_VAR:cookie";
 BasicRule wl:1101 "mz:$BODY_VAR:googleplus";
 BasicRule wl:1007 "mz:$BODY_VAR:name";
 BasicRule wl:1007 "mz:$BODY_VAR:action";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:attachment%5burl%5d";
 BasicRule wl:1100,1101 "mz:$BODY_VAR:attachment_url";
 BasicRule wl:1001,1009,1100,1101,1302,1303,1310,1311 "mz:$BODY_VAR:html";
 BasicRule wl:1015 "mz:$BODY_VAR:title";
 BasicRule wl:1001,1009,1015 "mz:$BODY_VAR:recaptcha_challenge_field";
 BasicRule wl:1011 "mz:$BODY_VAR:pwd";
 BasicRule wl:1000 "mz:$BODY_VAR:excerpt";

### BODY|NAME
 BasicRule wl:1000 "mz:$BODY_VAR:delete_option|NAME";
 BasicRule wl:1000 "mz:$BODY_VAR:from|NAME";

Simple ARGS (GET)
 # WP login screen
 BasicRule wl:1100,1101 "mz:$ARGS_VAR:redirect_to";
 BasicRule wl:1000,1009 "mz:$ARGS_VAR:_wp_http_referer";
 BasicRule wl:1000 "mz:$ARGS_VAR:wp_http_referer";
 BasicRule wl:1000 "mz:$ARGS_VAR:action";
 BasicRule wl:1000 "mz:$ARGS_VAR:action2";


 # load and load[] GET variable
 BasicRule wl:1000,1015 "mz:$ARGS_VAR:load";
 BasicRule wl:1000,1015 "mz:$ARGS_VAR:load[]";
 BasicRule wl:1015 "mz:$ARGS_VAR:q";
 BasicRule wl:1000,1015 "mz:$ARGS_VAR:load%5b%5d";

URL
 BasicRule wl:1000 "mz:URL|$URL:/wp-admin/update-core.php";
 BasicRule wl:1000 "mz:URL|$URL:/wp-admin/update.php";
 BasicRule wl:1000 "mz:$URL:/wp-includes/js/imgareaselect/imgareaselect.css|URL";
 BasicRule wl:1002 "mz:$URL_X:/wp-content/uploads/[0-9]{4}/[0-9]{2}/[^/]+\.jpg$|URL";


 # URL|ARGS
 BasicRule wl:1015 "mz:$URL:/wp-admin/load-styles.php|$ARGS_VAR:dashicons,admin-bar,wp-admin,buttons,wp-auth-check";
 BasicRule wl:1000 "mz:$URL:/wp-admin/about.php|$ARGS_VAR:updated";
 BasicRule wl:1009 "mz:$URL:/wp-admin/customize.php|$ARGS_VAR:return";


 # URL|BODY
 BasicRule wl:1009,1100,1101 "mz:$URL:/wp-admin/post.php|$BODY_VAR:_wp_http_referer";
 BasicRule wl:1016 "mz:$URL:/wp-admin/post.php|$BODY_VAR:metakeyselect";
 BasicRule wl:11 "mz:$URL:/xmlrpc.php|BODY";
 BasicRule wl:11,16 "mz:$URL:/wp-cron.php|BODY";
 BasicRule wl:2 "mz:$URL:/wp-admin/async-upload.php|BODY";


 # URL|BODY|NAME
 BasicRule wl:1100,1101 "mz:$URL:/wp-admin/post.php|$BODY_VAR:_wp_original_http_referer|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/post.php|$BODY_VAR:metakeyselect|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/user-edit.php|$BODY_VAR:from|NAME";
 BasicRule wl:1100,1101 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:attachment%5burl%5d|NAME";
 BasicRule wl:1100,1101 "mz:$URL:/wp-admin/post.php|$BODY_VAR:attachment_url|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/plugins.php|$BODY_VAR:verify-delete|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/post.php|$BODY_VAR:post_category[]|NAME";
 BasicRule wl:1311 "mz:$URL:/wp-admin/post.php|$BODY_VAR:post_category|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/post.php|$BODY_VAR:tax_input[post_tag]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/post.php|$BODY_VAR:newtag[post_tag]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/users.php|$BODY_VAR:users[]|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/update-core.php|$BODY_VAR:Update%2BTranslations|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/update-core.php|$BODY_VAR:Update%2BNow|NAME";


 # URL|ARGS|NAME
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/load-scripts.php|$ARGS_VAR:load[]|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/users.php|$ARGS_VAR:delete_count|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/users.php|$ARGS_VAR:update|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/customize.php|$ARGS_VAR:autofocus[control]|NAME";

# plain WP site
 BasicRule wl:1000 "mz:URL|$URL:/wp-admin/update-core.php";
 BasicRule wl:1000 "mz:URL|$URL:/wp-admin/update.php";


 # URL|BODY
 BasicRule wl:1009,1100,1101 "mz:$URL:/wp-admin/post.php|$BODY_VAR:_wp_http_referer";
 BasicRule wl:1016 "mz:$URL:/wp-admin/post.php|$BODY_VAR:metakeyselect";
 BasicRule wl:11 "mz:$URL:/xmlrpc.php|BODY";
 BasicRule wl:11,16 "mz:$URL:/wp-cron.php|BODY";


 # URL|BODY|NAME
 BasicRule wl:1100,1101 "mz:$URL:/wp-admin/post.php|$BODY_VAR:_wp_original_http_referer|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/post.php|$BODY_VAR:metakeyselect|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/user-edit.php|$BODY_VAR:from|NAME";
 BasicRule wl:1100,1101 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:attachment%5burl%5d|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:data[wp-auth-check]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:data[wp-check-locked-posts][]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:data[wp-refresh-post-lock][post_id]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/admin-ajax.php|$BODY_VAR:data[wp-refresh-post-lock][lock]|NAME";
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/update-core.php|$BODY_VAR:checked[]|NAME";


 # URL|ARGS|NAME
 BasicRule wl:1310,1311 "mz:$URL:/wp-admin/load-scripts.php|$ARGS_VAR:load[]|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/users.php|$ARGS_VAR:delete_count|NAME";
 BasicRule wl:1000 "mz:$URL:/wp-admin/users.php|$ARGS_VAR:update|NAME";

Plugins
 #WP Minify
 BasicRule wl:1015 "mz:$URL:/wp-content/plugins/bwp-minify/min/|$ARGS_VAR:f";

 

5: Include this inside the http{} block in your nginx.conf file .

Add this to the first line:

http {
 include      /etc/nginx/naxsi_core.rules;
 include       mime.types;
 ...
 ...
 ...
 }

 

5: Add Location Block for Naxsi in the server {} section of Main Nginx configuration.

 ....
 .....
 location / {
 include           /etc/nginx/naxsi/naxsi.rules;
 ....
 ....
 }

location /RequestDenied {
 return 406;
 }

 

Now Naxsi is configured and is in Learning mode. To disable learning mode LearningMode

 vi /etc/nginx/naxsi/naxsi.rules
 # LearningMode;

 

 

STEP 8. Configure FastCGI Cache.

 

To enable FastCGI cache  we will add these lines inside the http {} block section in nginx main config file.

 

http { 

    .......
   fastcgi_cache_path /var/cache/ngx_fastcgi levels=1:2 keys_zone=fastcgi_cache:10m inactive=10m max_size=64m;
    fastcgi_cache_key $scheme$request_method$host$request_uri;
    fastcgi_cache_lock on;
    fastcgi_cache_use_stale error timeout invalid_header updating http_500;
    fastcgi_cache_valid 5m;
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

 

The fastcgi_cache_path directive defines the location of the cache.

levels define the subdirectory levels.

fastcgi_cache defines the name of memory zone.

It’s maximum size 64mb and the inactive time.

max_size must be less than your server’s Total  RAM + Swap.

 

Integrate the FastCGI cache with PHP-FPM.

Also, Add these lines inside the server {} block of your Nginx configuration file.

 

    location ~\.php$ {

    set $fastcgi_skipcache 0;
 
 
        if ($http_x_custom_header) {
            set $fastcgi_skipcache 0;
        }
 
        # Don't cache the following URL's
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
            set $fastcgi_skipcache 1;
        }   

        # Don't use the cache for logged in users or recent commenters
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
            set $fastcgi_skipcache 1;
        }

        #Don't cache if there is a cookie called PHPSESSID
        if ($http_cookie = "PHPSESSID")
        {
            set $fastcgi_skipcache 1;
        }

        # Bypass cache for POST requests
        if ($request_method = POST) { 
            set $fastcgi_skipcache 1; 
        }

        # Bypass cache for URL with query string
        if ($query_string != "")  { 
            set $fastcgi_skipcache 1; 
        }
 
        if ($http_cookie ~ "users_login_cookie") {
            set $fastcgi_skipcache 1;
        }


        include fastcgi_params;
        include fastcgi.conf;

        fastcgi_cache fastcgi_cache;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_methods GET HEAD;

        # note: adds a HTTP response header "X-Cache" returning HIT/MISS/BYPASS/EXPIRED for cache use status
        add_header X-Fastcgi-Cache $upstream_cache_status;
        fastcgi_cache_bypass $fastcgi_skipcache;
        fastcgi_no_cache $fastcgi_skipcache;

        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 4k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_index index.php;
        fastcgi_pass    127.0.0.1:9000;
    }

 

 

Also, Check the nginx configuration file for syntax errors.

[root@debyum nginx]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

 

Finally, Test the working of FastCGI cache.

root@debyum:~# curl -X GET -I http://45.55.64.233/hello.php
HTTP/1.1 200 OK
Server: nginx/1.11.4
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Fastcgi-Cache: HIT
Date: Sun, 13 Nov 2016 12:16:13 GMT
X-Page-Speed: Using ngx_pagespeed
Cache-Control: max-age=0, no-cache

 

Now that we have installed and configured Nginx with Pagespeed, NAXSI WAF, and FastCGI Cache we will install MySQL and PHP-FPM  on the next page to finish this LEMP Setup.

 

 

STEP 9. Install MySQL.

Use the following commands to install MySQL

root@debyum:~# sudo apt-get install mysql-server -y

 

Start Mysql server and also enable it to start at reboot.

root@debyum:~# systemctl enable mysql.service
root@debyum:~# systemctl start mysql.service

 

 

Securing the Database Server.

In addition, We also need to secure the Database server by running this script ( mysql_secure_installation ) in the shell.

root@debyum:~# mysql_secure_installation
Securing the MySQL server deployment.

Enter password for user root: 

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No: k
Using existing password for root.
Change the password for root ? ((Press y|Y for Yes, any other key for No) : k

 ... skipping.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

 

If you want to stop MySQL service use,

root@debyum:~# systemctl stop mysql.service

 

 

STEP 10. Install PHP-FPM

PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites.

Install PHP with following command:

shell> sudo apt-get install php7.0 php7.0-fpm php7.0-mysql

 

Change the value of cgi.fix_pathinfo=1 to 0 in php.ini.

Open php.ini file in any editor:

root@debyum:~# php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/7.0/cli
Loaded Configuration File => /etc/php/7.0/cli/php.ini

 

shell> vi /etc/php/7.0/cli/php.ini
cgi.fix_pathinfo=0

 

 

Enable PHP-FPM service.

root@debyum:~# systemctl list-unit-files | grep php
php7.0-fpm.service enabled
root@debyum:~# sudo systemctl enable php7.0-fpm.service 
root@debyum:~# sudo systemctl start php7.0-fpm.service

 

Also, To check the status of php7.0-fpm.service, use the command:

root@debyum:~# sudo systemctl status php7.0-fpm.service 
 php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager
 Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled)
 Active: active (running) since Sun 2016-11-13 10:42:32 UTC; 34s ago
 Main PID: 26938 (php-fpm7.0)
 Status: "Processes active: 0,root@ubuntu-2gb-nyc3-01:~# php -v
PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
 with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
 CGroup: /system.slice/php7.0-fpm.service
 ├─26938 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf) 
 ├─26942 php-fpm: pool www 
 └─26943 php-fpm: pool www

Nov 13 10:42:32 debyum systemd[1]: Stopped The PHP 7.0 FastCGI Process Manager.
Nov 13 10:42:32 debyum systemd[1]: Starting The PHP 7.0 FastCGI Process Manager...
Nov 13 10:42:32 debyum systemd[1]: Started The PHP 7.0 FastCGI Process Manager.

 

Finally, Check PHP Version.

root@debyum:~# php -v
PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
 with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies

 

 

Conclusion

With LAMP stack installed, you can now install different types of applications or CMS or run a simple website on your server.

I have tried to cover all the basic to advance concepts like NAXSI, PageSpeed and FastCGI cache with their examples. Still, if I have missed anything please update us through comment box. I will keep updating the same based on feedback’s received.Thanks and a Great DAY.

 

share on:
engy

engy

Hello there, My name is Rishi Guleria and I work as a Linux system administrator. I have created this blog to share what I have learned so far and to learn new things. Good Day. :)

1 Comment

  1. ive been trying for a few hours with this now with no luck, Im trying the setup on a fresh ubuntu 16.04 updated and upgraded. I can get nginx installed with page speed, header show pagespeed ngx and nginx. the problem comes with php. I follow the install from above and everything seems to go ok. no errors from nginx or php. the problem come when i try to open a php page from a web browser. it does not render the page it asks to download and save the php file. its not very clear in the guide on the location of the nginx.conf files. Im finding these all over the server. Step 6 section 4. Include pagespeed.conf in server{} block of main nginx configuration file (/etc/nginx/nginx.conf) .

    As this server is fresh there is no server block within the /etc/nginx/nginx.conf

    been trying to get pagespeed to work with a full server setup for about 1 week now. using you method has come the closest. im not giving up.

Leave a Response

share on: