Difference between revisions of "WordPress Optimization"

From wiki.mikejung.biz
Jump to: navigation, search
Line 1: Line 1:
<seo title="WordPress Optimization Guide" titlemode="append" keywords="Wordpress,Optimization,memcached,varnish,centos,ubuntu,liquidweb"  description="Wordpress Optimization"></seo>
<seo title="cPanel WordPress Optimization Guide" titlemode="append" keywords="Wordpress,Optimization,memcached,varnish,centos,ubuntu,liquidweb, how to optimize wordpress on cpanel"  description="Wiki page that covers how to optimize wordpress on a VPS with cPanel"></seo>
=How to Optimize Wordpress on a cPanel Server=
=How to Optimize Wordpress on a cPanel Server=

Revision as of 15:42, 7 February 2015

Liquidweb 728x90.jpg

How to Optimize Wordpress on a cPanel Server

This page is meant to help improve Wordpress performance on a cPanel server. There is quite a lot of customization that needs to be done, but if you follow this guide you can haz fast Wordpress!

WordPress Performance Tests

By using the guide below, you can significantly improve Wordpress performance. For my tests I used WordPress 4.0.1 and did not create any posts, or add any content to the blog. I did this to set a baseline for performance, once you start adding in content it's hard to really compare results.

I tested out performance on [LiquidWeb's 1GB SSD VPS] The VPS has 2 vCPUs and 1GB of RAM along with 50GB all SSD storage.

For the "Default" run I used a newly created cPanel server, installed WordPress and started to running tests. I used MySQL 5.6, Apache 2.4 Prefork with PHP 5.4 using SuPHP as the handler. I did not have an optimized .htaccess file in place, Varnish was not installed, memcached was not installed, and w3totalcache was not used for this run. Obviously this is not how most people run WordPress, but I wanted to use the most basic configuration and no optimizations to show the "worst case" WordPress performance.

I used Apache Benchmark to test out the site. I ran this from a remote location, so this was NOT run on the same server that hosted the Wordpress site. This command will use 5 concurrent connections and will load the site 1000 times.

ab -c 5 -n 1000 http://mytestdomain.lol/

As you can see, with the default configuration I get around 13 Requests per second. The response time for 95% of requests was 456ms. This isn't amazing, but not terrible. The server was able to handle the load without issue, but view the next set of results to see what happens once we optimize the server a bit.

Server Software:        Apache/2.4.10
Server Hostname:        mytestdomain.lol
Server Port:            80

Document Path:          /
Document Length:        7418 bytes

Concurrency Level:      5
Time taken for tests:   76.810 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      7675000 bytes
HTML transferred:       7418000 bytes
Requests per second:    13.02 [#/sec] (mean)
Time per request:       384.050 [ms] (mean)
Time per request:       76.810 [ms] (mean, across all concurrent requests)
Transfer rate:          97.58 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   2.1      1      20
Processing:   274  382  51.1    382     655
Waiting:      219  309  44.2    310     491
Total:        275  384  51.2    385     655

Percentage of the requests served within a certain time (ms)
  50%    385
  66%    411
  75%    425
  80%    433
  90%    447
  95%    456
  98%    468
  99%    478
 100%    655 (longest request)

Once we installed PHP-FPM, Varnish, Memcached, Apache Event, applied .htaccess, and installed w3totalcache we get much better results. With the configuration listed below my test site was able to process 805 Requests per second. The response time for 95% of requests was 11ms which is insane. As you can see if you modify the default cPanel settings you can get significant performance gains for a basic Wordpress site.

Server Software:        Apache/2.4.10
Server Hostname:        mytestdomain.lol
Server Port:            80

Document Path:          /
Document Length:        7753 bytes

Concurrency Level:      5
Time taken for tests:   1.242 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      8124694 bytes
HTML transferred:       7753000 bytes
Requests per second:    805.07 [#/sec] (mean)
Time per request:       6.211 [ms] (mean)
Time per request:       1.242 [ms] (mean, across all concurrent requests)
Transfer rate:          6387.65 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        2    3   1.1      3      11
Processing:     1    3   1.1      3      12
Waiting:        1    3   1.1      3      12
Total:          4    6   2.0      6      17

Percentage of the requests served within a certain time (ms)
  50%      6
  66%      6
  75%      7
  80%      7
  90%      9
  95%     10
  98%     13
  99%     14
 100%     17 (longest request)

Installation Steps

MySQL 5.6 Configuration for Wordpress

Ensure that MySQL 5.6 is installed and that innodb_buffer_pool_size is set. Please note that you must move the old innodb logs out of the way, stop MySQL and then start it up again. If you do not do this then MySQL will fail to start and you will have downtime on your hands until you remove the old log files.

This configuration should work well for most servers with 1GB or 2GB of RAM.

cat /etc/my.cnf
innodb_buffer_pool_size = 64M
innodb_log_file_size = 128M
key_buffer_size = 64M

Apache 2.4 Event Configuration for Wordpress

cPanel Tweak Settings Listen Port

In WHM Tweak Settings. Change the default Apache listen IP and port to and apply the changes before any accounts are created. Leave the SSL IP and port alone, apache will still be handling ssl traffic.

cPanel Apache Event Configuration

Because cPanel likes to override the main httpd.conf file, which is modified also by WHM global configuration, we will want to put an event ifmodule block in pre_virtualhost_global.conf, this will override any dumb settings cpanel tries to apply, keeping our event settings at the defaults, which should be fine for most websites.

vim /usr/local/apache/conf/includes/pre_virtualhost_global.conf

KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

<IfModule event.c>
ThreadsPerChild 64
ServerLimit 16
MaxRequestWorkers 1024
StartServers 3
MaxConnectionsPerChild 0

Apache Event MPM and Version Info

Using Apache 2.4 EVENT, we are NOT using mod_php or SuPHP as the handler, we are using FastCGI to pass off PHP handling to PHP-FPM.

httpd -V
Server version: Apache/2.4.10 (Unix)
Server built:   Nov 26 2014 14:49:27
Cpanel::Easy::Apache v3.26.10 rev9999
Server's Module Magic Number: 20120211:36
Server loaded:  APR 1.5.1, APR-UTIL 1.5.4
Compiled using: APR 1.5.1, APR-UTIL 1.5.4
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAVE_IPV6 (IPv4-mapped addresses disabled)
 -D HTTPD_ROOT="/usr/local/apache"
 -D SUEXEC_BIN="/usr/local/apache/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

Varnish Installation and Configuration for Wordpress

Installation Method

This seems to be the simplest way to install Varnish.

rpm --nosignature -i https://repo.varnish-cache.org/redhat/varnish-4.0.el6.rpm
wget https://dl.fedoraproject.org/pub/epel/6/x86_64/jemalloc-3.6.0-1.el6.x86_64.rpm
rpm -i jemalloc-3.6.0-1.el6.x86_64.rpm
yum install varnish
chkconfig varnish on


This file is used to configure the varnish daemon. We will be changing the listening port to 80 and configuring the malloc storage size based on the size of the instance used. I set this to 128MB for the 1GB VPS, you may need to tune this if you run into memory issues.

For this file, we really only need to worry about two items, the listening port and the storage size. The listen port should always be set to 80. The storage size should scale with the instance size (how much RAM your server has). I was able to hammer my server with 1000 requests @ 10 concurrent connections and my server didn't even break a sweat with only 1GB, so this should be pretty good for most sites.

vim /etc/sysconfig/varnish 



This file defines what the backend servers are (in this case that is apache It also defines how varnish caches things, and handles them. We are basically just going to define the ACL for Purging so that W3Total cache can purge if needed.

Really, for the most part we should just be able to set it and forget it, but if you run into issues you will modify the VCL. By default Varnish is able to cache a lot with no special VCL in place. If you run into issues with SSL, or Sessions or whatever you might want to add in some VCL to handle this, otherwise the file below should be fine.

vim /etc/varnish/default.vcl

backend default {
    .host = "";
    .port = "8080";

acl purge {

sub vcl_recv {
        if (req.method == "PURGE") {
                if (!client.ip ~ purge) {
                        return(synth(405,"Not allowed."));
                return (purge);

PHP 5.5 Configuration for Wordpress

Other than making sure EA is using PHP 5.5.x as the main version there is nothing to configure here really (in terms of modules or whatnot).

Zend OPcache Configuration

Assuming you are using PHP 5.5+ you should be able to easily enable PHP's built in OPcache by modifying /usr/local/lib/php.ini. Make sure that opcache.so is located in your extensions directory that is specified in the php.ini file. Once you have edited the file restart php-fpm.


PHP Version Info

As long as we are using PHP 5.5 and up, you should be good.

php -v
PHP 5.5.19 (cli) (built: Nov 26 2014 14:53:33) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with the ionCube PHP Loader v4.6.1, Copyright (c) 2002-2014, by ionCube Ltd.
    with Suhosin v0.9.36, Copyright (c) 2007-2014, by SektionEins GmbH

cPanel PHP Handler Info

Make sure you set the default PHP handler to FCGI, if you don't do this then the PHP-FPM script will not complete and you might have down websites to deal with.

/usr/local/cpanel/bin/rebuild_phpconf --current
Available handlers: fcgi cgi none
PHP4 SAPI: none
PHP5 SAPI: fcgi
SUEXEC: enabled
RUID2: not installed

PHP-FPM Configuration

Installation method for PHP-FPM

This script seems to work well for installing and configuring PHP-FPM on a cPanel account. The script will install PHP-FPM, generate per domain configuration files and modify httpd.conf to configure existing domains to use PHP-FPM. You will need to make sure you enable FCGI via Easy Apache and select the default PHP handler to be FCGI.

wget http://sysally.net/cphstack.sh
chmod a+x cphstack.sh
./cphstack.sh install
service php-fpm start

PHP-FPM Config File: /usr/local/etc/php-fpm.conf

This is the global configuration file for PHP-FPM. There is not much to mess with here, at the end of the file there is an includes directory listed which houses the individual vhost configs. NOTE The memcache.so line was added by me to get the memcache module to work. Everything else is at the default, but keep in mind that the .conf files under the include directory will take precedence over this file.

pid = /var/run/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm.log

user = nobody
group = nobody
listen =
pm = ondemand
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[extension] = memcache.so

PHP-FPM Config File(s): /opt/xstack/cphstack/php-fpm.pool.d/*.conf

The per domain config files go in this directory. Each file is named after the domain, which is nice, for example, on my test server the only file under this directory was:

-rw-r--r-- 1 root root 18163 Nov 26 14:56 domain.conf

My config file has the following settings:

; Pool Definition ;

user = user
group = user
listen = /var/run/php-fpm/user.sock
listen.mode = 0666
pm = ondemand
pm.max_children = 15
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 256

Memcached Installation and Configuration for Wordpress

yum install memcached

vim /etc/memcached.conf

##Modify the file to include these lines. You can raise -m from 64 to however much memory you want memcached to use, this configuration file is meant for a smaller server with 1GB or 2GB of RAM. ##
-m 64
-p 11211
-u nobody

Once you have finalized the [Memcached] configuration file, go ahead and start up memcached and use chkconfig to make sure that memcached starts up on reboot.

service memcached start
chkconfig memcached on

Now you need to install the memcache PHP module so that WordPress can use it with w3totalcache

pecl install memcache
echo "extension=memcache.so" >> /usr/local/lib/php.ini
service httpd restart

Run the command below to make sure that the memcache PHP module is loaded.

php -m | grep memcache

WordPress Configuration

Nothing too special here, installed the latest version of Wordpress and installed w3totalcache/


This is how I enabled the plugin. No need to really worry about page cache since we are caching the hell out of everything already.

Page Cache: Disabled
Minify: Disabled
Database Cache: Enabled, uses Memcached
Object Cache: Enabled, uses Memcached
Browser Cache: Enabled
CDN: Disabled
Reverse Proxy: Enable Varnish Cache, server

cPanel Configuration

Tweak Settings

Updating Use pigz from Off to On.

Updating Bandwidth limit check from On to Off

Updating Allow cPanel & WHM to determine the best value for your MySQL max_allowed_packet configuration? from On to Off

Updating Allow cPanel & WHM to determine the best value for your MySQL open_files_limit configuration? from On to Off.

Updating Critical load threshold from “10” to # of CPUs (autodetect).

Apache non-SSL IP/port

Optimized .htaccess for WordPress

<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/plain text/xml text/css application/x-javascript application/javascript text/javascript

<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 5 seconds"
ExpiresByType text/css A31536000
ExpiresByType application/x-javascript A31536000
# Text
ExpiresByType text/css A31536000
ExpiresByType application/x-javascript A31536000
ExpiresByType text/html A3600
ExpiresByType text/richtext A3600
ExpiresByType text/plain A3600
ExpiresByType text/xml A3600

# Image
ExpiresByType image/gif A31536000
ExpiresByType image/x-icon A31536000
ExpiresByType image/jpeg A31536000
ExpiresByType image/png A31536000
ExpiresByType image/svg+xml A31536000

# Video
ExpiresByType video/asf A31536000
ExpiresByType video/avi A31536000
ExpiresByType video/quicktime A31536000
ExpiresByType video/mp4 A31536000
ExpiresByType video/mpeg A31536000

ExpiresByType application/pdf A31536000

# Flash
ExpiresByType application/x-shockwave-flash A31536000

# Font
ExpiresByType application/x-font-ttf A31536000
ExpiresByType application/vnd.ms-fontobject A31536000
ExpiresByType application/x-font-otf A31536000

# Audio
ExpiresByType audio/mpeg A31536000
ExpiresByType audio/ogg A31536000
ExpiresByType audio/wav A31536000
ExpiresByType audio/wma A31536000

# Zip/Tar
ExpiresByType application/x-tar A31536000
ExpiresByType application/x-gzip A31536000
ExpiresByType application/zip A31536000

Options -Indexes

how to modify the base URL for wordpress 4.0


1. Login to wp-admin

2. Settings > General

3. WordPress Address (URL) -- leave this alone, this is the base install directory, changing this will break things.

4. Site Address (URL) -- change this from domain.com/somedir to domain.com.

5. Copy index.php and .htaccess from the install directory to public_html

6. Edit require('./wp-blog-header.php'); to ('./installdir/wp-blog-header.php')

7. You may need to make other changes, especially with the theme.

how to disable all wordpress 4.1 plugins via MySQL(phpmyadmin)

In the table wp_options, under the option_name column (field) find the active_plugins row, change the option_value field to: