Configure nginx to host multiple subdomains
Tags: nginx, config, subdomain
Published: 2019-02-17 02:36:40

---
title: Configure nginx to host multiple subdomains
published: true
description: Configure nginx to host multiple subdomains
tags: nginx, config, subdomain
---

*This post has been cross-posted from my [blog](https://blog.onstash.me/nginx-subdomain-config/)*

---

Configuring nginx for subdomains in the same machine was confusing for me. So I am writing this tutorial primarily for (self)reference but people can find it useful. Without much ado, let's get started.

For those of you who don't know what nginx is exactly, head over to this [freeCodeCamp article](https://medium.freecodecamp.org/an-introduction-to-nginx-for-developers-62179b6a458f) as a starting point.

I assume you're on a linux machine and you know what nginx means.

First and foremost, install nginx -
```bash
sudo apt-get install nginx
```

Second head over to `/etc/nginx/sites-available/default` by opening it on vim/nano. You would come across something like this - 

```
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
    #
    # Note: You should disable gzip for SSL traffic.
    # See: https://bugs.debian.org/773332
    #
    # Read up on ssl_ciphers to ensure a secure configuration.
    # See: https://bugs.debian.org/765782
    #
    # Self signed certs generated by the ssl-cert package
    # Don't use them in a production server!
    #
    # include snippets/snakeoil.conf;

    root /var/www/html;

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

    server_name _;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    # pass PHP scripts to FastCGI server
    #
    #location ~ \.php$ {
    #   include snippets/fastcgi-php.conf;
    #
    #   # With php-fpm (or other unix sockets):
    #   fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    #   # With php-cgi (or other tcp sockets):
    #   fastcgi_pass 127.0.0.1:9000;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #   deny all;
    #}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#   listen 80;
#   listen [::]:80;
#
#   server_name example.com;
#
#   root /var/www/example.com;
#   index index.html;
#
#   location / {
#       try_files $uri $uri/ =404;
#   }.
#}
```

From the above you can gather the following points - 
* `server {}` - that tells nginx that "Hey this is how I think you should configure the server"
* `listen 80` - translates to "Listen to port 80, which is the default port for web clients"
* `root /var/www/html;` - nginx understands that HTML file/files from that location can be served
* `index index.html index.htm index.nginx-debian.html;` - this indicates that these kind of files should be served in a decreasing order of priority (left to right).
* `server_name _;` - this conveys that `_` is the server name. Assuming our domain to be `example.com`, the server name would be `example.com`. That's because when a request is received for `example.com`, nginx should whether to process it or not.
* `location / {}` - this means that all requests must be handled by this server config. There is an option to handle specific requests as well. For example, requests starting with `/server_1` can load `server_1.html` and all other requests can load `default.html`.

Next obvious question is - how do I configure subdomains?

It's not that complicated. It involves 7 steps - 

* Copy the default configuration and rename it as `subdomain1.example.com`.
```bash
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/subdomain1.example.com
```

Note: You don't necessarily have to name the file `subdomain1.example.com`. It's easier if you follow a convention that makes it easy for everybody involved.

* Open it and remove the term `default_server` besides `listen 80` and the line below it. This is crucial.
* Change the `server_name` as `subdomain1.example.com` & change the HTML `root` that's being used
* Then link that file to a file in nginx's sites-enabled directory. This is for nginx to understand that configuration `subdomain1.example.com` is enabled in the configuration.
```
sudo ln -s /etc/nginx/sites-available/subdomain1.example.com /etc/nginx/sites-enabled/subdomain1.example.com
```
* Write a HTML file inside `/var/www/html` for `subdomain1.example.com`
* Restart the nginx server
* If you're using a DNS provider like Cloudflare, add the box's IP to it with an A record `subdomain1.example.com`. If not, then add the box's IP and subdomain1.example.com to /etc/hosts.
* Load `subdomain1.example.com` on the browser to check how it loads. If everything is fine, you will see the HTML that you wrote for this subdomain.

Extend the same approach for any other domain or subdomain that you require.