Skip to content

Instantly share code, notes, and snippets.

@andy-igoo
Created April 30, 2018 09:16
Show Gist options
  • Save andy-igoo/68818d1b1b1560b661be1e473a2aa2f7 to your computer and use it in GitHub Desktop.
Save andy-igoo/68818d1b1b1560b661be1e473a2aa2f7 to your computer and use it in GitHub Desktop.
Magento 2 Vagrant Setup

Magento 2 Example Dev Environment

Creating a Vagrant Box

Firstly, create a folder for your Magento 2 project and navigate to it. E.g. mkdir ~/Projects/magento2.lan

Requirements

Make sure you have Virtual Box installed (check which version is compatible here) and Vagrant.

Virtual Box: Download here

Vagrant: Download here

You will also need NFS on your system. Please enable or install this feature if it's not available. Many OS have NFS ready to go out of the box.

Init box and download

You will need to select a box to begin with. Here we are going to use a popular Ubuntu distribution from the Ubuntu collection of boxes as many people are familiar with it; it tends to be (along with Mint) the first one people play with. You can search for different boxes here at https://app.vagrantup.com/boxes/search where you may like to use something else.

In your terminal ...

  • vagrant init ubuntu/xenial64 Or your favourite one. This one is a popular Ubuntu box.
  • vagrant up

Note: If you're after a RHEL flavoured box then you are going to have to transpose the package install commands to reflect these Debian style apt installs.

If you get a recurring message saying default: Warning: Authentication failure. Retrying... then see this blog post.

When downloaded and running, log in to your box, set your local and update.

Use your own locale for the locale-gen command.

  • vagrant ssh
  • sudo apt-get install language-pack-en

Use less /var/lib/locales/supported.d/en to find your locale if you don't know.`

  • sudo locale-gen en_GB.UTF-8
  • sudo apt update && sudo apt upgrade

If it asks you continue without install grub say yes.

Set up service inside the VM

Install php

sudo apt install -y php7.0 php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-mcrypt php7.0-curl php7.0-intl php7.0-xsl php7.0-mbstring php7.0-zip php7.0-bcmath php7.0-iconv php7.0-soap php-fpm

Test PHP

php -v

Install Nginx

sudo apt install nginx Make sure Apache isn't running first

Test Nginx

curl -I 127.0.0.1

Install MySQL

sudo apt-get install mysql-server sudo mysql_secure_installation

Answer the questions the script will ask you

VALID PASSWORD? (n)

Change the password (up to you)

Remove anon users? (y)

Disallow remote login (up to you, say no if not sure.)

Remove test database (y)

Reload privilege tables (y)

Test MySql

mysql -p -u root -e"SHOW DATABASES"

You should see something like

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

(Yay!)

Remove the default web server pages

sudo rm -rf /var/www/html/*

Create a PHP info page

sudo nano /var/www/html/index.php

([ctrl x] and y to save in nano.)

Or use your favorite text editor! Just remember you need root privileges to make the file.

Add this code to the file for testing later

<?php
    phpinfo();
?>

Make an index.html file as well with a simple hello message

curl http://localhost/ (will give you the contents of index.html)

Create a mount point for our Magento 2 project

sudo mkdir /webroot

sudo chown vagrant /webroot/

Exit out of box

exit

vagrant halt

Set up the Vagrantfile

Remove replace the contents of the Vagrantfile file with the following

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

# Options
VM_CPUS         = 2
VM_MEMORY       = 1024
VM_NAME         = "igoo-example_php7"
VM_HOSTNAME     = "igoo-example-php7.igoo-example.co.uk"
VM_IPADDR       = "10.20.48.10"

VM_BOX          = "ubuntu/xenial64" # Change this to what you used. Use 'vagrant box list' to see.
# VM_BOX_JSON     = "http://example.com/vagrant/igoo-example.env.php7.json" # This is for publishing on a private server

VM_WEB_ROOT     = "/webroot"
VM_NFS_VERSION  = "3,nolock"
# VM_NFS_VERSION  = "4,nolock" # Version 4 is more secure than the other but there is no real speed difference.


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.host_name = VM_HOSTNAME
  config.vm.network "private_network", ip: VM_IPADDR,  auto_config: true
  config.vm.network "forwarded_port", guest: 80, host: 8080, auto_correct: true
  config.vm.boot_timeout = 300

  # Un-comment these for provision scripts. See Vagrant docs for more
  # config.vm.provision :shell, path: "vagrant/install.sh", run: "once"
  # config.vm.provision :shell, path: "vagrant/reload.sh", run: "always"

  # Customize provider
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--ostype", "Ubuntu_64"] # Assuming it's a 64 bit Ubuntu
    vb.customize ["modifyvm", :id, "--memory", VM_MEMORY]
    vb.customize ["modifyvm", :id, "--cpus", VM_CPUS]
    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
    vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
    vb.name = VM_NAME
  end

  config.vm.box = VM_BOX
  # config.vm.box_url = VM_BOX_JSON
  config.ssh.forward_agent = true
  # config.vm.box_check_update = false # For when there's no network, prevents a hang.

  # Not for Windows machines. See https://github.com/winnfsd/vagrant-winnfsd for an alternative.
  config.vm.synced_folder "./", VM_WEB_ROOT, :nfs => { :mount_options => ["dmode=777", "fmode=666"] }, nfs_version: VM_NFS_VERSION, nfs_udp: false, :linux__nfs_options => ['rw','no_subtree_check','all_squash','async'], :bsd__nfs_options => ['rw','no_subtree_check','all_squash','async']
  config.vm.synced_folder "./var", VM_WEB_ROOT + "/var", create: true, :mount_options => ["dmode=777", "fmode=666"]

  #
end

Back to your terminal ...

  • vagrant up
  • vagrant ssh
  • ls /webroot Should see your project root here and a var folder

PHP and Nginx setup

You should now be able to visit http://10.20.48.10/ and see your test page but http://10.20.48.10/index.php you will notice doesn't work yet; the php file just downloads.

Update the nginx default config file

sudo nano /etc/nginx/sites-enabled/default Or your favorite text editor

Modify the following parts to this ..

	# .. stuff .. #
        
        # Add index.php to the list if you are using PHP
        index index.php index.html index.htm index.nginx-debian.html;

	# .. more suff.. #

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php7.0-cgi alone:
        #       fastcgi_pass 127.0.0.1:9000;
        #       # With php7.0-fpm:
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

	# .. stuff at the end.. #

Test it

sudo nginx -t

If okay restart nginx

sudo service nginx restart

Reload http://10.20.48.10/ and observe php.ini location (Loaded Configuration File section)

sudo nano /etc/php/7.0/fpm/php.ini

Change the following (for M2 setup later)

max_execution_time = 60

sudo service php7.0-fpm restart

MySql setup

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Add or change these values

query_cache_type = 1
query_cache_size = 32M
query_cache_limit=2M

Some final changes to Nginx

sudo nano /etc/nginx/nginx.conf

# Make the user vagrant here
user vagrant

worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        multi_accept on;
        use epoll;
}

SSL Setup

Here we will us the snakeoil certificates. Your browser will give you a red warning but either add an exception or click the continue link in the advanced section.

sudo nano /etc/nginx/sites-enabled/default

Uncomment the following:

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

and

include snippets/snakeoil.conf;

If you don't have snake oil certificates already generate them with:

  • sudo apt install ssl-cert
  • sudo make-ssl-cert generate-default-snakeoil
  • sudo ls -l /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/private/ssl-cert-snakeoil.key
  • sudo usermod --append --groups ssl-cert vagrant

Change PHP-FPM user

sudo nano /etc/php/7.0/fpm/pool.d/www.conf

user = vagrant 
group = vagrant

	...

listen.owner = vagrant 
listen.group = vagrant

sudo service nginx restart

sudo service php7.0-fpm restart

Install composer globally

Go to a directory you don't care about such as cd ~

  • wget https://getcomposer.org/composer.phar
  • sudo chmod +x composer.phar
  • sudo mv composer.phar /usr/bin/composer

Try it!

composer

Tada!

Installing Magento 2 to test

Create a database for it

mysql -p -u root -e"CREATE DATABASE magento2"

If you haven't already, go to Magento Marketplace, log in or sign up and generate keys by going to "My Profile" and clicking "Access keys". The public key is the username and the private key is the password.

  • cd /webroot
  • composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition

This will install into a folder named project-community-edition which you can move the contents up a level later on. But for now we will just work with that. If we try to install into just the webroot folder, it will throw and error due to the folder not being empty. Yes it is annoying.

Make a new file in your project root called magento2.conf and paste in the following configuration. When doing your own setup after this test remember to edit set $MAGE_ROOT /webroot/project-community-edition to reflect your preferred structure.

server {
   listen 80;
   listen 443 ssl;
   server_name magento2.lan;
   set $MAGE_ROOT /webroot/project-community-edition; # MAKE SURE THIS IS CHANGED FOR YOUR SITUATION IN THE FUTURE

## Optional override of deployment mode. We recommend you use the
## command 'bin/magento deploy:mode:set' to switch modes instead.
##
## set $MAGE_MODE developer; # or production or developer
##
## If you set MAGE_MODE in server config, you must pass the variable into the
## PHP entry point blocks, which are indicated below. You can pass
## it in using:
##
## fastcgi_param  MAGE_MODE $MAGE_MODE;
##
## In production mode, you should uncomment the 'expires' directive in the /static/ location block

    root $MAGE_ROOT/pub;

    index index.php;
    autoindex off;
    charset UTF-8;
    error_page 404 403 = /errors/404.php;
    #add_header "X-UA-Compatible" "IE=Edge";

    # PHP entry point for setup application
    location ~* ^/setup($|/) {
        root $MAGE_ROOT;
        location ~ ^/setup/index.php {
            # Removed as it causes a blank screen sometimes.
            # fastcgi_split_path_info ^(.+?\.php)(/.*)$;

            fastcgi_pass   unix:/run/php/php7.0-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        location ~ ^/setup/(?!pub/). {
            deny all;
        }

        location ~ ^/setup/pub/ {
            add_header X-Frame-Options "SAMEORIGIN";
        }
    }

    # PHP entry point for update application
    location ~* ^/update($|/) {
        root $MAGE_ROOT;

        location ~ ^/update/index.php {
            fastcgi_split_path_info ^(/update/index.php)(/.+)$;
            fastcgi_pass   unix:/run/php/php7.0-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO        $fastcgi_path_info;
            include        fastcgi_params;
        }

        # Deny everything but index.php
        location ~ ^/update/(?!pub/). {
            deny all;
        }

        location ~ ^/update/pub/ {
            add_header X-Frame-Options "SAMEORIGIN";
        }
    }

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

    location /pub/ {
        location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) {
            deny all;
        }
        alias $MAGE_ROOT/pub/;
        add_header X-Frame-Options "SAMEORIGIN";
    }

    location /static/ {
        # Uncomment the following line in production mode
        # expires max;

        # Remove signature of the static files that is used to overcome the browser cache
        location ~ ^/static/version {
            rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
        }

        location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
            add_header Cache-Control "public";
            add_header X-Frame-Options "SAMEORIGIN";
            expires +1y;

            if (!-f $request_filename) {
                rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
            }
        }
        location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
            add_header Cache-Control "no-store";
            add_header X-Frame-Options "SAMEORIGIN";
            expires    off;

            if (!-f $request_filename) {
               rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
            }
        }
        if (!-f $request_filename) {
            rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
        add_header X-Frame-Options "SAMEORIGIN";
    }

    location /media/ {
        try_files $uri $uri/ /get.php?$args;

        location ~ ^/media/theme_customization/.*\.xml {
            deny all;
        }

        location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
            add_header Cache-Control "public";
            add_header X-Frame-Options "SAMEORIGIN";
            expires +1y;
            try_files $uri $uri/ /get.php?$args;
        }
        location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
            add_header Cache-Control "no-store";
            add_header X-Frame-Options "SAMEORIGIN";
            expires    off;
            try_files $uri $uri/ /get.php?$args;
        }
        add_header X-Frame-Options "SAMEORIGIN";
    }

    location /media/customer/ {
        deny all;
    }

    location /media/downloadable/ {
        deny all;
    }

    location /media/import/ {
        deny all;
    }

    # PHP entry point for main application
    location ~ (index|get|static|report|404|503)\.php$ {
        try_files $uri =404;
        fastcgi_pass   unix:/run/php/php7.0-fpm.sock;
        fastcgi_buffers 1024 4k;

        fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
        fastcgi_param  PHP_VALUE "memory_limit=768M \n max_execution_time=600";
        fastcgi_read_timeout 600s;
        fastcgi_connect_timeout 600s;

        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    gzip on;
    gzip_disable "msie6";

    gzip_comp_level 6;
    gzip_min_length 1100;
    gzip_buffers 16 8k;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        text/js
        text/xml
        text/javascript
        application/javascript
        application/x-javascript
        application/json
        application/xml
        application/xml+rss
        image/svg+xml;
    gzip_vary on;

    # Banned locations (only reached if the earlier PHP entry point regexes don't match)
    location ~* (\.php$|\.htaccess$|\.git) {
        deny all;
    }
}

Copy to the nginx folder on the VM and test

  • sudo cp magento2.conf /etc/nginx/sites-enabled/
  • sudo nginx -t
  • sudo service nginx restart As long as there are no errors

Exit the box and change the Vagrant file for the new web root

exit

On the host machine

vagrant halt

Get magento2.lan to resolve to the right ip

For windows use https://archive.codeplex.com/?p=hostsfileeditor

For Mac and Linux edit the /etc/hosts as root

10.20.48.10 magento2.lan

Start the box and get to the Magento install screen

You should be able to now see Magento 2's setup page.

Remember your sql details and that we created a database called magento2.

Put Redis on it!

Setup Redis here: https://redis.io/topics/quickstart Enable it in Magento 2 (use the correct magento version): http://devdocs.magento.com/guides/v2.2/config-guide/redis/redis-pg-cache.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment