How to setup secure subdomains using nginx and certbot on a VPS
Tags: devops, nginx, server, certbot
Published: 2020-06-09 18:29:16

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](https://m.do.co/c/139ece3a635f) 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


```sh
$ ssh user@hostname
```

### 2 - Install and start nginx

Use the following command to install nginx on your VPS


```sh
$ 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

```sh
$ cd /var/www

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

```
#### Creating simple html pages for each


```html

<!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

```sh

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

```

### 4 - Creating server blocks for each subdomain


```sh

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



```sh

$ sudo nano dashboard.example.com

```
- Copy and paste the configurations given below


```sh

## 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

```sh


$ 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

```sh
$ 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

```sh

$ 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

```sh
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


```sh

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

```

Update the server block with these configurations

```sh

# 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

```sh
$ 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