homeLogo

~ 8 min read

Serving multiple sites using Nginx

Nginx is a web server and reverse proxy server. It is a free and open source software package designed for running a web server. It is a high performance web server, written in C.

Nginx Subdomains

This tutorial comes with hands-on demos but doesn’t require many prerequisites and will assume you have an Ubuntu Server LTS with SSH enabled and NGINX installed.

Setting Up DNS Records

Before you can serve NGINX subdomains or multiple domains, you will need to add an A record in a DNS control panel. The A record binds and points all domains and subdomains to a single IP address to let web browsers find your website.

1. Launch your favorite web browser, and log in to your DNS control panel.

2. Click on Add Record to start adding A records. Your browser redirects to a page where you’ll configure DNS settings for your domain and subdomains.

Adding an A Record

Now configure the DNS settings with the following:

Select A record in the Type field.

Enter @ in the Host field, and your server IP in the Value field.

Select your desired value in the TTL field, then click on the Confirm button to save the settings.

Repeat the same process for other subdomains.

Configuring DNS settings for Domain and Subdomains The final DNS Settings page looks like the one below.

Viewing DNS Settings Page

Your DNS record control panel may vary in functionality and design, but the same principles will apply to all.

Setting Up Web Directories for NGINX Domain and Subdomain

Now that you’ve added A records for your domain and subdomains, it’s time to set up their web directories. NGINX comes with a default virtual host file and is configured to serve a web directory located at /usr/share/nginx/html.

You’ll create a separate web directory for each domain inside the NGINX default document root /var/www/html.

1. First, open your terminal and run the commands below to create web directories for all domains and subdomains. Doing so separates, organizes, and isolates files for each website.

sudo mkdir /var/www/html/example.com
sudo mkdir /var/www/html/web1.example.com
sudo mkdir /var/www/html/web2.example.com

2. Next, run the chown command to recursively (-R) change the ownership of each directory you created in step one to www-data user and group. You’re changing ownership of each directory to www-data user and group since NGINX runs as a www-data user.

sudo chown -R www-data:www-data /var/www/html/example.com
sudo chown -R www-data:www-data /var/www/html/web1.example.com
sudo chown -R www-data:www-data /var/www/html/web2.example.com

3. Create a file named index.html in your preferred code editor and then copy/paste the code below to the index.html file. Save the file inside your domains’ primary web directory _/var/www/html/example.com .

The HTML code below displays a message that says “Congratulations! The example.com website is working!” when the index.html file is opened in a web browser.

<html>
    <head>
        <title>Welcome to example.com!</title>
    </head>
        <body>
        <h1>Congratulations! The example.com website is working!</h1>
    </body>
</html>

4. Finally, create the same index.html in the /var/www/html/web1.example.com and /var/www/html/web2.example.com directories. But replace example.com with web1.example.com, and web2.example.com in the code of each index.html accordingly.

Setting Up Virtual Host for NGINX Domain and Subdomains

You already have an index.html page for your domain and subdomains to serve through an NGINX web server. The next step is you’ll create an NGINX virtual host configuration file for each domain to serve the HTML pages.

1. Create an NGINX virtual host configuration file in your preferred code editor, and then copy/paste the code below to that file. Save the file in the /etc/nginx/sites-available/ directory. The code below controls the behavior of your server, such as the server name and index (home) page when a user tries to access your domain.

server {
    # Binds the TCP port 80.
    listen 80; 

            # Root directory used to search for a file
    root /var/www/html/example.com;
            # Defines the file to use as index page
    index index.html index.htm;
            # Defines the domain or subdomain name. 
    # If no server_name is defined in a server block then 
            # Nginx uses the 'empty' name
    server_name example.com;

    location / {
        # Return a 404 error for instances when the server receives 
                    # requests for untraceable files and directories.
        try_files $uri $uri/ =404;
    }
}

2. Next, run the following nginx command to check (-t) the NGINX configuration file for any syntax error. sudo nginx -t If no syntax error is found in the NGINX configuration file, you will get the following output.

Verifying NGINX configuration file

3. Next, run the below command to create a symbolic link (ln -s) from the /etc/nginx/sites-available to the /etc/nginx/sites-enabled/ directory. This command enables the example.com virtual host configuration file.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

The sites-available and sites-enabled format are standard within an NGINX Ubuntu installation but other distributions may use a different standard.

4. Repeat steps one to three to create NGINX virtual host configuration files namedweb1.example.com_ and web2.example.com.

Change the following lines in each NGINX virtual host configuration file:

  • Replace the line root /var/www/html/example.com with the webroot directory of each subdomain (root /var/www/html/web1.example.com and root /var/www/html/web2.example.com).
  • Replace the line server_name example.com with the name of each subdomain (server_name web1.example.com and server_name web2.example.com).

5. Now run the sudo ln commands below as you did in step three to enable the virtual host configuration files.

# Enables web1.example.com NGINX virtual host configuration file
sudo ln -s /etc/nginx/sites-available/web1.example.com /etc/nginx/sites-enabled/
# Enables web2.example.com NGINX virtual host configuration file
sudo ln -s /etc/nginx/sites-available/web2.example.com /etc/nginx/sites-enabled/

6. Run the below systemctl command to restart the NGINX (restart nginx) service to apply all configuration changes.

sudo systemctl restart nginx

7. Finally, navigate to the domain and subdomains’ URLs on your browser to test if the websites work fine.

If the domain and subdomains load up, you’ll see a message like the one below.

Verifying websites are loading through the web browser.

Setting Up HTTPS on NGINX Domain and Subdomain

You’ve successfully set up and tested an NGINX domain and subdomains on HTTP protocol, which is great. But you must secure your domain and subdomains’ connection by enabling HTTPS. How? With a certificate that you’ll get from a Certificate Authority like Let’s Encrypt SSL.

1. First, run the command below to install the Certbot software package (apt-get install certbot). Certbot lets you download an SSL certificate for your domain and subdomains.

sudo apt-get install certbot python3-certbot-nginx -y

2. Next, run the certbot command below to download an SSL certificate (certonly) for your domain (-d example.com). Notice that you agree to the term of service (—agree-tos) with your email address (—email).

sudo certbot certonly --agree-tos --email [email protected] -d example.com

Replace the email with your own.

3. Enter ‘1’ to select the NGINX Web Server plugin (nginx) to authenticate with the ACME CA, as shown below.

Selecting Plugin to Authenticate with ACME CA

After selecting the NGINX Web Server plugin, you’ll see the download progress of the SSL certificate for your domain (example.com).

By default, Let’s Encrypt’s SSL certificates are stored in the /etc/letsencrypt/live/ directory.

Showing Download Progress of the SSL Certificate

4. Now run each command below as you did in step two to download SSL certificates for the remaining subdomains (web1.example.com and web2.example.com).

sudo certbot certonly —agree-tos —email [email protected] -d web1.example.com sudo certbot certonly —agree-tos —email [email protected] -d web2.example.com

5. Finally, run the ls command below to list all SSL certificates in the /etc/letsencrypt/live/ directory that contain (*) the example.com in their names. Doing so lets you verify that the SSL certificates exist.

ls /etc/letsencrypt/live/*example.com/

Configuring NGINX Virtual Host to Use SSL Certificates

At this point, you already have SSL certificates at your disposal. But how do you use them to secure your domain and subdomains? You’ll define the certificates’ path in the server block of each NGINX virtual host configuration file.

1. Open the example.com NGINX virtual host configuration file sitting at the /etc/nginx/sites-available/ directory in your preferred code editor.

2. Replace the content of the file with the code below, where you define your domain’s SSL certificate’s path, and SSL protocol (under Path of the SSL certificate).

server {
            # Binds the TCP port 80.
        listen 80;
            # Defines the domain or subdomain name. 
        # If no server_name is defined in a server block then 
            # Nginx uses the 'empty' name
        server_name example.com;
            # Redirect the traffic to the corresponding 
            # HTTPS server block with status code 301
        return 301 https://$host$request_uri;
        }

server {
        # Binds the TCP port 443 and enable SSL.
        listen 443 SSL;
            # Root directory used to search for a file        
            root /var/www/html/example.com; 
            # Defines the domain or subdomain name. 
        # If no server_name is defined in a server block then 
            # Nginx uses the 'empty' name
        server_name example.com;

            # Path of the SSL certificate
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
            # Use the file generated by certbot command.
        include /etc/letsencrypt/options-ssl-nginx.conf;
            # Define the path of the dhparam.pem file.
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
            # Return a 404 error for instances when the server receives 
            # requests for untraceable files and directories.
        try_files $uri $uri/ =404;
        }

    }

3. Repeat the same process (steps one to two) for the remaining virtual host configuration files web1.example.com and web2.example.com. But be sure to replace the SSL certificate’s path with your subdomain’s certificate’s path (under Path of the SSL certificate).

4. Now rerun the systemctl command below to restart the NGINX service to apply the configuration changes.

sudo systemctl restart nginx

5. Finally, navigate to your domain and subdomain’s URLs on your web browser. But this time, instead of the HTTP protocol, use HTTPS to see if they work.