Installing WordPress + W3TotalCache with LEMP on CentOS for Maximum Performance

Nginx is free high performance HTTP web server c, open source, which, unlike some other web servers, does not rely on streaming requests, instead it uses a much more scalable event driven (asynchronous) architecture.

This uses a very small and predictable amount of memory under heavy load. Nginx combined with a simple and very robust FastCGI Process for PHP ( PHP-FPM ) and the most popular database server MySQL can give you a lot of performance using a small amount of memory.

The article is divided into the following sections:

  • Initial setup
  • Installing and configuring Nginx
  • Installing and Configuring MySQL
  • Installing and configuring PHP-FPM
  • Install and configure WordPress
  • Tuning caching for best performance

Before proceeding with the installation, start a session by running:

screen -U -S lemp-stack

Once you are in a screen session, make sure your CentOS is fully up to date by running:

yum update

if you have Apache installed on your VPS, stop it and uninstall it by running the following command:

/etc/init.d/httpd stop
yum remove httpd

STEP 1) Installing and Configuring Nginx

Enable the EPEL repository by running:

You can find out your VPS architecture by running

uname -m

– 32-bit VPS:

wget -P /tmp http://mirror.pnl.gov/epel/6/i386/epel-release-6-8.noarch.rpm
rpm -Uvh /tmp/epel-release-6-8.noarch.rpm
rm -f /tmp/epel-release-6-8.noarch.rpm

– 64-bit VPS:

wget -P /tmp http://mirror.itc.virginia.edu/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -Uvh /tmp/epel-release-6-8.noarch.rpm
rm -f /tmp/epel-release-6-8.noarch.rpm

Install Nginx using the yum command:

yum install nginx

Go to the nginx config directory /etc/nginx/ and edit nginx.conf text editor:

cd /etc/nginx/
vim nginx.conf

user              nginx;
worker_processes  2;

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;
}

http {
    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"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  30;
    server_tokens off;

    gzip on;
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;

    # enabled sites
    include /etc/nginx/sites-enabled/*;

}

Create directories sites-enabled and sites-available inside directory /etc/nginx:

mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled

Configure the default Nginx virtual host directive by adding the following line to the file /etc/nginx/sites-available/default.conf

server {
    listen       80 default_server;
    server_name  _;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page  404              /404.html;
    location = /404.html {
        root   /usr/share/nginx/html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Enable the default nginx virtual host directive by creating a symbolic link to the default config in /etc/nginx/sites-enabled/

cd /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/default.conf

Test Nginx configuration, add it to system startup, and finally start it with:

nginx -t
/etc/init.d/nginx restart
chkconfig nginx on

STEP 2) Installing and Configuring MySQL

Install MySQL database server, start and add it to system startup by running the following commands:

yum install mysql mysql-server
service mysqld restart
chkconfig mysqld on

Then run below command for MySQL to secure installation

## mysql_secure_installation

Enter current password for root (enter for none):
Set root password? [Y/n] y
Remove anonymous users? [Y/n] y
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y

Make sure your MySQL is not being eavesdropped on your server’s public IP by adding the following /etc/my.cnf

vim /etc/my.cnf

[mysqld]
bind-address = 127.0.0.1
...

Restart the database server for the changes to take effect with:

/etc/init.d/mysqld restart

STEP 3) Install and configure PHP-FPM

Install PHP-FPM and some useful PHP extensions by running below command:

yum install php-fpm php-mysql php-gd php-mcrypt

Edit /etc/php.ini and change / uncomment the following:

cgi.fix_pathinfo=0
date.timezone = "your timezone"
memory_limit = 64M
expose_php = Off

Next, edit the config file /etc/php-fpm.conf in your editor and uncomment the following:

emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10

PHP-FPM pool created in /etc/php-fpm.d/www.conf:

mv /etc/php-fpm.d/www.conf /root/
## vim /etc/php-fpm.d/www.conf

[wordpress]
;listen = 127.0.0.1:9001
listen = /var/run/php-wordpress.socket
user = nginx
group = nginx
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/blogcms.log
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 400
listen.backlog = -1
pm.status_path = /status
request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = yes
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
php_admin_value[error_log] = /var/log/php-fpm/wordpress-error.log
php_admin_flag[log_errors] = on

Reload PHP-FPM and add it at system startup:

/etc/init.d/php-fpm restart
chkconfig php-fpm on

At this point, you must have Nginx , MySQL and PHP-FPM running on the server. Let’s continue creating the directive for your application virtual host WordPress:

vim /etc/nginx/sites-available/my-wordpress.ru.conf

server {
        listen 80;
        server_name my-wordpress.ru;
        rewrite ^(.*) http://www.my-wordpress.ru$1 permanent;
}

server {
        listen 80;
        server_name www.my-wordpress.ru;

        client_max_body_size 5m;
        client_body_timeout 60;

        access_log /var/log/nginx/my-wordpress.ru-access;
        error_log /var/log/nginx/my-wordpress.ru-error error;

        root /var/www/html/my-wordpress.ru/;
        index  index.html index.php;

        ### root directory ###
        location / {
                try_files $uri $uri/ /index.php?$args;
        }

        ### security ###
        error_page 403 =404;
        location ~ /. { access_log off; log_not_found off; deny all; }
        location ~ ~$ { access_log off; log_not_found off; deny all; }
        location ~* wp-admin/includes { deny all; }
        location ~* wp-includes/theme-compat/ { deny all; }
        location ~* wp-includes/js/tinymce/langs/.*.php { deny all; }
        location /wp-includes/ { internal; }
        #location ~* wp-config.php { deny all; }
        location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php)$ {
                types { }
                default_type text/plain;
        }

        #  location ~* wp-admin {
        #      allow <YOUR_IP>;
        #      allow 127.0.0.1;
        #      deny all;
        #  }

        ### disable logging ###
        location = /robots.txt { access_log off; log_not_found off; }
        location = /favicon.ico { access_log off; log_not_found off; }

        ### caches ###
        location ~* .(jpg|jpeg|gif|css|png|js|ico|html)$ { access_log off; expires max; }
        location ~* .(woff|svg)$ { access_log off; log_not_found off; expires 30d; }
        location ~* .(js)$ { access_log off; log_not_found off; expires 7d; }

        ### php block ###
        location ~ .php?$ {
                try_files $uri =404;
                include fastcgi_params;
                #fastcgi_pass 127.0.0.1:9001;
                fastcgi_pass unix:/var/run/php-wordpress.socket;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_intercept_errors on;
                fastcgi_split_path_info ^(.+.php)(.*)$;
                #Prevent version info leakage
                fastcgi_hide_header X-Powered-By;
        }
}

Enable the virtual host directive and restart Nginx by running the following commands:

cd /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/my-wordpress.tld.conf
nginx -t
/etc/init.d/nginx restart

Testing PHP-FPM by creating a PHP script info.php in document /var/www/html/my-wordpress.ru/:

mkdir -p /var/www/html/my-wordpress.ru/
cd /var/www/html/my-wordpress.ru/
echo -e "<?phpntphpinfo();n" > info.php

access to test your PHP-FPM: http://my-wordpress.ru/info.php

STEP 4) WordPress setup

The next step is to install WordPress inside the document root at /var/www/html/my-wordpress.ru/. Before installing WordPress, let’s first create a MySQL database by doing the following:

mysql -u root -p

mysql> create database wordpressDB;
mysql> grant all on wordpressDB.* to [email protected] identified by 'YOUR_PASS';
mysql> quit

cd /var/www/html/my-wordpress.ru/
wget http://wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* .
rm -rf latest.zip wordpress/

Next, copy the sample WordPress configuration and MySQL database configuration information:

cp wp-config-sample.php wp-config.php
vim wp-config.php

define('DB_NAME', 'wordpressDB');
define('DB_USER', 'wpUser');
define('DB_PASSWORD', 'YOUR_PASS');

chown nginx: -R /var/www/html/my-wordpress.ru/

open http://my-wordpress.ru and complete the WordPress installation

STEP 5) Configure caching for best performance

Install PHP-APC (Alternative PHP Cache) by running:

yum install php-pecl-apc

After installing APC, add the following lines to /etc/php.d/apc.ini

cat > /etc/php.d/apc.ini

extension = apc.so
apc.enabled=1
apc.shm_segments=1
apc.shm_size=128M
apc.num_files_hint=1024
apc.user_entries_hint=4096
apc.ttl=7200
apc.use_request_time=1
apc.user_ttl=7200
apc.gc_ttl=3600
apc.cache_by_default=1
apc.filters
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.file_update_protection=2
apc.enable_cli=0
apc.max_file_size=1M
apc.stat=1
apc.stat_ctime=0
apc.canonicalize=0
apc.write_lock=1
apc.report_autofilter=0
apc.rfc1867=0
apc.rfc1867_prefix =upload_
apc.rfc1867_name=APC_UPLOAD_PROGRESS
apc.rfc1867_freq=0
apc.rfc1867_ttl=3600
apc.include_once_override=0
apc.lazy_classes=0
apc.lazy_functions=0
apc.coredump_unmap=0
apc.file_md5=0
apc.preload_path

and restart PHP-FPM for the changes to take effect.

/etc/init.d/php-fpm restart

check APC boot with command:

php -m | grep -w apc

or by opening the script info.php at the root of the document.

The next thing to do is log into your WordPress admin area and install the W3 Total Cache plugin. For the W3 Total Cache plugin to work, you must first enable SEO дружественную структуру Url.

Настройки->Постоянные ссылки->Произвольно:

http://my-wordpress.tld/%postname%/

and then proceed with the installation W3 Total Cache… After installation, go

Performance->General Settings

and enable / disable the following options:

Page cache: enabled
Page cache method: Disk: Enhaced

Minify: disabled

Database Cache: enabled
Database Cache Method: Opcode: Alternative PHP Cache (APC)

Object Cache: enbabled
Object Cache Method: Opcode: Alternative PHP Cache (APC)

Browser Cache: disabled

CDN: this is up to you.

Click, Save all settings to save your changes.

Add the following line to /var/www/html/my-wordpress.tld/nginx.conf

cat > /var/www/html/my-wordpress.ru/nginx.conf

# BEGIN W3TC Page Cache cache
location ~ /wp-content/cache/page_enhanced.*html$ {
    add_header Vary Cookie;
}
# END W3TC Page Cache cache
# BEGIN W3TC Page Cache core
set $w3tc_rewrite 1;
if ($request_method = POST) {
    set $w3tc_rewrite 0;
}
if ($query_string != "") {
    set $w3tc_rewrite 0;
}
if ($request_uri !~ /$) {
    set $w3tc_rewrite 0;
}
if ($http_cookie ~* "(comment_author|wp-postpass|w3tc_logged_out|wordpress_logged_in|wptouch_switch_toggle)") {
    set $w3tc_rewrite 0;
}
if (!-f "$document_root/wp-content/cache/page_enhanced/$http_host/$request_uri/_index.html") {
  set $w3tc_rewrite 0;
}
if ($w3tc_rewrite = 1) {
    rewrite .* "/wp-content/cache/page_enhanced/$http_host/$request_uri/_index.html" last;
}
# END W3TC Page Cache core

make sure the ownership of the document root is in order by:

chown nginx: -R /var/www/html/my-wordpress.ru/

In the next step, we have to tell Nginx to use a config file. Let’s edit the file /etc/nginx/sites-enabled/my-wordpress.ru.conf and add / uncomment the following:

include /var/www/html/my-wordpress.ru/nginx.conf;
...
location ~* wp-config.php { deny all; }

Let’s test the Nginx configuration file and restart it for the changes to take effect by running:

nginx -t
/etc/init.d/nginx restart

You can also edit the WordPress config file /var/www/html/my-wordpress.ru/wp-config.php and define the following parameters, WordPress will not query the database for the site url:

define('WP_HOME', 'http://my-wordpress.ru');
define('WP_SITEURL', 'http://my-wordpress.ru');

Sidebar