How to Set Up Multiple Websites on a Single Server with SSL [Ubuntu + Nginx + Let’s Encrypt]

In this tutorial, I will show how to configure Server Blocks in Nginx to host 02 separate websites on an Ubuntu 22.04 server. Also, the websites will be secured with SSL using Let’s Encrypt.

Harsha Nanayakkara
7 min readSep 3, 2022

If you already have Nginx installed, please click here to skip the installation steps and jump directly into the tutorial.

First, we should install Nginx on the Ubuntu server. In case if you don’t have it, run the below commands to install and verify.

$ sudo apt update
$ sudo apt install nginx -y
$ nginx -v --> checks the installed version

Once Nginx is installed, it is always good to check the status to make sure it is running and enabled to automatically start even after the server is restarted.

To check the status → $ systemctl status nginx . The output should be like the following screenshot.

systemctl status nginx

You could also try to access the respective server IP through the web browser to ensure the default Nginx welcome page is loaded without issue.

Nginx Default Welcome Page

All right. Now we can move ahead with the Website setup.

Note: The domain names used for this demo are as follows;

  • mywebsite1.com
  • mywebsite2.com

Step 01: Create Directory Structure within /var/www/

By default, Nginx has /var/www/html directory to serve the default welcome webpage. However, we will create additional directories within /var/www/ for each of the sites besides the default html directory.

$ sudo mkdir -p /var/www/mywebsite1.com/html
$ sudo mkdir -p /var/www/mywebsite2.com/html

We have created html directory within the site-specific directories to keep the website files. This will make the directory structure more understandable.

What Permissions Should I Have?

Well, there are many debates on how to setup the permissions on website directories. Anyway, I won’t get into more details on permissions here because it is a broad topic for another day! I have used the permissions as described below to keep the things simple and restrict unwanted access.

Your user (ubuntu in this case) will be the owner of the website directory with full permissions (read, write, execute). -R stands for recursive where it will update owner of each and every file and folder inside the directory.

$ sudo chown -R ubuntu /var/www/mywebsite1.com/html
$ sudo chown -R ubuntu /var/www/mywebsite2.com/html

Web server (www-data in this case) will be the group owner with only read and execute permissions.

$ sudo chgrp -R www-data /var/www/mywebsite1.com/html
$ sudo chgrp -R www-data /var/www/mywebsite2.com/html

Now, we should give permissions to user (u), group (g) and others (o) respectively. Here, we will set read,write, eXecute permissions for the user and read, eXecute permissions for the group and zero permissions for others. In other words, permissions should be 750.

Note: When using the -R flag, make sure to use the X (capital x) instead of x (simple x). This will specify that execute permissions should only be set on directories, not regular files.

$ sudo chmod -R u=rwX,g=rX,o= /var/www/mywebsite1.com/html
$ sudo chmod -R u=rwX,g=rX,o= /var/www/mywebsite2.com/html

The final command makes all the files and folders created inside the directory to automatically inherit same group ownership as the parent folder (html in this case), which has been set to www-data previously. This allows the web server to read and execute the files without any issue.

$ sudo chmod g+s /var/www/mywebsite1.com/html
$ sudo chmod g+s /var/www/mywebsite2.com/html

Note: It is recommended NOT to allow web server to write to whole website directory due to security reasons. If you have folders that needs to be writable by the web server, only allow the write permission on that specific folder only.

Step 02: Create Default Web Pages for Each Site

Now, let’s create default web pages to display some content to distinguish sites so that we can check if both sites are working later on. For that, we need to create an index.html file within the directory structures created earlier. For this demo, I will create the file and add some text to it through the terminal using the following command.

$ echo "Welcome to My Website 1" > /var/www/mywebsite1.com/html/index.html$ echo "Welcome to My Website 2" > /var/www/mywebsite2.com/html/index.html

Step 03: Create and Enable Virtual Host (AKA Server Blocks) for Domains

In this section, we will configure the Server Blocks to instruct Nginx how to server the web content.

It has a default server block in /etc/nginx/sites-available/default . We will create a new file inside the sites-available directory for our own task as below.

$ cd /etc/nginx/sites-available/
$ sudo nano mywebsite1.com

Include the following lines of commands. Repeat the steps for other domain as well. Change the server_name and root directives accordingly.

server {
listen 80;
listen [::]:80;
server_name mywebsite1.com www.mywebsite1.com; root /var/www/mywebsite1.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}

Once create, we have to enable the server blocks, so that Nginx will read them during startup. For that, we should connect the created files to sites-enabled directory using symbolic links.

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

If you cd into the sites-enabled directory it will show the links as below;

mywebsite1.com -> /etc/nginx/sites-available/mywebsite1.com
mywebsite2.com -> /etc/nginx/sites-available/mywebsite2.com

Lastly, we need to restart Nginx to enable the changes.

$ sudo systemctl restart nginx

Step 04: Test the Results

For this demo, I have added relevant entries to the hosts file to test the results. Since I am using a windows machine, hosts file can be found in C:\Windows\System32\drivers\etc , which I have modified like below. Insert the web server’s public IP into the <web server public IP> placeholder without the brackets.

<web server public IP> mywebsite1.com www.mywebsite1.com
<web server public IP> mywebsite2.com www.mywebsite2.com

Then go to the browser and type the domain name and Voila! the sites are working. YAY!

mywebsite1.com
mywebsite2.com

Now, we have successfully configured the Nginx web server to serve our web sites. Next part is to secure the sites with SSL.

Step 05: Configure SSL for the Websites Using Let’s Encrypt

Let’s encrypt allows anyone with a domain name to secure their sites with trusted certificates at zero cost. According to the official documentation they recommend to use Certbot ACME client. This installation is for an Ubuntu machine running Nginx.

You can get customized instructions for other operating system and web servers from here.

Install snapd

In my case, I already had snapd installed. For more details and installation instructions it is recommended to refer the official website.

For Ubuntu it is as follows;

$ sudo apt update
$ sudo apt install snapd

Remove certbot-auto and any Certbot OS packages

This section is only applicable if you already have any Certbot packages installed previously using apt, yum or dnf. You should remove them before installing the Certbot snap.

Install Certbot

Run the following command to install Certbot.

$ sudo snap install --classic certbot

Enable the Certbot Command to Run

Symbolic link should be created as shown below to allow the Certbot command to run properly.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Get a Certificate

Certbot can edit the Nginx file automatically. However, I don’t want that. I just need a certificate so that I can edit Nginx file manually by my self.

$ sudo certbot certonly --nginx

You will be asked for an email address. Once your provide it will list the existing domain names for selection to enable HTTPS. You will see an output like the following screenshot.

Note: I used NO-IP website to configure DNS for this demo to be able to create SSL certificates through let’s encrypt. Therefore, I had to change the domain name as mywebsite1.ddns.net . This free service only allows 1 domain for free. So, I could only enable SSL for mywebsite1.ddns.net . However, the process is same to enable SSL for any number of domains.

Once you have the certificates it is time to update the respective Nginx configuration file. We will add the certificates into the mywebsite1.com file inside/etc/nginx/sites-available .

Make sure to insert semicolon (;) after each line, otherwise it will say nginx: [emerg] invalid number of arguments in “ssl_certificate” directive in /etc/nginx/…

server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/mywebsite1.ddns.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite1.ddns.net/privkey.pem;
server_name mywebsite1.ddns.net; root /var/www/mywebsite1.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}

Check for any errors with $ sudo nginx -t . If all good you can safely reload the nginx service.

$ sudo systemctl reload nginx

You will see the secured padlock icon next to the address bar.

SSL enabled website

We have successfully configured a web server on an Ubuntu machine with Nginx and secured the site with SSL. Let’s call it a day!

I sincerely hope this article will be helpful for anyone in the process of configuring their own Web server. I highly value your feedback and support!

Thank you for reading and stay safe!

--

--

Harsha Nanayakkara

An enthusiastic autodidact who is passionate to gain and freely share knowledge. I would really appreciate your feedback and support!