Speed up VestaCP on CentOS 7

VestaCP is a very popular open-source control panel used to make hosting your websites as easy as possible. It installs a full LAMP or LEMP stack and makes it easy to control the server without needing to add vhosts manually through a configuration editor.

A downside, in my opinion, is that VestaCP is not very fast out of the box. WordPress could run much faster and so could other applications with some modifications to the underlying software stack. Since most people will use VestaCP to run a single, or multiple WordPress based websites, we’ll be focusing on them specifically. Although these changes can be used with other popular CMS without too many issues.

I won’t be going over anything to do with the DNS or email section for reasons explained later on.

This is quite a long guide so I would take the time to read it carefully. I’ll be going over how each part of the server affects the speed of the server. If you don’t care and want to just speed up your server without a deeper understanding, then skip to part 3. “The Technical Part”.


  1. Before we start
  2. So how do we get VestaCP to run faster?
    1. PHP and OpCode
    2. CMS Caching
  3. The Technical Part
    1. Upgrading PHP
    2. Installing PHP OpCache
    3. Upgrading MariaDB
    4. Caching WordPress
    5. Tuning the server
  4. Benchmarks


Before We Start

If you haven’t already installed VestaCP then I would recommend a few things before you do.

I am not using Apache, Apache uses too many resources and is not as fast as a pure NGINX setup.

The exact command I’ve installed with is below:

VestaCP Install options
bash vst-install.sh –nginx yes –phpfpm yes –apache no –named no –remi yes –vsftpd no –proftpd no –iptables yes –fail2ban yes –quota no –exim no –dovecot no –spamassassin no –clamav no –mysql yes –postgresql no

 

  • Don’t install software you don’t need.

This especially applies if you’re using a server with a small amount of memory. If you are okay with using SFTP instead of FTP, then don’t install an FTP server. If you host your email elsewhere (which I recommend you do to save resources, MXroute is a great provider), then don’t install a mail server; a properly configured mail server will use multiple GB of RAM which could be used for MySQL or PHP instead.

  • Don’t host your own DNS or Email.

This might sound odd since it’s a large part of the functionality of VestaCP, not only are they a difficult thing to manage in the long run but they are very easy to break and hard to fix if you haven’t got the experience. For email I use and recommend MXroute and for DNS I recommend Cloudflare. Using Cloudflare will also work great since we can make use of their free caching service to get a nice speed boost in distributing your websites resources around the world.

When you create your website on VestaCP without these two installed, you need to deselect “DNS Support” and “Mail Support”!

  • Use NGINX and PHP-FPM instead of Apache or Apache + NGINX.

Apache is notoriously bad for memory usage and slowness when handling a high amount of concurrent users.

Requests per second tested on different browsers
Courtesy of DreamHost
Memory usage of different web browsers under load
Courtesy of DreamHost

The downside is that NGINX takes more work to get right, the configuration is easy to work with, the problem is that .htaccess files are not supported. This means that things such as the WordPress rewrite rules need to be put into the nginx.conf file directly. We’ll go over all that later so don’t worry about it yet.

  • Install Remi Repository

This is how we’re going to install certain software on CentOS 7 later on in this tutorial, if you haven’t already installed VestaCP then make sure you select it during the install, if you have already installed VestaCP then you can follow our guide to install it instead.


So how do we get VestaCP to run faster?

The first thing we need to do is check the resources we’re running on. 

VestaCP has some basic requirements, 512MB of RAM, 20GB storage and a 1Ghz CPU, the installer has 4 categories which depend on the amount of RAM available. Less than 1GB is “micro” and doesn’t support the phpfcgi template. Less than 3GB is “small”, less than 7GB is “medium” and more than 7GB is “large”. If you install using the default options then the anti-spam and antivirus packages are only installed on medium and large servers.

The VPS I’ll be using has 1GB of RAM, 20GB of SSD storage and a single core 3.5Ghz CPU, more than enough for a LEMP only install. I personally wouldn’t go any lower than 1GB, 2-3GB being the most comfortable. An SSD is a must have so make sure your host has it as a feature, I recommend HostHatch, BuyVM, LiteServer and Inception Hosting.

The reason we need at least 1GB of RAM is because MySQL and PHP can both devour our available RAM very easily, check the usage now on a modified install running no websites

              total        used        free      shared  buff/cache   available
Mem:            992         150         139          16         702         655
Swap:          1023           2        1021
Total:         2016         153        1160

Only 655MB free before any usage is put onto the server, although it doesn’t sound like a lot it’s actually enough for a very high performing server!


What to do about PHP?

PHP is the technology used to power dynamic sites on most of the internet. VestaCP installs it by default as part of the LEMP / LAMP stack and it’s one of the things we’ll be working with to speed up our web server. Since PHP has to run before anything dynamic (so any page on a WordPress website) can be sent to the visitor, meaning that if the PHP process is running slowly then nothing can be sent, drastically increasing the load time for the visitor. If the PHP process is running very quickly then the user is sent the data for their browser to render faster, thus making the page load time faster.

Basically it is in our best interest to have PHP running as fast as possible; we’ll be using a couple of different ways to do this.

Firstly we’ll be upgrading to PHP 7, or 7.1. VestaCP by default installs an old version of PHP as it’s the only version available in the default repositories for CentOS 7.

Transactions per second on different PHP processors with WordPress
Thanks to Kinsta for the graph

As you can see PHP 7 makes a huge difference in the amount of transactions per second a server can process, we won’t be getting into HHVM for now.

So what else can we do to speed up PHP?

I’m glad you asked since this is where things get really cool. We can make use of something called “Zend OpCache” on our server to cache the PHP files output directly. When a PHP file is run, the code inside of the file is first compiled, then executed, then sent to the user. When running a CMS such as WordPress this compilation can take a toll on the system, as it will need to be done every single time a script is run. It is an extra task for the PHP process to do before it can even do the task it has been given.

A good analogy would be the wheels on a car, every time you want to drive your car you would need to install every wheel first, then when you had finished driving your car to the destination, the wheels fall off again. This means before you can even get started on your journey, no matter how long, you will need to install these wheels first.

OpCache changes this, the wheels now no longer fall off each time, the car will still have to be driven to it’s destination each time (or executed like a PHP script) but will no longer need the wheels putting on first (compiling the PHP program). A visual diagram is below.

How OpCode Cache works.
Sourced from here

To recap so far, we know we need around 1GB of RAM total, PHP will be upgraded to 7.0 and Zend OpCache will be installed to cut down on compiling time.


Optimising the database, MariaDB

The database aspect is one of the most important parts of running a web server. When using a system such as WordPress the database is used as a storage point for all page content and configuration settings, if this database is slow then your content will load slowly too.

MariaDB will also be one of the largest programs we need to run due to the amount of memory it uses, if we have a low end system then keeping its usage as low as possible is a big concern.

Normally I replace MySQL systems with MariaDB but since VestaCP has already done that we have no need too. Instead, we can update the version installed to a newer version with more features and better performance.

The problem with optimizing a database is that you can do it forever, it can always be improved meaning there is too much to go over in this post. The main thing to note about the database is that the slower it is, the longer it takes for the PHP process to finish as it needs to collect information first. Better database = faster website.


Caching the CMS

Since the CMS we’re using is WordPress there are a variety of common plugins that can be used to setup a cache system. We’ll be using W3 Total Cache for it’s customisation and compatibility with NGINX.

Caching works by taking a dynamic page, such as a WordPress post, and turning it into a static file which is served instead. This can speed a webpage up by hundreds of times since no processing needs to take place before it is sent to the client.

Comparing various WordPress caching plugins.
Courtesy of Dashboard Junkie

There isn’t a reason not to use caching so long as it is configured properly. It’s free and easy to do and gives huge benefits performance wise.

Now we know about the things we’ll be changing, lets move onto the more technical part.


The Technical Part



Upgrading PHP

We’ve wrote a much more detailed post on how to do this before, we’ll go over it quickly here too.

Make sure everything is up to date.

sudo yum update

Now install yum-utils so that we can replace the currently installed version of PHP.

sudo yum install yum-utils

This is where Remi is used, you should have installed it with VestaCP but if not do this first then continue.

Enable the PHP 7 in Remi.

sudo yum-config-manager --enable remi-php70

Now update Yum to apply the change.

sudo yum update

Restart PHP.

sudo service php-fpm restart

Check the new version that you have installed.

php -v

Now disable the old versions of PHP.

sudo yum-config-manager --disable remi-php56 && sudo yum-config-manager --disable remi-php55 && sudo yum-config-manager --disable remi-php56-debuginfo && sudo yum-config-manager --disable remi-php55-debuginfo
sudo yum clean all 
sudo yum update

All done, let’s move onto OpCache.


Installing OpCache

Installing OpCache is a very easy thing to do but must be done after the PHP upgrade has been done.

First login to your server and update yum.

sudo yum update

Now we can install OpCache.

sudo yum install php-opcache

Now we need to restart PHP.

sudo service php-fpm restart && sudo service nginx restart

Now we need to see if OpCache is running; in the root directory of one of the domains hosted on your server create a file called “info.php”. Inside that file paste the following:

<?php phpinfo(); ?>

Now open your web browser and navigate to where you placed the file, there should be a section on this page called Zend OpCache if all is working.

Zend OpCache default configuration
Yours should look similar

 


Upgrading MariaDB

Upgrading MariaDB is just like before when we upgraded PHP with a few changes.

First make sure Yum is up to date again.

sudo yum update

Now take a backup of your databases if you have any.

Once you’ve done that we now need to remove MariaDB from the system.

sudo yum remove mariadb mariadb-server

Now we need to add a repository for MariaDB.

sudo nano /etc/yum.repos.d/MariaDB.repo

Insert the following content:

# Used to install MariaDB 10 instead of default 5.5
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = https://yum.mariadb.org/10.2/centos7-amd64/
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Update Yum again and accept the GPG key for the repository we added.

sudo yum update

Now install MariaDB again with the newer version.

sudo yum install mariadb mariadb-server

Now start the database.

sudo service mariadb start

Enable the MariaDB service so that it starts on boot.

systemctl start mariadb
systemctl enable mariadb.service

MariaDB is now upgraded and working, lets get the caching system working.


Caching WordPress

If you are using custom perma-links in WordPress then you need to edit your domain in the VestaCP control panel and change the “Web Template” to “wordpress2” so that you do not get 404 errors.

To cache WordPress we’re going to be using the W3 Total Cache plugin, it’s very popular and will work very well. Since NGINX doesn’t support the use of .htaccess files as Apache does, for configuration the plugin will create an nginx.conf file in our webroot which will be used instead. To have VestaCP use this file we’ll need to edit one configuration file in the users /conf/ folder.

Let’s install the plugin first then we’ll go over how to edit that config file. Go to the plugins page, select “Add New” and search “W3 Total Cache”, install  and activate it.

Now we have the plugin installed we can go through the initial configuration setup. There should be a new option on your left admin bar called “Performance”. Click that and go to “General Settings”. Tick the box called “Toggle all caching types” and then Save all settings.

Toggle W3TC caching

Now scroll to the bottom of the page and deselect the CDN toggle. This is because we won’t be using a CDN for now and it will cause issues if we do not. Click save all settings AND Purge Caches when you have done this.

Disable W3TC caching

Now that we’ve done this go back to your SSH terminal, we need to enable the nginx.conf file we spoke about earlier. Since my username in VestaCP is called “speedup” and the website being used is “luweb.serv.life” then my config file will be located at “/home/speedup/web/luweb.serv.life/public_html/nginx.conf”.

There are 2 files we are going to edit, one is SSL (if you are using SSL on your website), and the other is for normal HTTP traffic.

With a text editor such as nano, open the file at the following location:

/home/yourusername/conf/web/nginx.conf

Inside of this file there will be a separate configuration block for each website. Since this is the “nginx.conf” file it applies for any traffic sent over HTTP, not HTTPS.

Find the configuration block for the website you are working on, there will be a include that looks similar to this  “include /etc/nginx/conf.d/webmail.inc*;”. Make a new line after this and place the following:

include         /home/yourusername/web/yourwebsite/public_html/nginx.conf;

Now test the configuration file

nginx -t

If you get a success then restart NGINX, if you get a failure then go back and make sure you have entered the text correctly.

If you are using HTTPS, then you need to edit another file too. It is located at:

/home/yourusername/conf/web/snginx.conf

It should be exactly the same as the other file you edited, just with some some extra configuration for the websites SSL setup. Do the same as before.

Test NGINX the same way as before and restart if it passed.

sudo service nginx restart

Now W3 Total Cache is installed and working, at the bottom of the “General Settings” page there is an import button. Download this file and import it. I have made some basic settings that will get you going and shouldn’t break your site. Now clear the cache and restart NGINX again for it to take effect.

Now that we have MariaDB and PHP 7 installed, WordPress caching setup and ready to go we can start tuning each of these to get the best performance.


Tuning the server

Now we can tune the server, since our systems are different you can’t just copy and paste and expect something great. With all these upgrades done my system is currently sat on around 477MB available memory. You can just leave your system with the stock settings and it’ll work fine but a few changes can be made to get the most out of this system. Tuning is something you could do forever and still never get perfect so I’m going to keep this brief, if you research the various components and how they can be optimised you should be able to do this yourself.

First, I’m going to decrease the amount of login attempts Fail2Ban will allow before blocking an IP address on the SSH port. This can be done in the Vesta Control Panel directly in the web interface.

Login using the admin account, navigate to “Server” at the top right, scroll down to “Fail2Ban” then click the configure button.

Your’s will look like this if it is default:

[ssh-iptables]
enabled = true
filter = sshd
action = vesta[name=SSH]
logpath = /var/log/secure
maxretry = 5

Change it so that it looks like this instead:

[ssh-iptables]
enabled = true
filter = sshd
action = vesta[name=SSH]
logpath = /var/log/secure
findtime = 600
maxretry = 3

This means that anybody who gets the wrong login 3 times in a 10 minute window will be banned for one month. You can change this by editing the maxretry and findtime parameters.

Tuning MySQL and PHP is a much more daunting task, I recommend HaydenJames, Tocker and Zend.


Benchmarking VestaCP and Final Words

All benchmarks are done via SSL and a default WordPress index page install to simulate a real website. Boom is used to test concurrency from a remote VPS.



Before Starting

Boom Scores

Server Software: nginx
Running GET https://luweb.serv.life:443
Running for 30 seconds - concurrency 5.

Starting the load........................................................................
........................................................................................ Done
-------- Results --------
Successful calls 160
Total time         30.0009 s  
Average           0.9195 s  
Fastest           0.7351 s  
Slowest           1.1386 s  
Amplitude         0.4035 s  
Standard deviation 0.076202
RPS               5
BSI               :(
-------- Status codes --------
Code 200           160 times.
-------- Legend --------
RPS: Request Per Second
BSI: Boom Speed Index

Server Software: nginx
Running GET https://luweb.serv.life:443
Running for 30 seconds - concurrency 10.
Starting the load..................................................................................................................................................................... Done

-------- Results --------
Successful calls 165
Total time 30.0215 s 
Average 1.7807 s 
Fastest 1.2852 s 
Slowest 2.2843 s 
Amplitude 0.9991 s 
Standard deviation 0.184134
RPS 5
BSI :(

-------- Status codes --------
Code 200 165 times.

-------- Legend --------
RPS: Request Per Second
BSI: Boom Speed Index

GTMetrix Load Time
View full result here
WebPageTest Results
View full result here
Pingdom speed test results
View full result here

Waterfall of the webpage as it loads

 


After Following This Guide

GTmetrix after following this guide
View full result here
WebPageTest after following this guide
View full result here
Pingdom after following this guide
View full result here

WebPageTest Waterfall graph after following this guide

 

 


Final Words

As you can see from the benchmarks just doing a few simple modifications to VestaCP makes a huge difference in speed. The caching system also plays a significant part in the difference but is amplified by the efficiency of NGINX in serving static content and the overall speed of PHP 7 and OpCode Cache when running dynamic files.

I run a similar setup on a HostHatch VPS to serve this website to you, although with more resources than the test server for this article. This is my longest post so far, over 3000 words! Thanks for sticking it out, I hope to get some more stuff like this out soon although it’ll take me a while.


Do you use VestaCP, if so, have you done anything to optimise it for your usage? If you get stuck leave a comment and I’ll see if I can help out 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *