DEV Community

Cover image for How to setup secure subdomains using nginx and certbot on a VPS
Bruce
Bruce

Posted on

How to setup secure subdomains using nginx and certbot on a VPS

Did you know that you can host as many subdomains as you want thanks to nginx on a VPS?

Well if you don't know how to do that, reading this tutorial is going to help you setup subdomains assuming that you already have a domain setup already.

Here's the general assumption for this setup:

  • Ubuntu server
  • A fully registered domain name: example.com (use your real domain name)
  • Subdomain names: dashboard.example.com, shop.example.com

Before starting this tutorial, first thing you've to do is to point all your subdomains to your server’s public IP address via your DNS provider (edit A, CNAME).

I am using DigitalOcean because of how easy it is to get started. If you can sign up on DigitalOcean with my Referral Link you get $100 in credit that can be spent in 60 days.

Well enough with talking let's jump straight to it:

1 - SSH into your VPS

$ ssh user@hostname

2 - Install and start nginx

Use the following command to install nginx on your VPS

$ sudo apt install nginx

# start nginx service

$ sudo systemctl start nginx

3 - Setup the test directories for each subdomain

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

Creating directories for each subdomain

$ cd /var/www

$ sudo mkdir shop.example.com dashboard.example.com

Creating simple html pages for each


<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Example.com</title>
    </head>

    <body>
        <h1>It works</h1>
    </body>

</html>

Copy and paste the code above in each of the html files


$ sudo nano shop.example.com/index.html
$ sudo nano dashboard.example.com/index.html

4 - Creating server blocks for each subdomain


cd /etc/nginx/sites-available

Inside /etc/nginx/sites-available. We are going to create server block for each subdomains and do modifications for each.We are also going to create symbolic link of each file


$ sudo nano dashboard.example.com

  • Copy and paste the configurations given below

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

Make a symbolic link



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

# do the same for the other subdomain

5 - Testing

$ sudo nginx -t
$ sudo systemctl restart nginx

If you head over to each of the subdomains in your browser you are going to see that it works but you notice that the browser is screaming at you that there is no ssl certificate

Hold on, we are going to fix that, plus there is a bonus..so keep on reading

6 - Install Certbot and generate SSL Certificate


$ sudo apt install -y certbot

# stop nginx service, this is a must
$ sudo systemctl stop nginx

# generate an ssl certificate
$ sudo certbot certonly -d shop.example.com -d dashboard.example.com

Hit enter and you are going to see this menu of options

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Nginx Web Server plugin (nginx)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2

Choose the second option and press ENTER, that's it .Now we have to do one more last thing and we are done. We need to tell nginx how to handle non secure connections.

7 - Redirect all HTTP traffic to HTTPS


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

Update the server block with these configurations


# dashboard.example.com subdomain server block
server {
    listen 80;
    listen [::]:80;
    server_name dashboard.example.com www.dashboard.example.com;
    error_page 497 https://dashboard.example.com$request_uri;
    return 301 https://dashboard.example.com$request_uri;
}

server {
    listen 443 ssl;
    root /var/www/dashboard.example.com;
    index index.html index.htm;
    server_name www.dashboard.example.com;

    # ssl configuration;
    ssl_certificate /etc/letsencrypt/live/dashboard.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dashboard.example.com/privkey.pem;

    return 301 https:/dashboard.example.com$request_uri;
}
server {
    listen 443 ssl;
    root /var/www/dashboard.example.com;
    index index.html index.htm;

    # ssl configuration;
    ssl_certificate /etc/letsencrypt/live/dashboard.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dashboard.example.com/privkey.pem;
}

# do the same for the other subdomain file and make sure you replace subdomain name

You notice in the server block we are telling nginx where to look for our generated ssl certificate key and i have also added www redirection configurations as a bonus 😉!

Make sure to add an A record with www.dashboard.example.com and www.shop.example.com pointing to your server’s public IP address.

8 - Test again and Restart nginx service

$ sudo nginx -t
$ sudo systemctl restart nginx

And there you have it. Our nginx server is redirecting all www traffic to non-www over SSL. The configuration is also telling nginx to redirect all HTTP traffic to HTTPS to make sure we are secure.

Thank you for reading!

Your comments are welcome

Latest comments (1)

Collapse
 
steffen1971 profile image
steffen1971

Thank you for this tutorial.
I think there is a "/" missing and also "server_name = dashboard.example.com;" in the last server block.