How to Speed up WordPress Site with VPS: Advanced Step-by-Step Guide

If you’re reading this, you are searching for a way to speed up your WordPress website.

In this step by step guide, I will show you how to speed up WordPress site to make it load in less than 1 second (for only $5 per month). For real!

At the end of this step-by-step WordPress speed up guide your website will be in top 10% fastest websites in the World!

As you may notice, WPGoblin homepage loads in just above half of a second!

Here is the proof:

You can do the test by yourself via Pingdom speed test.

Continue with this guide to achieve the same results today!

Speed optimization the wrong way

It’s known that website speed is being used in desktop search rankings.

But recently, Google reported that, as of July 2018, website speed is going to be used in mobile page rankings too. Because of this, everyone is talking about importance of website speed in SEO, CRO and overall user experience on the site.

It’s true that Google is giving an additional boost to fast websites in search results. You can exploit this by optimizing your WordPress website for speed.

To optimize WordPress for speed, many ‘WordPress experts’ give advice like:

  • Choose good hosting
  • Optimize your images, css and javascript
  • Install caching plugin
  • Use less plugins
  • Reduce the number of requests
  • Optimize database
  • and more…

For sure, those tips are amazing! But there is one big problem with it:

They aren’t telling you how to do it!?

In this WordPress speed optimization guide, I will show you exact step by step on how to boost your website speed.

I have to warn you upfront that this works ONLY if you implement every step and it’s worth it!

Implement every step of this guide, and
Google will love you

After years of learning and experimenting, I finally found a way to optimize WordPress website for speed the right way.

Everything that I learned throughout my journey, I compressed to fit in this speed optimization guide.

By implementing every single step that you read here, you will boost your website speed through the roof. It will save you hundreds of hours and even more money in the long run.

Yes, you can make your website load in less than 1 second.

By strictly following every advice provided in this guide, you can become the owner of one of the fastest websites in the World.

NOTE: Some steps may be confusing. If something goes wrong, repeat the step. If you’re stuck, feel free to contact us for help.

Keep up until the end, trust me, it’s worth it!

Lets make your WordPress website great again!

8 Steps to ultra fast WordPress website:

  1. Initial VPS Setup (LEMP Stack)
    1. Get Fast SSD VPS Server
    2. Install Linux (Ubuntu 16.04)
    3. Connect to the server
    4. Initial server configuration
    5. Install Nginx
    6. Install MySql
    7. Install PHP 7.2
  2. Connect domain to Cloudflare
  3. PHPMyAdmin installation
  4. WordPress installation (or transfer)
  5. SSL Configuration
  6. Brotli and GZip Compression
  7. Caching
    1. PHP Bytecode Cache (PHP OPCache)
    2. Redis Database Caching
    3. Nginx Server Caching
    4. Cloudflare Edge Caching
    5. Browser Caching
  8. CDN (Content Delivery Network) Cache – Optional

Step #1: Initial VPS Setup (Install LEMP Stack)

Good server is crucial for ultra fast speeds. Just by transferring WordPress site to SSD VPS, you can cut your website loading times in half.

When it comes to server response time, most important is Time To First Byte (TTFB). In other words, how fast server responds to the requests that are coming in. If TTFB is long, the server response is slow.

Any optimization that you do after (even caching), won’t help. So it’s crucial to host your WordPress site on good VPS server to reduce TTFB as much as possible.

Even though if caching is perfectly set up as we show in this guide, request still has to reach the server. Slow server response may be a killer for your website speed and website business in general.

Just by choosing great VPS server for your WordPress website, you can overcome most speed issues and boost your website speed through the roof.

Let’s pick best VPS server for your site.

1.1. Get Fast SSD VPS Server

As you know, fast SSD VPS makes the difference.

There are many VPS hosting providers on the web. Linode is the one I like the most. Low prices, fast speeds. Amazing.

I get blazing fast speeds on my websites with Linode. I want the same to you too.

Get your Linode server.


1. Create free Linode account

Head over to Linode and create free account.

Input your email, username, password in sign up form and click “Create Account” button.

Go to your email and confirm account to continue sign up process.

2. Welcome to Linode! – Get 4 months free VPS!

Use coupon code “PODCASTINIT2018” to get 4 months of free SSD VPS hosting with WPGoblin and Linode!

3. Add funds and complete account sign up (Get 4 months free with coupon – PODCASTINIT2018)

First part of the form fill in with your personal billing information.

In “Optional Information” part of the form add promotion code “PODCASTINIT2018” to get $20 USD of credit. This is enough for 4 months of free hosting!

To complete sign up process it’s required to add credit card information.

Credit card will be used for initial payment. PayPal isn’t available on initial account setup, but when account is complete, you can add funds to your account via PayPal too.

I personally use PayPal to add credits to my account. If you are also going to use PayPal, I suggest you to start with $5 USD preload amount via credit card. And, for future payments you can use PayPal via account dashboard.

Agree to TOS, click “Add Credit” and you are ready to start using your VPS! 🙂

4. Activate your Linode VPS

To activate your Linode virtual private server, visit your Linodes manager.

Take the cheapest $5 USD server!

With server configuration and caching setup showed in this guide, this small and cheap server can handle more than hundreds of thousands concurrent users! Yes, more than 100,000 users on your website in same time! Easy.

1 CPU core, 1 GB of RAM and 20 GB of storage will be more than enough for most blogs and eCommerce sites. You  won’t need to upgrade for a long period of time. And, if you ever reach that point, you can upgrade to a better server in just few clicks.

Server location

Location of the server directly impacts website speed. To reach blazing fast speeds, server must be as close as possible to you visitors.

Location of your server depends on your website traffic. If your website was up and running on some other hosting for couple of months, check your Google Analytics account. Check report where traffic is grouped by country.

Simply, if one country dominates with more than 50% traffic coming from it, pick server location closest to that country.

If your website is new or depends on traffic from all over the world (but mostly US and EU), I would go for server located in Newark, NJ. It’s in US, but still very close to EU what makes website very fast for both US and EU visitors!

Pick your server, click “Add this Linode! Congratulations, your server is booting up!

Continue with connecting to your server to start initial configuration.

1.2. Install Linux (Ubuntu 16.04)

Empty server won’t help much. It still needs to be configured.

You are safe! Every single step of configuration you need to do is covered by this guide.

First step is to install operating system.

Your server will be running on Ubuntu 16.04 LTS version of Linux OS.

Ubuntu 16.04 LTS is simple to configure, easy to install, free to use, safe and there are a lot of professionals on the web to help you if you are stuck somewhere in the process.

Lets get Linux up and running.


1. Get into your Linode server

Navigate to your Linode manager. Click on your Linode to access its dashboard.

2. Deploy an Image

Click on “Deploy an Image” link to start new Ubuntu 16.04 deployment configuration.

3. Configure deployment image

Copy-paste following configuration:

  • Image: Ubuntu 16.04 LTS
  • Deployment Disk Size: 19968 (or maximum that you can get)
  • Swap Disk: 512 MB
  • Root Password: (your password for logging into the server)

If you don’t know what some of these mean, no worries. You will be familiar with all settings until the end of this guide.

Click on “Deploy” button start initial server deployment process!

4. Power up the server

Deployment process will take 1-2 minutes. When it is done, click on “Boot!” button to power up your new server.

1.3. Connect to the server

Your Linux server with Ubuntu 16.04 operating system is booting up.

To power up WordPress site on it, you still need the rest of the LEMP stack (Linux, Nginx, MySql and PHP) to be installed.

Lets connect to the server to start LEMP stack installation process.


1. Download PuTTY (for Windows users) or open Terminal (for Mac users)

Download latest release of Putty by visiting Putty download page.

2. Find your server IP

To connect to the server, you need server IP.

You can find your server IP by visiting Linode manager page.

3. Connect to server

Open PuTTY client and fill it in with following information:

  • Host name (or IP): [email protected]YOURIP
  • Connection type: SSH

To save this configuration for future usage, click “Save” button.

To finally connect to your website click “Open” button.

3. Log in with password

Remember the password you set up in step 1.3.

Click “Yes” when pop up window appears and type in the password. While typing password, characters will be invisible and pointer won’t be moving. Don’t let this trick you. This is just a security measure. When you type in the password, click “Enter” to confirm the login.

Congratulations you successfully logged into the server.

Whenever you want to connect to your server, repeat this process.

1.4. Initial server configuration

To enhance security of the server and prevent yourself from executing commands on the server by accident it is recommended to access and work on server as custom created user rather than root user.


1. Create new user

Important! Tips when executing commands:

  • Each line is new command.
  • Execute commands without # (hashtag).
  • You can copy (“CTRL”+”C” on keyboard) commands from this post and paste (right mouse click) directly in PuTTY.

Create new user by executing:


When prompted, input your password, repeat the password. Again, while typing password, pointer won’t be moving while characters will actually be registered.

Confirm password with “Enter” to go to next step.

Other information aren’t important, you can skip them by pressing “Enter“.

When prompted, confirm adding user with “Y” and then “Enter”.

2. Give sudo (admin) privileges to new user

# usermod -aG sudo YOURUSERNAME

3. Log in as new user

Close current PuTTY application instance. Open PuTTY again and load your server connection.

To connect to the server with just created user replace:

  • Host name (or IP): root@YOURIP


  • Host name (or IP): YOURUSERNAME@YOURIP

Click “Save” to remember this for future connecting and “Open” to connect to the server.

4. Update currently installed dependencies

# sudo su
# apt-get update && apt-get upgrade

When prompted for password, input your password. When prompted for confirmation input “Y” and then “Enter”.

Ubuntu may prompt you when the “Grub” package is updated. If prompted, select “keep the local version currently installed” and click “Enter” button.

You will know that installing is complete when “[email protected]:” appears on the screen again.

When update is complete, you are ready to install Nginx server.

1.5. Installing Nginx

Nginx is high performance web server. Majority of to 100 most visited websites on the web are powered by Nginx.

Nginx makes the difference with its fast static files caching, improved website delivery speed by making use of HTTP/2 protocol, saving bandwidth by high compression, enhanced security with HTTP, TLS 1.2 and much more!

Instead of stable version from official Ubuntu repository, in this tutorial we will be installing mainline version.

Every few months when some version of Nginx is tested enough and all bugs are fixed, it gets released as stable version.

Mainline is most recent version of Nginx with all latest features. It’s recommended for use by Nginx team. In this version some small bugs may exist, but not so critical that it can harm your website security and performance in any way.

Follow these instructions to get it on your server.


1. Add Nginx repository signature key

To eliminate warnings during installation and to confirm official Nginx repository it’s necessary to add official Nginx key to apt program keyring.

Go back to PuTTY and create new file called “nginx_signing.key” by issuing following commands:

# sudo nano nginx_signing.key

Go to the browser and visit official Nginx signing key page Select all text that’s on the page and copy it.

To copy the key (when on the page) click:

On keyboard:
“CTR” + “A” – to select everything “CTRL” + “C” – to copy selection

Paste contents of Nginx signing key inside by pressing right click of mouse inside PuTTY.

Save and exit the file:

On keyboard:
“CTRL” + “X”, “Y” and then “ENTER” – to exit and save contents of the file.

To add key from recently created file issue following:

# sudo apt-key add nginx_signing.key

Key successfully added!

2. Add Nginx packages to sources list

To add latest Nginx packages  issue following commands:

# sudo nano /etc/apt/sources.list

Go to the bottom of the list and paste following at the end:

deb http://nginx.org/packages/mainline/ubuntu/ zesty nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ zesty nginx

*Note: use keyboard arrows to position cursor in the file. To paste contents inside of the file use right click of the mouse.

To exit and save the file press on keyboard:
“CTRL” + “X” , “Y” and then “ENTER”.

3. Update packages

Before any installation it is good to update current packages:

# sudo apt-get update

4. Install Nginx

Finally issue command to install nginx:

# sudo apt-get install nginx

5. Confirm installation

Confirm that latest version of Nginx is installed by checking currently installed version:

# nginx -v

If you see version 1.13.8 or higher, you are OK!

Restart Nginx with:

# sudo service nginx restart

Now, if you type in IP of your server in the browser, “Welcome to Nginx!” default page should be up! 🙂

1.6. Installing MySQL

MySQL is database management system. It is required for WordPress in order to work. WordPress uses it to save and restore website data from a database.

Later in one of next steps, your website database will be installed (in case of new WordPress installation) or restored (in case of transfer from another hosting) inside of MySQL.

Lets install MySQL to the server.


1. Install MySQL

Run installation command:

# sudo apt-get install mysql-server

When prompted confirm your installation with “Y” and “Enter”.

You will be asked input your MySQL root user password.

Type in your password and click “Enter”.

You will be asked to confirm the password.

Type it again and you are done!

2. Secure MySQL

MySQL comes with some insecure default.

Run following command to override defaults to secure your MySQL database engine:

# mysql_secure_installation

Input previously set root password.

When prompted:

Press enter to skip installing “VALIDATE PASSWORD” plugin.

Press enter to skip changing root password.

Press “Y”  and “Enter” to remove anonymous users.

Press “Y”  and “Enter” to disallow root login remotely.

Press “Y” and “Enter” to remove test database and access to it.

Press “Y” and “Enter” to reload privilege tables now.

Your MySQL installation is secure.

Lets speed up your website with fresh PHP 7.2 installation!

1.6. Installing PHP 7.2

PHP is in charge for translating your WordPress website code into HTML code to be shown to visitors.

To squeeze website speed out of PHP, in this guide I will be showing you how to install latest stable version of PHP, PHP 7.2.

It is proven that with every update of PHP, WordPress websites load faster. PHP 7.2 will give your website additional boost over your competitors since many websites don’t upgrade their PHP.

Let’s install PHP 7.2 on your server.


1. Install software properties common package

PHP 7.2 is still not part of official Ubuntu repository. This will allow you to install latest version of PHP.

# sudo apt-get install software-properties-common

Confirm installation with “Y” and “Enter”.

2. Add PHP 7.2 repository

Run to add PHP 7.2 repository so you can install it:

# sudo add-apt-repository ppa:ondrej/php

Some big pile of text may appear as soon as you activate the command. Just click “Enter” on the keyboard to confirm installation.

Run to update packages:

# sudo apt-get update

3. Install PHP 7.2

Run to install PHP 7.2:

# sudo apt install php7.2

If prompted, type “Y” + “Enter” to confirm installation.

4. Install PHP 7.2 modules required by WordPress

Run to add PHP modules required by WordPress:

# sudo apt install php7.2-common php7.2-cli php7.2-fpm
# sudo apt-get install php-pear php7.2-curl php7.2-dev php7.2-gd php7.2-mbstring php7.2-zip php7.2-mysql php7.2-xml

If prompted, type “Y” + “Enter” to confirm installation.

5. Secure PHP

Prevent users from executing unwanted scripts.

Run to edit your PHP.ini configuration file:

# sudo nano /etc/php/7.2/fpm/php.ini

Find “;cgi.fix_pathinfo=1” line.

Change “1” to “0” and uncomment the line by removing “;”.

Change to “cgi.fix_pathinfo=0”.

To save changes click “CTRL” + “X”, confirm save with “Y” and “Enter”.

While you are here, tweak php.ini settings to match WordPress requirements.

Run again to enter inside php.ini file:

# sudo nano /etc/php/7.2/fpm/php.ini

Find following lines and edit them to match following:

max_execution_time 60
memory_limit 256M 
post_max_size 64M 
upload_max_filesize 64M

To save changes click “CTRL” + “X”, confirm save with “Y” and “Enter”.

Run to restart PHP:

# sudo service php7.2-fpm restart

6. Confirm that PHP works

Run to open nginx.conf:

# sudo nano /etc/nginx/nginx.conf

Change user from nginx to www-data.

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to open default.conf:

# sudo nano /etc/nginx/conf.d/default.conf

Add red parts of the code to your config file:


   root /var/www/html;

   location / {
       root /usr/share/nginx/html; #delete this line
       index index.php index.html index.htm;


   # pass the PHP scripts to FastCGI server listening on
   location ~ \.php$ {
       root html; #delete this line
       fastcgi_pass   unix:/run/php/php7.2-fpm.sock;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
       include        fastcgi_params;


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart nginx:

# sudo service nginx restart

7. Create test info file

Run to create info.php file:

# sudo nano /var/www/html/info.php

Add following to the file:


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

8. Open test info file in the browser

Open your browser and navigate to:


You should see following screen:

9. Remove test info file

Run to remove info.php:

# sudo rm /var/www/html/info.php

Step #2: Connect Domain to Cloudflare – Cut DNS Lookup Load Time

First step, towards fast and secure website, is connecting a domain name you just bought with fast and secure DNS provider!

There are three important benefits (out of many) you get by going with Cloudflare:

Fast DNS lookup speeds

First time, when user is interacting with your website, whether directly typing domain name in browser address bar or clicking on a link on Google search results, domain name has to be linked to a server IP address where your website is hosted.

This is known as DNS lookup time. It’s measured in milliseconds.

You may think few hundred milliseconds doesn’t matter, but keep in mind that visitor still isn’t connected to your server.

And, if website is slow on connection, everything that you do after, doesn’t count. Your website will look slow in the eyes of the visitor.

Even though DNS lookup is done only on initial connection, good DNS provider with ultra fast DNS lookup speed will ensure that your website loads fast on first interaction with visitor.

First impression is very important. Every millisecond counts!

With Cloudflare you get real website speed for free!

Advanced website security

Cloudflare sits in between the server that your website is hosted on, and visitors browser who is trying to access your website.

That means that every user who wants to visit your website has to pass through Cloudflare system, even hackers and spammers.

That being said, Cloudflare has systems in place to easy fight those unwanted visitors.

Moreover, if your website gets attacked by DDoS attack (Distributed Denial of Service), in just few clicks within your Cloudflare dashboard.

There is more:

To take advantage of HTTPS protocol, you get free SSL certifiicate signed by Cloudflare to additionally boost your security and SEO.

HTTPS enables you to take advantage of HTTP/2 + SPDY parallel resource download which makes your website load even more faster!

Cloudflare origin caching

The Cloudflare CDN network is powered by 122 data centers (and counting) around the world. In just one click you can offload your website data to Cloudflare servers.

By doing that, you save your server resources. This gives you a chance to go with cheaper hosting and makes your website even faster since visitors are pulling website data from servers closer to them.

Free of charge worldwide CDN!


Read more about setting up Cloudflare CDN and caching on Caching step of this guide.

Lets start with speeding up your website by adding it to Cloudflare!


1. Add new website

Create account and click “+ Add Site” to set up website on Cloudflare.

 2. Cloudflare domain scanning

Cloudflare needs additional information about your domain name. Let them scan your domain name.

Type in your website domain name into the form field and click “Begin Scan“.

When scanning is complete continue the process by clicking on “Continue Setup” button.

3. Verify domain DNS records

Nothing special here.

Click “Continue” button to go to the next step.

4. Select Cloudflare plan

This is important!

I recommend starting with free plan, and, if needed, upgrade to PRO plan later.

Even free plan would give your website significant speed boost. Think of what can paid plan do?

It is getting more and more interesting… Right?! 🙂

There are some users who would definitely want to take advantage of Cloudflare paid plans.

Until the end of this guide you will know which category your website belongs to.

Lets continue with the process.

5. Change domain nameservers

One more step and you are done!

This will  give you full access to all domain name settings directly in Cloudflare dashboard. (and boost your website speed)

To port your domain name to Cloudflare there is only left to update your current domain nameservers with the new ones provided by Cloudflare.

To do that, copy Cloudflare nameservers (screen above), and paste them as a custom nameservers in your domain name control panel.

UI design of domain name control panel of each domain name provider will differ.

Check image below to see how it looks on domain registrar that we use. It should be quite similar in others too!

6. Re-check domain name servers

Final step is to re-check nameservers so that Cloudflare can pick them up to configure your domain in the background.


Your domain is on Cloudflare DNS!

First step to lightning fast WordPress site is finished, 8 to go!

7. Connect server and domain name via Cloudflare

Now when your domain is connected, it’s to connect your server to Cloudflare.

Navigate to “DNS tab in Cloudflare navigation menu.

Add A record. (or find and edit existing one)

In name field put your domain name. (e.g. example.com)

In IPv4 address put your Linode server IP. (i.e.

TTL automatic.

To confirm connecting server and your domain in Cloudflare, click “Add Record” button.

7. Redirect www domain name to non-www with Cloudflare

www domain name is your domain name with www prefix – www.google.com

non-www domain name is your domain name without www prefix – google.com

Nowadays most of the time users type in browser your domain name without www prefix. To prevent additional time needed for redirection, it’s obvious to use non-www domain sa primary domain.

Even though redirection is done on DNS level, and it’s really fast (faster than server level), I would still go with non-www domain name.

Every millisecond really important at the moment when no content is shown in the browser yet.

To do the redirection, add CNAME record.

In name field put www.

In IPv4 address put your domain name. (i.e. example.com)

TTL automatic.

Note: If you see “A” record with name “www”, delete it by pressing “X” button on that record.

8. Add your domain name to Nginx default.conf file

Go back to PuTTY and run to open default.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Replace “localhost” with your domain name:

server {
 listen 80;


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx:

# sudo service nginx restart

Step #3: PHPMyAdmin installation

PHPMyAdmin is required for managing MySql database. Also, it will be used to restore your WordPress database from backup file to the server.


1. Update current and install missing packages

# sudo apt-get update
# sudo apt-get install phpmyadmin php7.2-mbstring php7.2-gettext
# sudo apt-get install mycript

During the installation, you will be prompted for some information.

Whenever you are prompted to confirm package installation, press “Y” and “Enter”.

Installation wizard will ask you which web server you would like the software to automatically configure. Since you use Nginx, neither apache2 or lighttpd are available options. To skip this, hit TAB, and than confirm with “Enter”.

The next prompt will ask if you would like dbconfig-common to configure a database for PHPMyAdmin to use. Pick “YES”.

You will need to enter the MySQL password that you configured during the MySQL installation to allow these changes.

2. Activate mbstring module

# sudo phpenmod mbstring

3. Create symbolic link

Run to connect PHPMyAdmin installation folder with the server:

# sudo ln -s /usr/share/phpmyadmin /usr/share/nginx/html

4. Make PHPMyAdmin accessible from the browser

Run to open default.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Add following code at the end of server block, just before last “}” tag:

        location /phpmyadmin {

                # auth_basic "Admin Login";
                # auth_basic_user_file /etc/nginx/pma_pass;

                root /usr/share/nginx/html;
                index index.php index.html index.htm;
                location ~ ^/phpmyadmin/(.+\.php)$ {
                        try_files $uri =404;
                        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                        include fastcgi_params;
                        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
                        root /usr/share/nginx/html;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx:

# sudo service nginx restart

5. Confirm that PHPmyAdmin is working

Navigate your browser to:


If everything is OK, you should see this screen:

You can log in to PHPMyAdmin with username “root” and MySQL password which was set when MySQL was installed.

6. Secure PHPMyAdmin

PHPMyAdmin works now, but it’s good to additionally protect it.

There are two things you can do to prevent anyone except you to interact with your MySQL data through PHPMyAdmin.

Lets implement those steps and enhance your PHPMyAdmin security.

6.1 Change default PHPMyAdmin location

First, we will change default initial link to PHPMyAdmin from http://YOURWEBSITE.com/phpmyadmin to http://YOURWEBSITE.com/anythingyouwant.

This is amazing security measure because if hackers don’t even know your PHPMyAdmin link, they can’t hack it.

Smart, right? 🙂

Run to rename your phpmyadmin symbolic link:

# cd /usr/share/nginx/html
# sudo mv phpmyadmin anythingyouwant

Run to open Nginx default.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Edit red parts of the file:


location /anythingyouwant {

# auth_basic "Admin Login";
# auth_basic_user_file /etc/nginx/pma_pass;

root /usr/share/nginx/html;
 index index.php index.html index.htm;
 location ~ ^/anythingyouwant/(.+\.php)$ {
 try_files $uri =404;
 fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


location ~* ^/anythingyouwant/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
 root /usr/share/nginx/html;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server to pick up changes:

# sudo service nginx restart

Visit your new PHPMyAdmin link in browser:


6.2. Protect PHPMyAdmin with authentication gate

Even though PHPMyAdmin has login protection, everyone knows that “root” user exists.

That being said, it is good to set up additional line of login protection before even user reaches original PHPMyAdmin login screen.

To do that pick your login username and password. Remember it.

Run this to encrypt your password:

# openssl passwd

Type in your password. Repeat password.

Your password is encrypted!

Run create authentication file:

# sudo nano /etc/nginx/pma_pass

Add your username and encrypted password to the file (e.g. demouser:GWCQERalTooYo):


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Add link to the authentication file in Nginx default.conf:

# sudo nano /etc/nginx/conf.d/default.conf

Check PHPMyAdmin block and uncomment (or add) red text:

location /anything {

               auth_basic "Admin Login";
               auth_basic_user_file /etc/nginx/pma_pass;

                root /usr/share/nginx/html;
                index index.php index.html index.htm;
                location ~ ^/anything/(.+\.php)$ {
                        try_files $uri =404;
                        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                        include fastcgi_params;
                        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


                location ~* ^/anything/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
                        root /usr/share/nginx/html;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server to pick up changes:

# sudo service nginx restart

Get back to to browser and visit http://YOURDOMAINNAME/anythingyouwant

New “Admin login” popup window should appear.

You can get through it with username and password that you recently set in pma_pass file. (username:password)

Done! Your PHPMyAdmin is secure!

Lets finally set up your WordPress site.

Step #4: WordPress installation (or transfer)

In this step I will assume that you already have WordPress website hosted with some other hosting provider.

For you who want to start with new installation of WordPress, download WordPress from official download page and continue.

To move your site over to Linode you will need to back up your files and database from current hosting.

You can use our step by step WordPress website backup guide (still not created). Backup your website files and database manually.

When you have your backup sitting on your desktop, proceed with this guide to restore it on the server.


1. Transfer MySQL database

1.1. Enable serveruploads up to 100 mb 

Run to open server Nginx.conf file:

# sudo nano /etc/nginx/nginx.conf

Add following red line to http server block:

http {
        client_max_body_size 100m;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server to pick up changes:

# sudo service nginx restart

1.2. Create new database

Got to your favorite browser and navigate to your secret PHPMyAdmin link. (http://YOURDOMAINNAME/SECRETPHPMYADMIN)

If you didn’t secure your PHPMyAdmin, go back to previous step.

In left sidebar click on “New” and then fill in the fields:

  • Database name – name of your database (e.g. kraljevstvomeda)
  • Collation – utf8_general_ci

Click on “Create” button to finish the process.

NOTE: Some error may show on initial page load. Just click “Ignore”.

1.3. Import your website database backup

NOTE: If you correctly exported your WordPress database, you should have DATABASENAME.sql file on your desktop.

(1) To import your WordPress database via PHPMyAdmin, click on your database name in the sidebar.
(2) Click “Import” in top navigation bar.
(3) Click on “Choose file” button and choose YOURDBNAME.sql file from your system.
(4) Uncheck “Partial import” checkbox.
(5) Click “Go” button to start the import.

Have you got the same screen? That’s good!

1.4. Add new user and give database privileges

Since username and password of MySQL user will be exposed in WordPress config, it is good to create new user for every WordPress database instead of using root.

To create new user navigate to your database page by clicking on the database name, in left sidebar.

Click on “User accounts” in top navigation bar. Then, click “Add user account“.

Type in your desired username and password.

To add user, click “Go” button in bottom right corner of the page.

2. Transfer WordPress files (with Filezilla)

At the moment your WordPress files should be on your desktop inside a folder.

Lets upload them to the server.

2.1. Install FileZilla FTP client

FileZilla is application which will enable you to upload your WordPress website files to the server. It is easy due to simple visual interface.

Download FileZilla here and install it on your PC.

2.2. Upload files

Open FileZilla and click on “Site manager” icon. (1)

(2) To add your server, click on “New site” button.
(3) Name your connection (e.g. domain name)
(4) As a host name, put your server IP
(5) Protocol should be “SFTP – SSH File Transfer Protocol
(6) Logon type is “Normal“. As username put “root” and password, your “root” user password.
(7) To log in click “Connect” button.

In “Remote site:” field  put:


Click “Enter” to enter into the requested folder. (1)

Drag and drop folder with your WordPress files inside area (2).

NOTE: Your WordPress files should be inside sub-folder within html folder. (like this: /var/www/html/YOURWORDPRESSFOLDER/[WordPress files and folders])

File upload may take couple of minutes.

When files are uploaded continue with fixing WordPress file permissions.

2.3. Fix WordPress file permissions and ownership

In FileZilla, inside your sites folder, select all folders only.

Right click on them and click on “File permissions“.

In file permissions window, as “Numeric value” put 755.

Check “Recurse into subdirectories” and select “Apply to directories only“. Click OK.

This will take couple of minutes.

When process is over, select all folders and files inside your sites folder.

Right click on selection, click again on “File permissions“.

This time as “Numeric value” put 644.

Check “Recurse into subdirectories” and select “Apply to files only“. Click OK.

This may take couple of minutes.

Next, go to Putty and run to add ownership of files to your user (sudo user):

# sudo chown -R www-data:www-data /var/www/html/YOURWORDPRESSFOLDER

NOTE: YOURUSERNAME – user you use to log in via Putty

Run to make all files and folders created inherit group ownership:

# sudo find /var/www/html/YOURWORDPRESSFOLDER -type d -exec chmod g+s {} \;

Run to give WordPress permissions to install new themes and plugins:

# sudo chmod g+w /var/www/html/YOURWORDPRESSFOLDER/wp-content

Run to give write access to WordPress to themes and plugins folders directly:

# sudo chmod -R g+w /var/www/html/YOURWORDPRESSFOLDER/wp-content/themes 
# sudo chmod -R g+w /var/www/html/YOURWORDPRESSFOLDER/wp-content/plugins

3. Connect WordPress files to MySQL database

Run to open wp-config.php file:

# sudo nano /var/www/html/YOURWORDPRESSFOLDER/wp-config.php

Edit following lines:


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

4. Edit Nginx configuration for WordPress CMS

This is one of the most important things to do.

In this step you will set up foundations of your website server config file. As configured now, this will be semi-final version of config file which will change only slightly later to secure website by adding SSL certificate or to add server caching.

Run to edit your Nginx default.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Edit your config file to match this configuration (you can delete everything currently inside config and copy this one):

server {

        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html/YOURFOLDERNAME;

        index index.php index.html index.htm index.nginx-debian.html;

        server_name YOURDOMAINNAME;

        access_log /var/log/nginx/YOURDOMAINNAME.access.log;
        error_log /var/log/nginx/YOURDOMAINNAME.error.log;

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        location ~ \.php$ {
                fastcgi_pass   unix:/run/php/php7.2-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www/html/YOURFOLDERNAME$fastcgi_script_name;
                include        fastcgi_params;

        location ~ /\.ht {
                deny all;


            auth_basic "Admin Login";
            auth_basic_user_file /etc/nginx/pma_pass;

            root /usr/share/nginx/html;
            index index.php index.html index.htm;
            location ~ ^/YOURPHPMYADMINLINK/(.+\.php)$ {
                    try_files $uri =404;
                    fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                    include fastcgi_params;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


            location ~* ^/YOURPHPMYADMINLINK/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
                    root /usr/share/nginx/html;


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server:

# sudo service nginx restart

Now, if visit your domain, your website should load. 🙂

If your WordPress website was configured to run on https, you may see “Too many redirects” error. If you use Cloudflare, turn off SSL in “Crypto” settings tab. Or you can just ignore this and proceed with guide, since you will be activating SSL in next step of this guide anyway.

Check your website that everything loaded correctly. If your website is broken, go in to wp-admin panel and go to general settings. Make sure that URL has http in front of your domain name. (http://your_domain_name.com) instead of https.

You are good to go. Let’s proceed.

PS. If you need help, feel free to contact us via contact page or via comments on this post. I am glad to help.

Step #5: SSL Configuration

Making your website to run on HTTPS is not just about speed. It’s much more!

Yes, with HTTPS your website is more secure since data is encrypted and Google likes it. But, HTTPS gives you possibility to run your website via enhanced HTTP/2 network protocol.

Now, your website assets (images, js files, css files etc.) are downloaded from server one by one. When one is complete downloading, another one starts and so on. If one in front is stuck or is slow, all other wait for it to finish. Your website loads slow.

HTTP/2 is special because your visitors can download multiple assets in the same time. Simultaneous download, much more efficient and faster!

Follow the instructions to configure SSL, HTTPS and HTTP/2 for your website.


1. Request free SSL certificate from Cloudflare

Go to your Cloudflare dashboard and click on Crypto button from top navigation menu.

Scroll down to “Origin Certificates” and click on “Create Certificate” button.

When pop up window shows, go with defaults and click “Next” button to request SSL certificate.

Your origin certificate code and private key code should appear. In next step of this guide you will be installing those certificates on the server.

Next, make two simple text documents on your desktop and copy codes that you see in your screen in those text documents.

You can name them “Origin certificate” and “Private key“.

2. Install and configure certificate on the server

To install your certificate to the server, open Putty.

Run to create “SSL” directory:

# sudo mkdir /etc/nginx/ssl

Run to create origin certificate file on the system:

# sudo nano /etc/nginx/ssl/YOURDOMAINNAME.com.pem

Copy Origin Certificate code from text document and paste it with right click inside Putty.

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to create private key file on the system:

# sudo nano /etc/nginx/ssl/YOURDOMAINNAME.com.key

Copy Private Key code from text document and paste it with right click inside Putty.

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to create dhparam.pem file:

# sudo nano /etc/nginx/ssl/dhparam.pem

Enhance SSL configuration with dh parameters.

Copy following inside dhparam.pem file:


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Now, add links of just created files to server config of your website.

Run to enter in Nginx default.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Remove following lines from your configuration:

        listen 80 default_server;
        listen [::]:80 default_server;

And, add red lines to your server block configuration:

server {

        listen 443 ssl default_server;
        listen [::]:443 ssl http2 default_server;

        ssl     on;
        ssl_certificate         /etc/nginx/ssl/YOURDOMAINNAME.com.pem;
        ssl_certificate_key     /etc/nginx/ssl/YOURDOMAINNAME.com.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        ssl_dhparam  /etc/nginx/ssl/dhparam.pem;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server:

# sudo service nginx restart

3. Switch from http to https

Now it’s just left to configure SSL in Cloudflare.

Go to Cloudflare dashboard of your website and navigate to “Crypto” tab in top navigation menu.

Set SSL to “Full (strict)” mode.

Configure following:

Always use HTTPS: On
Authenticated Origin Pulls: On
Require Modern TLS: On
Opportunistic Encryption: On
TLS 1.3: Enable+0RTT
Automatic HTTPS Rewrites: On

Visit your website and it should load over HTTPS! 🙂

To finish this SSL/HTTPS configuration, navigate to your WordPress admin panel.

Go to Settings > General and change URL prefixes to “https://”.

Your website is super safe due to SSL connection and much faster due to HTTP/2 protocol. Congratulations!

This was just basic speed optimization!

Stuff that are coming next are secrets that will make your WordPress website load in less that 1 second as you have seen at the beginning of the post!

Keep up to abuse those secrets to your advantage!

Step #6: Brotli and GZip Compression

File size is one of the factors that affect website speed the most. This is true by the fact that when visitor request to your server is made, files are being transferred from your server to their browser.

This means that if you want your website to be faster, file size needs to be reduced. This can be achieved by compression on the server right before files are transferred to the visitor’s browser.

Gzip compression can reduce size of some files even up to 90%. It’s definitely one of the best and easiest optimizations that you can do to speed up your WordPress website.

In this guide I will show you how to enable Gzip compression between your server and Cloudflare servers, while Brotli compression will be used between Cloudflare servers and visitors.


1. Enable Gzip compression on Nginx server

By default, gzip compression isn’t enabled on the server. To enable it on your Nginx server follow next steps.

Run this to open your server Nginx config:

# sudo nano /etc/nginx/nginx.conf

Add red lines to your config:


        sendfile        on;
        tcp_nopush     on;
        tcp_nodelay on;
        types_hash_max_size 2048;
        keepalive_timeout  65;

        # Gzip Settings

        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_min_length 256;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;

    include /etc/nginx/conf.d/*.conf;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to restart Nginx server:

# sudo service nginx restart

Check if Gzip compression is running by typing in your website domain name on GIDZip Test.

Note: Domain name must be full, together with ‘https://’ prefix. (i.e. (https://yourdomain.com)

Gzip compression is up and running! 🙂

2. Enable Brotli compression on Cloudflare

Cloudflare supports Brotli compression between it’s servers and your visitors. It’s impacts file size similar to Gzip compression, in some cases even better.

Let’s activate it.

Go to Performance tab for your domain in Cloudflare.

Scroll down to “Brotli” and activate it! Done!

Step #7: Caching (WordPress Speed Optimization Secrets)

Caching makes big difference between average and ultra fast websites. This is secret of all secrets when it comes to website speed.

All data which isn’t changing frequently, like articles on blogs and pages on business sites, can be cached. Caching will make your data stored in simplest format as close to your visitor so it can be accessed as fast as possible.

When page is visited, this is whats going on behind the scenes:

  • request is received by the server PHP code is compiled and executed
  • data is pulled from database
  • HTML code is generated
  • HTML is served by server to the browser.

If each step above is cached on first visit, every other visitor skips this whole process and gets data served as fast as possible.

Let’s speed up your website by implementing cache on PHP code, database, server, Cloudflare and in visitors browser!

A lot things to do, but it’s worth it.

7.1. PHP Bytecode Cache (PHP OPCache)

On every request, when PHP code is being executed, it has to be compiled to opcode, machine language. This translation of PHP code to machine language takes a bit of time.

To reduce this waiting time on every request, code can be compiled only once (on first request) and stored in memory for future use.

All future requests can pull this directly from memory.


This is how to configure OPCache (aka. Bytecode):

Run to open php.ini file:

# sudo nano /etc/php/7.2/fpm/php.ini

Change following lines:

from ";opcache.enable=0" to "opcache.enable=1"
from ";opcache.memory_consumption=128" to "opcache.memory_consumption=128"
from ";opcache.max_accelerated_files=10000" to "opcache.max_accelerated_files=10000"
from ";opcache.revalidate_freq=2" to "opcache.revalidate_freq=240"

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Run to enable OPCache:

# sudo phpenmod opcache

Restart PHP 7.2 and Nginx for changes to take effect:

# sudo service php7.2-fpm restart
# sudo service nginx restart

You can create test info.php file to confirm that everything is up and running:

# sudo nano /var/www/html/YOURFOLDERNAME/info.php

Copy following in the file:


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

OPCache has been successfully installed!

Run to remove info.php:

# sudo rm /var/www/html/YOURFOLDERNAME/info.php

7.2. Redis Database Caching

Redis is in-memory data structure store.

Simply, you can see Redis as temporary database inside memory (RAM).

Temporary means that data is stored inside memory for some specified period of time, or until server is restarted.

Only first request gets data all the way from the database while all next requests pull the data from the memory. Memory is lightning fast what makes that data is returned almost instantly.

You can define how long data is stored and when should fresh data be requested from MySQL database.

Let’s speed up your database.


7.2.1. Install and build required dependencies

Run to update packages:

# sudo apt-get update

Run to build dependencies:

# sudo apt-get install build-essential tcl

If prompted with question, type “Y”, and then “Enter”.

7.2.2. Download, compile and install Redis

Run to change location to temp folder:

# cd /tmp

Run to download latest stable version of Redis:

# curl -O http://download.redis.io/redis-stable.tar.gz

Run to unpack downloaded file:

# tar xzvf redis-stable.tar.gz

Move to unpacked folder:

# cd redis-stable

Run to compile Redis:

# make

Run to test compiled build:

# make test

Testing might take 2-5 min. All test should pass with green “[ok]” confirmation text.

At the end of test run, message “All tests passed without errors!” should appear.

When testing is complete, run to install Redis:

# sudo make install

7.2.3. Redis configuration

Run to create Redis config directory:

# sudo mkdir /etc/redis

Run to copy configuration sample in created folder:

# sudo cp /tmp/redis-stable/redis.conf /etc/redis

Run to open config file:

# sudo nano /etc/redis/redis.conf

Edit red text inside config (currently no, change to systemd):


# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised systemd

# If a pid file is specified, Redis writes it where specified at startup
# and removes it at exit.


Next, find dir (working directory) and edit red text:


# The working directory.
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# The Append Only File will also be created inside this directory.
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis

################################# REPLICATION #################################


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

7.2.4. Inform system about Redis (create systemd Unit file)

Run to create redis.service file:

# sudo nano /etc/systemd/system/redis.service

Copy and paste following text into the file:

Description=Redis In-Memory Data Store

ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

7.2.5. Create Radis user, group and directories

Run to create Redis user and group:

# sudo adduser --system --group --no-create-home redis

Run to create /var/lib/redis directory:

# sudo mkdir /var/lib/redis

Give Redis user ownership to created directory:

# sudo chown redis:redis /var/lib/redis

Prevent regular users to access created directory:

# sudo chmod 770 /var/lib/redis

7.2.6. Start and test Redis

Run to start Redis service:

# sudo systemctl start redis

Run to check status of Redis service:

# sudo systemctl status redis

If everything is OK, you should see green active flag in console.

Run Redis command line tool to test the service:


Run to ping the service:> ping

You should see following output:


Run to set test caching variable inside Redis:> set test "It's working!"

You should get response OK.

Run to retrieve cached text from variable:> get test

You should get response “It’s working!”.

Run to exit from Redis command line tool:> exit

Run to restart Redis:

# sudo service redis restart

Now enter in Redis command line tool again:

# redis-cli

And, run to return test variable again:> get test

You should get the same response “It’s working!”.

Run to exit from Redis command line tool:> exit

Run to enable Redis to run at start:

# sudo systemctl enable redis

This should be returned as a response “Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /etc/systemd/system/redis.service.”.

Redis successfully installed on the server!

7.2.7. Configure WordPress connection settings

In next step you will be installing plugin which will control usage of Redis in WordPress.

If you go to plugins installation page you will get message wired “Connection information message”.

WordPress doesn’t know how to download plugins to the server.

Let’s fix this.

Go to Putty and run to open your website wp-config file:

# sudo nano /var/www/html/YOURWEBSITEFOLDER/wp-config.php

Go to the bottom of the file and copy following:

define('FS_METHOD', 'direct');

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

7.2.8. Install Redis plugin in WordPress

Now go to your website Admin page > Plugins > Add new.

Type in search “Redis Object Cache“, download and install the plugin.

Go to the plugin page and enable Redis cache.

Done! Your website is faster due to database object caching with Redis! 🙂

7.3. Nginx Server Caching

Redis caches everything that is being returned from the database to PHP. PHP builds HTML page out of data pulled from database or, if data is cached, from Redis.

When HTML is ready, it’s pushed by PHP to Nginx which serves content to a visitor.

In this step, you will configure Nginx server caching.

This means that Nginx will cache HTML code of each page returned by PHP for even faster response to a visitor request.

When request is made, only first visitor will wait for server to pull data from the database or Redis, and for PHP to process it. When HTML response comes to Nginx it will be cached in RAM.

Every next request will get a response directly from Nginx with HTML pre-generated by first user. But, dynamic requests like POST and /wp-admin/ won’t be cached.

If request is cached, database and PHP won’t be touched at all. Much faster response and more efficient use of server resources!

This way your server will be able to handle much more requests per second. With same server resources you can serve much more visitors.

Lets do it.


7.3.1. Configure Nginx caching

This configuration works for WordPress blogs and WooCommerce shops.

Run to open nginx.conf file:

# sudo nano /etc/nginx/conf.d/default.conf

Copy this at the top of your file before first server block to define cache path and zone name:

fastcgi_cache_path /var/run/nginx-cache-YOURWEBSITENAME levels=1:2
keys_zone=YOURCACHENAME:100m inactive=60m use_temp_path=off;

fastcgi_cache_key "$scheme$request_method$host$request_uri";

Add red lines inside location ~ \.php block:


 # pass the PHP scripts to FastCGI server listening on
        location ~ \.php$ {
           fastcgi_pass   unix:/run/php/php7.2-fpm.sock;
           fastcgi_index  index.php;
           fastcgi_param  SCRIPT_FILENAME  /var/www/html/kraljevstvomeda$fastcgi_script_name;
           include        fastcgi_params;

                fastcgi_cache_bypass $skip_cache;
                fastcgi_no_cache $skip_cache;
                fastcgi_cache YOURCACHENAME;
                fastcgi_cache_valid  60m;

                fastcgi_cache_use_stale updating;
                fastcgi_cache_lock on;
                fastcgi_cache_valid 200 302 206 1h;
                fastcgi_cache_valid 301      1h;
                fastcgi_cache_valid any      1h;


Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

7.3.2. Exclude dynamic requests from caching

To prevent server to cache dynamic requests open default.conf file again:

# sudo nano /etc/nginx/conf.d/default.conf

And, add following red commands:

        # Logging
        access_log /var/log/nginx/yourwebsitename.access.log;
        error_log /var/log/nginx/yourwebsitename.error.log;

        set $skip_cache 0;

        # POST requests and URLs with a query string should always go to PHP
        if ($request_method = POST) {
                set $skip_cache 1;

        if ($query_string != "") {
                set $skip_cache 1;

        # Don't cache URIs containing the following segments
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                set $skip_cache 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 $skip_cache 1;

        # Don't cache pages with woocommerce cart info when items are in cart
        if ( $cookie_woocommerce_items_in_cart = "1" ){
            set $skip_cache 1;

        # Don't cache uris containing the following segments
        if ($request_uri ~* "(/basket.*|/cart.*|/my-account.*|/checkout.*|/addons.*|/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
            set $skip_cache 1;

        location / {
                try_files $uri $uri/ /index.php$is_args$args;

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Restart server to make changes active:

# sudo service nginx restart

7.3.3. Install plugin for automatic cache purge

To make sure that every time when changes to posts and pages are made to be visible instantly to the visitors, cache must be cleared.

There is a plugin called “Nginx Cache” which clears cache automatically for posts and pages that are changed through WordPress backend.

To install it, go to plugin installation page (https://yourdomainname/wp-admin/plugin-install.php).

Search for “nginx cache”. InstallNginx Cache” plugin by Till Kruss and activate it.

When activated, go to plugin administration page. Click on “Nginx” button in top navigation bar.

In “Cache zone” text field put following:


Check “Automatically flush the cache when content changes” checkbox and click “Save” button.

From now on, this Nginx cache purge plugin will automatically clear cache when something is changed on your website.

Server caching configured successfully.

7.4. Cloudflare Edge Caching

At the moment, most requests that are reaching your server aren’t hitting database or PHP since the server is serving cached content from memory.

All load that was on your database is offloaded to Nginx server. Even better, you can offload everything to 3rd party servers like Cloudflare edge servers.

By caching your content on Cloudflare edge servers, your server is offloaded so it can respond to much more requests per second than before. And, Cloudflare edge servers are much closer to the visitor what makes page load times extremely fast.

If you run a blog or a business website with “static” content that doesn’t change on every request, like blog posts and pages, it is good to cache whole HTML pages on Cloudflare servers. All that, free of charge.

On the other hand, if you run an eCommerce web shop on WooCommerce, to take advantage of full page cache you must be paid Enterprise Cloudflare customer.

Enterprise membership allows you to prevent Cloudflare serving full page cache to a visitor on specified browser cookie.

This is the only way to prevent Cloudflare to cache WooCommerce content but to serve cached content on all other parts of your website.

WooCommerce websites have dynamic content that changes with every new visitor. For example, if a cached version of a cart or checkout page is served to every visitor, this definitely wouldn’t look good.

To overcome that, Cloudflare Enterprise users have the ability to specify special rules to prevent showing a cached version of a page when a request is made by a visitor with an active WooCommerce cookie in its browser. Simple, but costs a lot ($200 USD/month).

If you are just starting as an eCommerce website, I assume that you are low on budget so I suggest you to skip implementation of full page cache in step 7.4.2.

Don’t be sad, you can still take advantage of basic static Cloudflare cache. 🙂

If you are blog or business site it’s free of charge. You should implement every step by following instructions below.


7.4.1. Configure Cloudflare edge server cache

Basic cache will cache static content of your website on Cloudflare servers. All css and javascripfiles, images, pdf, fonts and documents like docx and pptx are considered as static by Cloudflare.

Navigate to “Cache” tab in your Cloudflare control panel.

Set “Cache level” to “Standard“.

Even though browser cache will be configured in next step, while you are here set Cloudflare “Browser Cache Expiration” to “Respect existing headers“. This is needed so that you can configure browser caching by yourself on server rather than on Cloudflare.

7.4.2. Configure full page cache for ultimate website speed (if WooCommerce, skip this )

Full page cache is real secret when it comes to WordPress website speed optimization. When full page cache is active, Cloudflare will cache, not just all static files, but whole HTML page.

On first request, HTML is generated on your server and saved as a cache on Cloudflare server. On each next request, HTML is almost instantly served to a visitor directly from its closest Cloudflare edge server.

Lets set up Cloudflare full page cache!

Navigate to “Page Rules” tab in your Cloudflare control panel.

Click on “Create Page Rule” to add new full page cache rule.

To activate full page cache on your whole WordPress website, in first field put following:


Then add “Cache Level” setting. First parameter for this setting should be “Cache Everything“.ž

Add new setting, “Edge Cache TTL” and set first parameter “a month“.

Edge Cache TTL setting controls how long should cache be kept on Cloudflare servers. I suggest to go for maximum possible time frame since there is Cloudflare WordPress plugin which will automatically purge full page cache when something ona a page or post is changed via WordPress admin panel.

Click “Save and Deploy” button and you are set.

There is one more step to do. You need to make sure that WordPress admin panel isn’t cached.

To exclude WordPress admin panel from full page cache, create new page rule.

To make this rule active only on your WordPress admin panel, put following in first field:


Add new “Cache Level” setting. Parameter should be “Standard“.

Order, first.

Cloudflare edge server full page cache (aka HTML cache) is successfully configured.

Let’s make sure that cache is automatically cleared when posts and pages are edited.

7.4.3. Install Cloudflare plugin for automatic cache purge

Official Cloudflare plugin will make sure that cache is refreshed every time a change is made on any of your pages or posts via WordPress admin panel.

To install Cloudflare plugin go to to your WordPress admin panel and navigate to install new plugin page.

Search for “cloudflare” and pick the one created by Cloudflare Team.

To configure plugin, go to Settings > Cloudflare in your WP Admin navigation menu.

If you followed this guide from the beginning, you should have your Cloudflare account. Click on “here” button to log into your account.

You will be asked to input your email and Cloudflare API key.

To find API key go to your domain Cloudflare dashboard and click on “Get your API key” button.

An then, in “API Key” section search for “Global API Key” and click “View API Key” button.

Type in your password an copy your API key.

Go back to Cloudflare plugin login page inside WordPress.

Put in your email and paste API key. Click “Save API Credentials“.

When Cloudflare plugin dashboard opens, switch “Automatic Cache Management” to “ON”.

When you change your posts or pages, Cloudflare,  Nginx and Redis cache (server and database cache configured in previous steps) will be purged and changes will be shown to the visitor.

7.5. Browser Caching

Last thing to configure is browser cache.

When visitor makes a request to your website, images and other files are downloaded to be shown in the browser.

Server can instruct browser to store downloaded files for certain period of time. This way you can leverage users browser memory to speed up your website.

This won’t only speed up your pages when visitor makes a repeated request to them (i.e. homepage is visited more than one time in short period of time), but also speed up load time of pages that visitors visits for a first time. Multiple pages most probably consist of same files.

Files once downloaded are stored on visitors PC and when needed are pulled almost instantly. Bam.


Go to Putty.

Run to open default.conf:

# sudo nano /etc/nginx/conf.d/default.conf

Add red code into the file in exact spot as showed here:

        location / {
                try_files $uri $uri/ /index.php$is_args$args;

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }

        # Browser caching
        location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|woff|woff2|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                expires 30d;
                log_not_found off;
                access_log off;

                add_header Access-Control-Allow-Origin *;

        # pass the PHP scripts to FastCGI server listening on
        location ~ \.php$ {

Exit and save the changes with “CTRL” + “X”, “Y” and than “Enter”.

Restart server to make changes active:

# sudo service nginx restart

Browser cache configured!

Step #8: CDN (Content Delivery Network) Cache – Optional

Step #9: Measure and show your results

Measure your website speed with Pingdom website speed test to see how fast your website currently is.

Measure two times from closes location to your server. First measured time will be your website load time without cache.

Second time is the real deal. On second try, cache is populated fully populated. And, that’s how fast your website actually is when served to visitors.

Post your results in the comments below! 🙂

Next step… secrets for even more speed!

Now, when your server is optimized and caching configured, there are still few secrets left that you can do inside WordPress to boost your website speed.

In next post I will show you how to speed up your WordPress site even more by installing and configuring few speed optimization plugins.

When you’re ready, follow our guide WordPress speed optimization with plugins.

Leave a Comment