How to setup subdomain or host multiple domains using nginx in linux server

Did you know, you can host multiple domains and subdomains using single ip address in linux via nginx server blocks (or virtual hosts in apache)?

Well if you don't know how to do that reading this tutorial will setup you two domains and one subdomain both pointing to the same ip address and host on the same server. Here's the general assumption for this setup:

  • IP Address:

  • Domain names: example.com, blog.example.com, fakenews.com

Before starting the tutorial, first thing you've to do is to point all your domains and subdomains to the single ip address via your DNS provider (edit A, CNAME). However if you want to test this locally, then edit the /etc/hosts configuration file and add the following: example.com blog.example.com fakenews.com

And when you ping these domains locally on the server, you'll get ok (200) response.

Now we'll follow the steps to setup these domain names:

1. Install and start nginx

Use the following command to install nginx on ubuntu

$ sudo apt install nginx
# now start it
$ sudo nginx

2. Test the nginx

Check any of the domains or ip address in your browser to make sure nginx works correctly. The browser will output a default nginx page.

3. Setup the test directories for each domains

Up until now, all the domains have set up correctly but there is one huge problem, all pointing to same page. We need to separate these domains to point to their own pages. For this, I will setup test directories and html pages.

  • Creating directories for each domains and subdomain

$ cd /var/www
$ sudo mkdir example.com blog.example.com fakenews.com
  • Creating simple html pages for each

$ sudo touch example.com/index.html
$ sudo touch blog.example.com/index.html
$ sudo touch fakenews.com/index.html
  • Lastly put some different content in each index.html files

4. Creating server blocks for each domains and subdomain

Nginx provide default server block in /etc/nginx/sites-available. We will copy that server block for each domains and do modifications for each. Also we will create symbolic link of new file

## For example.com domain
$ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com
$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
## similarly do for others also.

Now after modification, the new file will look like this for example.com domain

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  root /var/www/example.com;
  index index.html;
  server_name example.com;

Here default_server means if none of the other domains resolve, the last resort is to resolve this server block.

NOTE: There is only one default server block in nginx with same port.

Similarly for other two domains the configuration are:

## For blog.example.com subdomain
server {
  listen 80;
  listen [::]:80;
  root /var/www/blog.example.com;
  index index.html;
  server_name blog.example.com;

## For fakenews.com domain
server {
  listen 80;
  listen [::]:80;
  root /var/www/fakenews.com;
  index index.html;
  server_name fakenews.com;

Bonus: Suppose fakenews.com domain listen on different port (say 2368 port) and you want to proxying port in nginx to default 80 port, then you can use location block inside server block like this:

server {
   ## other configuration as above
    # ...
  location {
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header HOST $http_host;