Magento 2 Quick Start and Common Gotchas

This post is actually the content for a presentation I gave recently at the PHP E-Commerce Leeds/Bradford Meetup.


  1. Introduction
  2. Installing Dependencies
  3. Preparing to Install Magento 2
  4. Installing and Configuring Magento 2
  5. Further Notes and Tips

back to top


In this presentation, we will be getting Magento 2 installed and working. There are many ways you can approach this including choice of Linux distribution, database, web server, PHP version and many more. The following is by no means the only way to approach this task, but it is the way we have chosen at Edmonds Commerce.

In summary here are our choices:

Option Choice
Linux Distribution CentOS 7
Web Server Nginx
Database Percona 5.6
PHP Version 7 (not less than 7.0.6)
PHP OPcache Zend OPcache
Magento Version Latest (2.1 at time of writing)
Magento Installation Type Integrator
Magento Installation Method Command Line

We will write the article on the basis of you already having a clean Centos 7 installation. This could be a Virtual Machine, LXC container or an actual virtual or dedicated server. If you aren’t sure, I’d suggest starting out with VirtualBox as the easiest cross platform way to create local Virtual Machines.

Unless otherwise specified, you can assume the commands provided are to be entered onto a BASH command line terminal on your Linux server.

Note: Where a command has a clear placeholder for your own value, you might want to copy/paste into a text editor and edit the command before you paste it into your terminal

back to top

Installing Dependencies

This section is all about getting you form a basic Linux installation (CentOS in this case) and installing everything that you will need to run Magento 2.

Magento provide some good documentation on Magento 2 requirements which clearly describe what needs to be available. Here we are going to take our basic CentOS machine and get it ready with all the requirements in place.

Basic CentOS Setup

The first thing I’d suggest you do with your CentoOS machine is run a full yum upgrade

yum -y upgrade

Once this is done, it’s time to start installing some basics:

Note: the below is not a complete CentOS setup guide, its a taste of the kinds of things you might want to do. A full guide is beyond the scope of this article.

# some basics
yum -y install epel-release

yum -y install \
    htop \
    iftop \
    curl \
    wget \
    tar \
    vim \
    bash_completion \
    sudo \
    logrotate \
    p7zip \
    yum-utils \

# cron install and start
yum -y install crontabs
service crond start
chkconfig crond on

# install SSH - I leave securing it etc to you
yum install openssh-server
systemctl enable sshd
systemctl start sshd

Note: For a production server, you will need to make sure that sufficient time and effort is put into properly locking it down and securing it, or ensuring that your hosting company has done this for you.

Magento2 User

We now need to create a user that will be the owner of the files of the Magento 2 site. For our purposes, I’m going to call this user magento2.

useradd magento2 -p YOUR_PASSWORD_HERE

We will use this user later on.


Magento requires MySQL 5.6

This is quite a specific requirement and if you try to run it on another version you will see issues so it makes sense just to do what is recommended.

Rather than use original MySQL, we tend to prefer to use Percona which has a reputation for high performance.

Here are some commands to install Percona 5.6

yum -y install

yum -y install Percona-Server-server-56

Then we need to fix an issue with the MySQL socket permissions.

Copy and paste all of the following into your terminal in one go:

mv /usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/mysqld.orig

echo '
# Systemd service file for Percona Server
# # This service file is to start PS just with mysqld_safe

Description=MySQL Percona Server


# Needed to create system tables etc.
ExecStartPre=/usr/bin/mysql-systemd pre

# Start main service

# Dont signal startup success before a ping works
ExecStartPost=/usr/bin/mysql-systemd post
ExecStartPost=/bin/bash -c "chmod 777 /var/lib/mysql/mysql.sock"
# Give up if ping dont get an answer

PrivateTmp=false' > /usr/lib/systemd/system/mysqld.service

systemctl daemon-reload

Then get MySQL running

systemctl enable mysqld

systemctl start mysqld

systemctl status mysqld

Then you need to secure your MySQL installation, set a root password etc. There is a simple way to do this, just run:


You can just hit return for most quesions and accept the (sensible) default actions. The only thing you need to put in is the root password.

Keep track of your root password as you will need that next.

One you have done the MySQL secure installation, you should create a .my.cnf file in the home folder of any users you want to be able to connect to mysql easily. For example root and magento users.

First - create a BASH variable with your MySQL root password.


Then run the following to create your .my.cnf files

echo "
"   > ~/.my.cnf
chmod 600 ~/.my.cnf

echo "
"   > /home/magento2/.my.cnf
chown magento2:magento2 /home/magento2/.my.cnf
chmod 600 /home/magento2/.my.cnf


PHP-FPM (Fast Process Manager) is currently the best practice approach for installing PHP. Also, if you want to use Nginx then it is basically essential as there is no equivalent of Apache’s mod_php for Nginx.

rpm -Uvh
rpm -Uvh

yum -y install php70w-fpm


We also need to make sure that a variety of PHP extensions are also installed. The following code snippet creates an array of extensions and then loops through and installs them. You need to copy and paste the whole snippet into your terminal.


for extension in ${extensions[@]}
    yum -y install php70w-${extension}

We now have PHP installed and can run the following command to confirm:

php -v

We should see something along the lines of:

PHP 7.0.10 (cli) (built: Aug 20 2016 07:47:25) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.10, Copyright (c) 1999-2016, by Zend Technologies

The important thing to note here is that we have a version of PHP 7 higher than 7.0.5


We now need to modify PHP configuration to make sure the correct settings are in place.


This needs to be set. If you are in the UK you probably want this to be set to Europe/London

echo "date.timezone = Europe/London" >> /etc/php.ini

Memory Limit

For development, compilation and other complex tasks, Magento needs a hefty memory limit. 2 GB is recommended. Obviously this means that you should be running this on a machine that has plenty of memory. If you are using Virtualbox or other virtualisation, make sure you allocate enough memory to your machine to be able to support it. We also need to get PHP configured with this memory limit.

echo "memory_limit = 2G" >> /etc/php.ini


For development, you need to get error reporting and displaying of errors set up. To do this you will need to open the file /etc/php.ini and find the line display_errors = Off and change the Off to On. There are other development related settings you might want to adjust as well.

PHP-FPM backend

We need to have PHP-FPM listening for connections. There is a default www pool however I generally prefer to create my own with just the config I need.

To create a pool, simply make a new file in /etc/php-fpm.d/ called php-fpm-backend.conf. In this file you can put your own choice of configuration options.

You need to edit this file and enter in your chosen configuration. If you are not sure how to do this, you should probably install nano and use that as a command line text editor which is the easiest one to get started with.

yum -y install nano
cd /etc/php-fpm.d/
nano php-fpm-backend.conf

Then for the file contents you can put something along the lines of:


listen = '/var/run/php-fcgi-php-fpm-backend.sock'
listen.allowed_clients =
listen.owner = nginx = nginx
listen.mode = 0660

user = magento2
group = magento2

pm = ondemand
pm.max_children = 500
pm.start_servers = 50
pm.min_spare_servers = 50
pm.max_spare_servers = 50
pm.max_requests = 500

request_terminate_timeout = 600
;request_slowlog_timeout = 1
;slowlog = /var/log/php-fpm/php-fpm-backend-slow.log

catch_workers_output = yes

php_admin_value[error_log] = /var/log/php-fpm/php-fpm-backend-error.log
php_admin_flag[log_errors] = on

Note: The user/group has been set to the magento2 user we created earlier

I’d generally rename the default www pool so that it is disabled:

cd /etc/php-fpm.d
mv www.conf www.conf.disabled

You can’t start PHP-FPM until we have installed Nginx, lets do that now.


For the web server, the thing that actually receives and serves HTTP requests, we are going to use Nginx

To get the latest version, we will need to install the official Nginx repository

yum -y install nginx-release-centos-7-0.el7.ngx.noarch.rpm

Then to install Nginx we simply

yum -y install nginx


Nginx requires the correct configuration to properly run a site and access PHP-FPM.

Nginx has a nice file include syntax which allows you to keep your configuration organised and stick to the DRY principle, especially if you are configuring more than one site.

I prefer to create a folder inside /etc/nginx/ called includes which contains config files in the formant filename.confand then any configuration for specific vhosts can be included with the syntax include includes/filename.conf;

Magento 2

Configuring Nginx can be a bit tricky if you are not used to it. Thankfully Magento have provided a pretty good baseline Nginx configuration template to use for your sites. This configuration file requires you to define a variable value and then the rest of the configuration is based upon that. You can save this file to your includes directory. Note there are things in there that you might want to adjust as you see fit, for example the memory limit, so open it and have a look.

mkdir -p /etc/nginx/includes

cd /etc/nginx/includes

wget -O magento2.conf

vim magento2.conf

PHP-FPM backend

We need to let Nginx know about our PHP-FPM service, and we can add this with an upstream block.

Edit /etc/nginx/nginx.conf and somewhere before ‘include /etc/nginx/conf.d/*.conf’ we need to add the following:

    upstream fastcgi_backend {
            server unix:/var/run/php-fcgi-php-fpm-backend.sock;

Note: the path to the socket is as you configured in your custom PHP-FPM pool above.


Finally we need to set Nginx up to actually serve a site on a particular domain name. Thanks to the fact that the majority of required config is handled by the Magento include, our Vhost configuration can be quite sparse.

The vhost configuration files live in /etc/nginx/conf.d and by conventtion, the domain name should be reflected in the filename. For our purposes lets say the domain name is www.magento2.local.

cd /etc/nginx/conf.d

cat << 'EOF' >  www.magento2.local.conf
server {
    listen 80;
    server_name www.magento2.local;
    set $MAGE_ROOT /var/www/vhosts/www.magento2.local;
    include includes/magento2.conf;
    error_log /var/log/nginx/www.magento2.local.error.log info;
    access_log /var/log/nginx/www.magento2.local.access.log main;

You can disable the default Nginx site by doing:

mv default.conf default.conf.disabled

Then you can make sure your Nginx configuration is correct by doing:

nginx -t

GOTCHA: Nginx PID file inconsistency

Unfortunatley the official Nginx repository installation has a mismatch between the /etc/nginx/nginx.conf configuration and the systemd configuration in /usr/lib/systemd/system/nginx.service

grep '' /etc/nginx/nginx.conf
# pid        /var/run/;

grep '' /usr/lib/systemd/system/nginx.service
# PIDFile=/run/

We need the path the PID file to be the same in both files otherwise it won’t work. So to do this lets edit /etc/nginx/nginx.conf, find the line pid /var/run/; and remove /var so it becomes: pid /run/;

You can do this using your choice of editor, eg nano

nano /etc/nginx/nginx.conf

Start the Nginx and PHP-FPM Services

Start Nginx

systemctl enable nginx
systemctl start nginx
systemctl status nginx

And then finally we need to start PHP-FPM

systemctl enable php-fpm
systemctl start php-fpm
systemctl status php-fpm

Create Vhost Folder and Test

We need to make sure everything so far is working, so lets just do a phpinfo file.

Lets make the document root and create an index file that calls phpinfo();:

mkdir -p /var/www/vhosts/www.magento2.local/pub
echo '<?php phpinfo();' > /var/www/vhosts/www.magento2.local/pub/index.php

Now on your local machine, you need to create a HOSTS file entry to point to this installation. That is platform dependent but on linux you might do something like:

sudo echo " www.magento2.local" >> /etc/hosts

Where is whatever IP address your CentOS machine has. To see the IP address of your CentOS machine you can run ip addr.

You should now be able to go to http://www.magento2.local/ and see the PHP info page.

back to top

Preparing to Install Magento 2

This section is all about getting ready to actually install your Magento 2 site. There are a few options for installing Magento 2 however I have taken the liberty of choosing the Integrator option using composer as that is the one that is most relevant to us.


We are now nearly ready to start installing Magento 2 itself, there is one last tool we need to install: composer

Composer has basically revolutionised PHP development, bringing us a solid and reliable dependency management system. It’s great that Magento haved decided to use it with Magento 2.

In the spirit of getting this done quickly, here are the commands to install Composer, just run them:

expectedSignature=$(wget -O - -q)
php -r "copy('', 'composer-setup.php');"
actualSignature=$(php -r "echo hash_file('SHA384', 'composer-setup.php');")
if [[ "$expectedSignature" == "$actualSignature" ]]
    php composer-setup.php
    rm composer-setup.php
    mv composer.phar /bin/composer
    composer --version
    >&2 echo 'ERROR: Invalid installer signature'
    exit 1

Marketplace Authentication

Before you can download Magento, you need to get access keys. There are full instructions here

Ultimately, you need to log in and get to this page where you will see a Public Key and a Private Key.

You have one set of keys by default. However you can generate as many as you need and I suggest you use this feature to give you a new set of keys for each project. This way, if ever a set of keys is compromised then you can simply remove the keys from your account.

For our purposes, lets hit the big orange Create a New Access Key button and for the name put - www.magento2.local.

This will then generate new keys for you. Take a note of these as we will need them later.

Note: Strongly advise you use separate access keys for each project. Why not just use the intended primary domain of the project as the key name.

Magento File Owner

So far, the guide has assumed that you are running commands as the root user of your machine. However, any Linux or Unix user will tell you that doing everything as root is definitely not a good idea.

We need to change the owner of the vhost directory.

cd /var/www/vhosts/www.magento2.local
chown -R magento2:magento2 .

And then we need to become the magento2 user:

su magento2

_Note: Read these official docs which describe how to properly lock down permissions in production_

From here on we are now running as the magento2 Linux user and can move onto installing Magento 2.

First make sure you are the correct user:


You should be your magento2 user.

Note: Remember, from here you should not be running any commands as root, you should be the magento2 user

Using Composer Create Project

Get your access keys on hand (otherwise known as username and password).

Firstly we need to clear out our pub directory and phpinfo file.

cd /var/www/vhosts/www.magento2.local
rm -rf pub

Then we are ready to use the composer create project to set up Magento 2:

composer create-project --repository-url= magento/project-community-edition .

You will be asked for a username and password.

The username is your Public Key and the password is your Private Key.

Reminder, you can get these from

Once you run the command, you will have the option to store these credentials which I’d suggest is probably a good idea.

You should then see a load of composer output along the lines of:

Installing magento/project-community-edition (2.1.1)
  - Installing magento/project-community-edition (2.1.1)
    Downloading: 100%         

Created project in .
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing magento/magento-composer-installer (0.1.11)
    Downloading: 100%         

  - Installing symfony/process (v2.8.10)
    Downloading: 100%         

  - Installing magento/framework (100.1.1)
    Downloading: 100%         

  - Installing magento/language-zh_hans_cn (100.1.0)
    Downloading: 100%         

# ...(continues for quite some time)

And once that has completed you will see lots of suggestions of other things you might want to install with Composer, eg

magento/framework suggests installing ext-imagick (Use Image Magick >=3.0.0 as an optional alternative image processing library)
magento/module-theme suggests installing magento/module-theme-sample-data (Sample Data version:100.1.*)
magento/module-catalog suggests installing magento/module-catalog-sample-data (Sample Data version:100.1.*)
# ...

You can ignore this for now

Magento 2 Database

We need to create a MySQL database for Magento2 to use. Assuming you created a .my.cnf file in the home directory of your magento2 user, you can just run the following on the terminal:

mysql -e "CREATE DATABASE magento2_database CHARACTER SET utf8 COLLATE utf8_general_ci;"

Now we need to create a user for this database, feel free to set usernames and passwords as you see fit, and make sure you take note as you will need them later.

First set some variable values:


And then use them to create the user

 mysql -e "CREATE USER '$dbUser'@'localhost' IDENTIFIED BY '$dbPass' "
 mysql -e "
     ON magento2_database.* 
     TO '$dbUser'@'localhost' IDENTIFIED BY '$dbPass';
     flush privileges;

And then double check its worked

 mysql -e "SHOW GRANTS FOR '$dbUser'@'localhost'"

If you want to change the database name to something more meaningful then of course you are free to replace magento2_database with whatever you would like, same goes for the user magento2_dbuser.


Magento 2 developer documentation goes into a nice clear level of detail about how you might want ot set up permissions. You can read the relevant section here.

We’ve simplified our permissions by configuring PHP-FPM to run this pool as our magento2 user so the instructions aren’t completely relevant to our configuration, but are worth being aware of.

One command we do need to run though is this:

chmod 700 bin/magento

Which makes the CLI tool executable.

You are now ready to actually install Magento2

back to top

Installing and Configuring Magento 2

This section takes us through the installation process and basic post install configuration

Command Line Install

We are going to use the command line installer which is nicely documented on the official documentation.

The command line tool in Magento is likely to be something we use a lot so lets add it to our PATH.

Then update your ~/.bashrc file to extend your PATH:

echo "PATH=$PATH:/var/www/vhosts/www.magento2.local/bin" >> ~/.bashrc
source ~/.bashrc

Now you need to move into the project root directory

cd /var/www/vhosts/www.magento2.local

We are going to prepare an installation script and then run it, so run the following command to create the script

cat << 'EOF' > bin/installScript.bash
#!/usr/bin/env bash
magento setup:install \
    --admin-firstname "ADMIN_FIRSTNAME_HERE" \
    --admin-lastname "ADMIN_LASTNAME_HERE" \
    --admin-email "ADMIN_EMAIL_HERE" \
    --admin-user "ADMIN_USERNAME_HERE" \
    --admin-password "ADMIN_PASSWORD_HERE" \
    --db-host "localhost" \
    --db-name "magento2_database" \
    --db-user "magento2_dbuser" \
    --db-password "DB_PASSWORD_HERE" \
    --db-prefix "" \
    --base-url "http://www.magento2.local/" \
    --use-secure "0" \
    --language "en_GB" \
    --currency "GBP" \
    --timezone "Europe/London" \
    --use-rewrites 1 \
    --backend-frontname "admin";

Then edit your script and replace the UPPER_CASE variables. If you previously installed nano then you can use that.

Note: Your password must be at least 7 characters and your password must include both numeric and alphabetic characters.

nano bin/installScript.bash

Once you are done, you can make it executable

chmod 700 bin/installScript.bash

Finally, you are ready to run the install


Once that has completed you should be able to see the front end on


and the admin on


Reinstallation of Magento 2

Should there be any problems and you want to reinstall, you’ve now created a nice easy to use script to repeat the process without having to remember lots of parameters.

To reinstall, simply:

mysql -e "DROP DATABASE IF EXISTS magento2_database;"
mysql -e "CREATE DATABASE magento2_database CHARACTER SET utf8 COLLATE utf8_general_ci;"
chmod 700 bin/magento

Note: This will totally wipe out the database (warning, that’s destructive). You might want to backup the database first just in case.

Post Install Tasks

There are some other tasks you probably want to do once you have the installation working:

Setup Cron Jobs

Cron jobs run on a schedule in the background and handle things like updating indexes and other background tasks. You can read more about the cron tasks on the official docs.

We need to set up a crontab for our magento2 user with the correct entries.

My preferred way to do this is to have a a _crontab_temp file which is tracked in the project and can then be used to easily track and possibly revert any changes to cron configuration.

cd /var/www/vhosts/www.magento2.local
cat << 'EOF' > _crontab_temp
* * * * * /usr/bin/php /var/www/vhosts/www.magento2.local/bin/magento cron:run | grep -v "Ran jobs by schedule" >> /var/www/magento2/var/log/magento.cron.log
* * * * * /usr/bin/php /var/www/vhosts/www.magento2.local/update/cron.php >> /var/www/magento2/var/log/update.cron.log
* * * * * /usr/bin/php /var/www/vhosts/www.magento2.local/bin/magento setup:cron:run >> /var/www/magento2/var/log/setup.cron.log

Then to actually add this to the crontab, simply

crontab _crontab_temp

crontab -l


As described in the official docs, you can reindex on the command line easily using the magento command.

Assuming you have already added the bin directory to your PATH, you can just run

magento indexer:reindex

And you should see output along the lines of :

Design Config Grid index has been rebuilt successfully in 00:00:00
Customer Grid index has been rebuilt successfully in 00:00:00
Category Products index has been rebuilt successfully in 00:00:00
Product Categories index has been rebuilt successfully in 00:00:00
Product Price index has been rebuilt successfully in 00:00:00
Product EAV index has been rebuilt successfully in 00:00:00
Stock index has been rebuilt successfully in 00:00:00
Catalog Rule Product index has been rebuilt successfully in 00:00:00
Catalog Product Rule index has been rebuilt successfully in 00:00:00
Catalog Search index has been rebuilt successfully in 00:00:00

Change Modes

Magento2 can run in one of three modes, production, default and developer. You want to run in production for live sites. For development locally, you probably want to be in developer mode.

You can see your current mode by running

magento deploy:mode:show

By default, Magento 2 is in the aptly named mode “default”. This is a compromise and should not be used, you really want to be in either production or developer modes.

You can change to developer mode by running these commands:

cd /var/www/vhosts/www.magento2.local
rm -rf /var/di/*
rm -rf /var/generation/* 
magento deploy:mode:set developer

Read more about modes here and also here


Magento2 makes heavy use of compiled code PHP code. This takes your source PHP and creates “compiled” PHP code which is actually used in production.

You can read about the compilation process on the official docs

In a nutshell though, you simply need to run this command:

magento setup:di:compile

Once this has completed you should see output along the lines of:

Compilation was started.
%message% 0/7 [>---------------------------]   0% 1 sec 40.0 MiB%message% 0/7 [>---------------------------]   0% 1 sec 40.0 MiBProxies code generation... 0/7 [>---------------------------]   0% 1 sec 40.0 MiB
Proxies code generation... 1/7 [====>-----------------------]  14% 1 sec 42.0 MiB
Repositories code generation... 1/7 [====>-----------------------]  14% 1 sec 42.0 MiB
Repositories code generation... 2/7 [========>-------------------]  28% 13 secs 132.0 MiB
Service data attributes generation... 2/7 [========>-------------------]  28% 13 secs 132.0 MiB
Service data attributes generation... 3/7 [============>---------------]  42% 13 secs 134.0 MiB
Application code generator... 3/7 [============>---------------]  42% 13 secs 134.0 MiB
Application code generator... 4/7 [================>-----------]  57% 29 secs 150.0 MiB
Interceptors generation... 4/7 [================>-----------]  57% 29 secs 150.0 MiB
Interceptors generation... 5/7 [====================>-------]  71% 45 secs 168.0 MiB
Area configuration aggregation... 5/7 [====================>-------]  71% 45 secs 168.0 MiB
Area configuration aggregation... 6/7 [========================>---]  85% 2 mins 238.0 MiB
Interception cache generation... 6/7 [========================>---]  85% 2 mins 238.0 MiB
Interception cache generation... 7/7 [============================] 100% 2 mins 238.0 MiB
Generated code and dependency injection configuration successfully.

back to top

Further Notes and Tips

Documentation Versions

If you search Google, you will probably find the docs for version 2.0 in the results. You can see this in the URL

Actually, you need to be looking at the documentation for the version you are working with, currently 2.1. If you do find a page in the results, you can generally just change the version number in the URL to make sure you are looking at the right version, eg

Often, there will be no difference, but occasionally there are signficant differences and you can end up going down the rabbit hole if you are reading the wrong docs.

On the flip side, you might find that the documentation for your version is incomplete and so you need to use the previous documentation. That’s fine, but I’d strongly suggest you check for up to date docs first and then use legacy docs as required.

Installing the Sample Data

Magento 1 had an option to install a set of sample data which was really handy. It gave you a nice representation of the different kinds of products, categories and configurations you might expect to see on a real store. The other advantage was that everyone could base their customisations on the default theme with this sample data and if it worked with this then there was a good chance it would work in general.

That concept has been carried over into Magento 2 and so, depending on the type of project you are working on, you might want to install the sample data.

You can read the official docs (incomplete at the time of writing). We will be using the composer method for which there is a magento CLI tool command.

To fully install the sample data, run the following commands

magento sampledata:deploy
magento setup:upgrade
magento setup:di:compile

Note: You must be in developer mode to install the sample data

As the docs say though, you should not build a production site from a database that has had the sample data. Your main use case for using the sample data is for generic theme/module development that you expect to be used on multiple client sites.

Flushing Caches and Indexes

When developing, it’s likely that you will want to flush caches and reindex on a fairly regular basis. Thankfully the new CLI tool makes this simple

magento cache:clean
magento indexer:reindex


As Magento 2 is using composer, you can update all of the library and framework code using the standard composer syntax, simply:

cd /var/www/vhosts/www.magento2.local
composer update

This will check all of the packages in the project for updated versions and will then update them. Finally it will update the composer.lock file with these updated versions.

Removing index.php From Front End URls

We don’t want index.php in our front end URLs and as we are using Nginx there is no need to.

To remove them we need to log into the Magento admin and then go to

STORES -> configuration -> GENERAL -> Web -> Search Engine Optimisation

In here there is a drop down option for Use Web Server Rewrites. Set this to Yes, then flush all caches and the index.php should be gone from URLs.

Varnish Cache

Varnish is a full page caching system that sits in front of your normal web server as a reverse proxy. This is something that you can do with Nginx on it’s own. What Varnish does which is also allows elements of the page to still be dynamic, pulling in just those elements using a technique called Edge Side Includes or ESI.

Magento 1 does not officially support Varnish but most production sites these days will be using it thanks to third party extentions that provide Varnish support.

For Magento 2, Varnish support has been baked in and is something that you almost certainly want to enable to get the best performance.

You can read the offical documentation about Varnish to understand more about it.

The following commands should be run as the root user

For us to install Varnish, we firstly need to make sure that we are going to get a compatible version.

Note: for Magento 2, you really want to be running Varnish 4

To find out exactly what version you would install you can run this:

yum info varnish

Which should give us something along the lines of:

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base:
 * epel:
 * extras:
 * updates:
 * webtatic:
Available Packages
Name        : varnish
Arch        : x86_64
Version     : 4.0.3
Release     : 3.el7
Size        : 421 k
Repo        : epel/x86_64
Summary     : High-performance HTTP accelerator
URL         :
Licence     : BSD
Description : This is Varnish Cache, a high-performance HTTP accelerator.
            : Documentation wiki and additional information about Varnish is
            : available on the following web site:

Note the bit we care about - Version : 4.0.3

Install Varnish

After we have confirmed that we will definitely get Varnish 4 from yum, we can do the install

yum -y install varnish
varnishd -V
systemctl enable varnish
systemctl start varnish

Configure Varnish and Nginx

One thing that needs to be understood is that Varnish is a web server and listens to HTTP connections in exactly the same was as Nginx. We need to decide which of the two services is going to be the one that external browsers are actually hitting.

Another factor in here is that Varnish does not support SSL, so if you are planning to use HTTPS (and you really should) then you will need Nginx to be the server that clients connect to on port 80 (for redirecting to SSL) and port 443 (for the actual SSL web traffic).

Here is how we are going to lay this out:

Port Public Server Connects To
80 (http) yes Nginx Varnish (6081)
443 (https) yes Nginx Varnish (6081)
6081 no Varnish Nginx (8080)
8080 no Nginx PHP-FPM (socket)

As this article has more of a development focus, we will not worry about the https 443 for now.

Note: this differs from the official documentation which recommends that you have Varnish listening on port 80.

The first thing we need to do is get our main Magento server listening on port 8080. To do this we need to edit the file /etc/nginx/conf.d/www.magneto2.local.conf and change listen 80; to listen;

nano /etc/nginx/conf.d/www.magento2.local.conf

We also need to add a new server block in this file which will actually listen on port 80 (and optionally also 443) and will then pass the request to Varnish.

Run the following command to add a new server block which is listening on port 80 and 443 and proxy passing to Varnish on 6081

cat << 'EOF' >> /etc/nginx/conf.d/www.magento2.local.conf
    listen 80;
    #uncomment the below 4 lines and update the paths to your SSL keys to enable SSL
    #listen 443 ssl http2;
    #ssl_certificate      /etc/nginx/ssl/;
    #ssl_certificate_key  /etc/nginx/ssl/;
    #ssl_trusted_certificate /etc/nginx/ssl/;
    server_name www.magento2.local;
    location / {
        proxy_pass  ;
        proxy_read_timeout    90;
        proxy_connect_timeout 90;
        proxy_redirect        off;
        proxy_max_temp_file_size 0;
        proxy_buffering off;
        proxy_request_buffering off;
        #Enable Keepalives
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto http;
        proxy_set_header      X-Forwarded-Port 80;
        proxy_set_header      Host $host;
    error_log /var/log/nginx/public.www.magento2.local.error.log info;
    access_log /var/log/nginx/public.www.magento2.local.access.log main;

Once this is done we need to test and then reload nginx config

nginx -t

systemctl reload nginx

And after this, you should be able to access the site in your browser. You might notice it is a lot faster.

Configure Magento to Use Varnish

You can read the official documentation which covers what needs to be done.

Some of the config might not be obvious though, here is what I would suggest for starters:

Option Value
Caching Application Varnish
TTL for public content Use system value
Access list localhost
Backend host localhost
Backend port 8080

Once you have filled this out, you will need to hit the orange Save Config button in the top right.

Once the config is saved, you can export the VCL file. You need to hit the button Export VCL for Varnish 4. This will download a file to your local machine which you should open in a text editor.

We need to take the contents of this file and get them onto a file on your server. For now lets just copy and paste the contents.

Local Machine: open the downloaded vcl file, select all and copy the contents

Server: run the following commands and then paste the contents, save and close

cd /etc/varnish
mv default.vcl default.vcl.backup
nano default.vcl

Paste in the contents and save the file, then we need to restart Varnish

systemctl restart varnish

For some reason I found that Varnish cache was not clearing unless I also ran the following:

Run the following as the magento2 user:

magento setup:config:set --http-cache-hosts=

This was mentioned on this page of the official docs

After running this command, doing magento cache:clean will flush the Varnish cache

Tags: Magento2 Magento Linux PHP E-Commerce