11

We would like to create multiple websites in Magento 2. There is an article about this topic in the Official Magento 2 Documentation, but the way they describe is not suitable for our case.

They are suggesting to use sub-domains in order to determine different websites, such as

  • website1.magento-site.com
  • website2.magento-site.com

We would like to use sub-folders instead of sub-domains. To give an example,

  • magento-site.com/website1
  • magento-site.com/website2

How can we overcome this issue on Nginx web server?

My Configuration

I am using Ubuntu 16.04. I have installed Nginx, and have not changed any Nginx core configuration. I have created a file magento-site.com.conf inside /etc/nginx/sites-enabled/magento-site.com.conf.

/etc/nginx/sites-enabled/magento-site.com.conf

server {
    listen 8080;
    server_name magento-site.com;

    set $MAGE_RUN_CODE website1;
    set $MAGE_ROOT /var/www/magento-site.com;
    include /var/www/magento-site.com/nginx.conf;
}

EDIT 1: (2017-10-23)

I have multiple stores for each website.

Bunyamin Inan
  • 2,502
  • 4
  • 20
  • 34

4 Answers4

15

I have tried numerous ways to achieve this task. I would like to thank @matias-hidalgo for his contributions, although I did not understand his answer at first read :).

Here is the scenario. We have two different websites, and each website has two different store views as follows:

Website 1

  • Website 1 (E-commerce)
  • Website 1 (Venda Assistida)

Website 2

  • Website 2 (E-commerce)
  • Website 2 (Venda Assistida)

In my solution, we are going to change some configuration in Magento Admin. Then we are going to create some sub-folders, and finally we are going to modify nginx.conf.

First of all, we need to make some configuration change in the Magento Admin. Go to Stores -> Configuration -> General -> Web. We need to change Base URLs for each store view.

For Default Config

Please provide the following configuration for default config. enter image description here

For Website 1 (E-commerce) and Website 1 (Venda Assistida)

Please provide the following configuration for all Website 1 store views. enter image description here

For Website 2 (E-commerce) and Website 2 (Venda Assistida)

Please provide the following configuration for all Website 2 store views. enter image description here

Secondly, we need to create website1 and website2 folders in the /pub directory. In the final, you should have the following folders:

  • MAGENTO_ROOT/pub/website1
  • MAGENTO_ROOT/pub/website2

Copy the pub/index.php file into these directories. Then we will make some changes in MAGENTO_ROOT/pub/website1/index.php and MAGENTO_ROOT/pub/website2/index.php.

Content of MAGENTO_ROOT/pub/website1/index.php

I have only changed 3 lines:

1st Line: require __DIR__ . '/../../app/bootstrap.php';

2nd Line: $params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = 'website1';

3rd Line: $params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';

<?php
/**
 * Public alias for the application entry point
 *
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\Filesystem\DirectoryList;

try {
    require __DIR__ . '/../../app/bootstrap.php';
} catch (\Exception $e) {
    echo <<<HTML
<div style="font:12px/1.35em arial, helvetica, sans-serif;">
    <div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;">
        <h3 style="margin:0;font-size:1.7em;font-weight:normal;text-transform:none;text-align:left;color:#2f2f2f;">
        Autoload error</h3>
    </div>
    <p>{$e->getMessage()}</p>
</div>
HTML;
    exit(1);
}

$params = $_SERVER;
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = 'website1';
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';
$params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = [
    DirectoryList::PUB => [DirectoryList::URL_PATH => ''],
    DirectoryList::MEDIA => [DirectoryList::URL_PATH => 'media'],
    DirectoryList::STATIC_VIEW => [DirectoryList::URL_PATH => 'static'],
    DirectoryList::UPLOAD => [DirectoryList::URL_PATH => 'media/upload'],
];

$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication(\Magento\Framework\App\Http::class);
$bootstrap->run($app);

For the final touch, we need to modify nginx.conf in your MAGENTO_ROOT directory. Please put the following configuration into your nginx.conf.

location /website1 {
    root /website1;
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /website1/index.php last;
        break;
    }
}

location /website2 {
    root /website2;
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /website2/index.php last;
        break;
    }
}

After all this configurations and modifications, you will be able to use websites as sub-folders. I hope it helps.

Bunyamin Inan
  • 2,502
  • 4
  • 20
  • 34
5

What about a pure nginx solution with this double map ?

First, for the web site (thanks @MagenX)

map $request_uri $MAGE_RUN_CODE {
    default website1;
    ~^/website1/.*  website1;
    ~^/website2/.*  website2;
}

A second for the new request uri

map $request_uri $REQUEST_URI {
    default  $request_uri;
    "~*^/(website[0-9])(?<p>.*)" $p;
}

And finally, dont forget to set the new computed REQUEST_URI

location ~ \.php$ {
(...)
   include fastcgi_params;
   fastcgi_param MAGE_RUN_CODE $MAGE_RUN_CODE;
   fastcgi_param REQUEST_URI $REQUEST_URI;
(...)
}
Petit_Nuage
  • 66
  • 1
  • 2
4

By Nginx configuration you can use this example configuration:

server {
    listen 80;
    ## SSL directives might go here
    server_name local.magento2.com;
    root /PATH/TO/YOUR/MAGENTO/pub;

    location / {
        index index.html index.php; ## Allow a static html file to be shown first
        try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler
        expires 30d; ## Assume all files are cachable
    }

    location /your/subfolder {
        root /your/subfolder;
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /your/subfolder/index.php last;
            break;
        }
        #limit_conn iplimit 50;
    }

    location @handler { ## Magento uses a common front handler
        rewrite / /index.php;
    }

    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 ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
        rewrite ^(.*.php)/ $1 last;
    }

    location ~ .php$ { ## Execute PHP scripts
        if (!-e $request_filename) {
            rewrite / /index.php last;
        }
        expires        off;
        #fastcgi_pass   unix:/run/php/php5.6-fpm.sock;
        fastcgi_pass   unix:/run/php/php7.0-fpm.sock;
        fastcgi_read_timeout 10m;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        #fastcgi_param  MAGE_RUN_CODE $mage_run_code;
        #fastcgi_param  MAGE_RUN_TYPE store;
        #fastcgi_param  MAGE_MODE developer; # default or production or developer
        include        /etc/nginx/fastcgi_params;
    }
}

and use this index.php as an example:

/PATH/TO/YOUR/MAGENTO/pub/your/subfolder/index.php
<?php
use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\Filesystem\DirectoryList;
try {
    require __DIR__ . '/../../../app/bootstrap.php';
} catch (\Exception $e) {
    echo <<<HTML
<div style="font:12px/1.35em arial, helvetica, sans-serif;">
    <div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;">
        <h3 style="margin:0;font-size:1.7em;font-weight:normal;text-transform:none;text-align:left;color:#2f2f2f;">
        Autoload error</h3>
    </div>
    <p>{$e->getMessage()}</p>
</div>
HTML;
    exit(1);
}

$params = $_SERVER;
$params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = [
    DirectoryList::PUB => [DirectoryList::URL_PATH => ''],
    DirectoryList::MEDIA => [DirectoryList::URL_PATH => 'media'],
    DirectoryList::STATIC_VIEW => [DirectoryList::URL_PATH => 'static'],
    DirectoryList::UPLOAD => [DirectoryList::URL_PATH => 'media/upload'],
];
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = 'website_code';
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
$app = $bootstrap->createApplication('Magento\Framework\App\Http');
$bootstrap->run($app);

In order to clarify:

In my vhost nginx configuration you will find this:

    location /your/subfolder {
        root /your/subfolder;
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /your/subfolder/index.php last;
            break;
        }
        #limit_conn iplimit 50;
    }

where the first "/your/subfolder" can be changed for whatever you want as website url. ex www.mywebsite.com/stack/magento -> /stack/magento

Then in order to define the website code which will be loaded into this url you have to create the index.php writing the website code here:

$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = 'website_code';

I hope this now is clear enough, I've to spend time in a project to get this done so I know it works and it's closer as how we used to do it on M1.

Matias Hidalgo
  • 453
  • 3
  • 10
  • I don't understand how this will solve my problem. I specifically asked how to use multiple website. Are you suggesting that this code can be also used for websites? – Bunyamin Inan Oct 20 '17 at 11:43
  • You said "We would like to use sub-folders instead of sub-domains." I'll update my answer now clarifying where each Subfolder config is – Matias Hidalgo Oct 20 '17 at 11:58
  • Yes, I said that. I also said that I would like to use multiple websites with sub-folders. I just don't understand what is store-code doing there? – Bunyamin Inan Oct 20 '17 at 12:01
  • That was just a suggestion, if your store codes are good enough you don't need to deal with nginx configuration... have a look now to my explanation – Matias Hidalgo Oct 20 '17 at 12:08
  • So you are saying that if my store code and website code match, this will work. I also have multiple stores for each website. – Bunyamin Inan Oct 23 '17 at 12:21
  • Sorry for confuse you, ignore the first suggestion, I'll remove it from my answer, with the nginx + index.php solution you can manage to have customized subfolder name for each store or website. Nice to hear it was helpful for you. – Matias Hidalgo Oct 24 '17 at 05:02
  • When i point the domain then what code i need to add instead of "location /your/subfolder " .conf file ? because after point the domain this sub directory not available in url. – Dhaval Vaghela Sep 19 '19 at 12:05
1

in your domain.conf in "etc/nginx" you need to create a map.

for example:

map $http_host$uri $MAGE_RUN_CODE { 
   ~*^(www\.)?magento-site\.com/website1/.*  website1;
   ~*^(www\.)?magento-site\.com/website2/.*  website2;
}

or

map $request_uri $MAGE_RUN_CODE {
    default default;
    ~^/website1/.*  website1;
    ~^/website2/.*  website2;
}
MagenX
  • 3,820
  • 1
  • 16
  • 30