Funny Side Up

Configure nginx to host multiple subdomains

February 16, 2019

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 as a starting point.

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

First and foremost, install nginx -

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.

    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.


Santosh Venkatraman

Personal blog by Santosh Venkatraman.
Technology, life, and such.