How to set up a Magento Multistore using multiple domains

in Magento Tags: DNSMagentoNginx

Many merchants use a single Magento installation for multiple shops or different domains.
This way you can address customers from different countries by serving a storefront using their native language and currency settings, or start a secondary website with another layout selling the same or different products.

This all can be done using stores, storefronts and websites.

Storefronts, Websites, Store views

Storefronts, websites and store views are used to serve different content depending on the domain name or subdirectory the visitor is requesting.
For example you can create different language sites using subdirectories and create a /de/ endpoint for german visitors, a/fr/ endpoint for the french and an /nl endpoint for your dutch visitors.

Websites, storefronts and store views have their own characteristics:

Website

The main difference between a Magento Website and Store is that the first one contains only customer data with no products and categories.

In short:

  • It is possible to maintain a separate customer base for the website, or share the customer accounts with all websites.
  • Different base currencies and payment methods can be defined for websites.
  • A different order base can be maintained.
  • Different prices can be given for the website using a configuration setting or you can share the price globally.
  • Different Website URLs can be used or can share the same website URL (Magento keeps unique cookies).

Keep in mind that having a Website is not enough: working with the front-end specific components like categories and product displays is possible only from the stores.

Store

When you wish to manage a range of stores at the same time using the same Magento installation, this is the option you need.
For example, you sell a brand that is offering both male and female clothing.
Using store fronts can have separate sites for women and men respectively with only one admin interface to control two stores.

In short:

  • Customer accounts are shared among all the stores under a specific website.
  • Use the same base currency and payment options.
  • Use the same product prices.
  • Products can be assigned to specific stores.
  • Can have different root category configuration.

Store View

Store views are usually used to present the store in different languages, although they can be used for other purposes, as well. Customers use the language chooser in the header to change the store view.

In short:

  • The common practice is to distinguish between different language views for stores.
  • Use different display prices for each store view.
  • Category settings can vary between store views.
  • Uses the same root category for all store views.
  • Inventory is shared across all the websites and stores. Either the product is IN STOCK or not.

More information can be found in the Magento 1 documentation about websites, stores and views (Magento 1) and The documentation for Magento 2

Configuration on Hypernode

On Hypernodes you are completely free to use any of the upper mentioned constructions.

Using the http.magerunmaps configuration file in /data/web/nginx/, you can configure your shop to use separate domains, sub directories or combinations of those 2 for stores and websites.

DNS Entries

First, create the needed DNS records to configure your store. If you will be serving your site on www.example.com, make sure the www dns record exists and points to the IP address of the hypernode.

There are two ways to point the DNS to your Hypernode:

  • Let Byte manage your DNS
  • Use CNAME records to point your DNS

The first option is the preferred options. Both ways are explained in the article DNS settings Hypernode.

When Byte manages your domains, read the article Link your domain to your Hypernode to complete the set-up.

Creating the storefronts and store-codes

After creating your DNS entries, we first configure the storefronts in your Magento admin backend. To route different store(views) to different domains, the configuration in the Magento admin backend should be completed first.
We won’t go into detail how to do this in this article. Follow the instructions for Magento 1 or the ones for Magento 2 in the documentation pages by Magento itself.

Listing the available storefronts

Using magerun, you can easily list all the stores and store views that are configured in Magento. We need the stores and the store codes to route each domain or subdirectory to it’s specific store(view)

To do this, use the following command:

For Magento 1:

n98-magerun sys:store:config:base-url:list

Or use the alias sf we created as a shortener.

For Magento 2:

n98-magerun2 sys:store:config:base-url:list

Or use the alias sf2 we created as a shortener.

This will generate a list of all storefronts, the store code and its URLs.

Configuring the http.magerunmaps file

When we have the list of store codes and their URLs, we need to create some Nginx configuration. Magento determines which store(view) to serve by store code.
This code is inserted in the environment of each request that is handled by php-fpm as an environment variable. Magento uses this environment variable to determine which content to serve for the request.

These codes are inserted in the environment by Nginx, using a mapping.

To set a different code for each domain name, we edit the http.magerunmaps file, which is the configuration to establish this.
Initially the http.magerunmaps file will look like this:

## Use this file to connect domain names with storefronts.
## By default, these variables are unset and logic in Magento's
## index.php will take over.
##
## Use this file if you do not want to hack index.php. Follow the
## commented examples.

# should be named runcode :)
map $http_host $storecode {
 hostnames;
 default mydefault_storecode;
   .yourshopA.com shop_a;
   .yourshopB.com shop_b;
}

# should be named runtype :)
map $http_host $storetype {
 hostnames;
 default store;
   .yourshopA.com website;
   .yourshopB.com store;
}

The variables inserted in the environment is the $storetype for websites and the $storecode variable for stores.
This mapping will set the $storecode variable, depending on the defined hostnames. If non of the defined hostnames match the one currently used, the default is set.

Example:

Lets use 2 store codes as an example. One store is using shop.example.nl and the other uses shop.example.be to serve both Dutch and Belgian users.
Additional, international visitors of your shop should be served the international shop that uses shop.example.com and shop.example.net as domains and both use shop_int as store code.
These domain names are just examples, they can be anything, as long as they differ from each other.

You created a store for the Dutch visitors with store-code store_nl and a store for the Belgian visitors with store-code store_be.

Now if we want to configure shop.example.nl to use the store_nl code, we can adjust the snippet for the store-code to:

map $http_host $storecode {
 hostnames;
   .example.nl shop_nl;
}

Notice the dot . instead of the ‘www’ part of the url: This dot functions as a wildcard. All subdomains ending with example.nl will now use store code shop_nl.
This effectively works for www.example.nl, shop.example.nl, b2b.example.nl etc.

Now if we want to add the Belgian store as well, we’ll add it to the snippet:

map $http_host $storecode {
 hostnames;
   .example.nl shop_nl;
   .example.be shop_be;
}

If you want to serve your international non-Dutch and non-Belgian customers using another storefront, we can choose to set a default value as well.
This will match all domains not defined specifically and functions as a catchall.

In this example we’ll use shop_int store-code for the international customers:

map $http_host $storecode {
 hostnames;
 default shop_int;
   .example.nl shop_nl;
   .example.be shop_be;
}

Using this method, you can link any domain to any store code using Nginx mappings.

This works similar for your website mapping, which most users don’t need as it is not frequently used:

map $http_host $storetype {
 hostnames;
 default store;
   .yourshopA.com website;
   .yourshopB.com store;
}

This way you can select whether your domain is used as a website or as a store.

Autogenerating a http.magerunmaps file

We created a plugin to autogenerate your Magerun mappings. This is not 100% accurate, but in most of the cases it works like a charm.
This plugin guesses your magerunmapping based on the configuration of your stores in the database of Magento.

Currently this plugin only works for Magento 1 and not for Magento 2.

To use this plugin, issue the following command:

cd ~/public && n98-magerun hypernode:maps-generate

This will return a list similar to this one:

---------------------------------------------
  Mage run maps for Nginx. [Byte Hypernode]
---------------------------------------------

map $host $storecode {
 hostnames;
default shop_int;
    .example.be shop_be;
    .example.nl shop_nl;
}

Don’t forget to remove the n98-magerun header from the output!

Additional information

0