# A Step-by-Step Guide to Implementing SSL for Your ASP.NET API.

Creating an ASP.NET API is straightforward, but securing it with HTTPS requires additional steps. In this blog, I’ll walk you through setting up SSL for your [ASP.NET](http://ASP.NET) API to ensure secure communication.

## Table of Content

* Containerize your ASP.NET API (with Docker)
    
* Set up Nginx (HTTP)
    
* Create a Certificate with Certbot
    
* Set Up SSL on Nginx (HTTPS)
    
* Automate Certificate Renewal (for Ubuntu)
    
* Summary
    

## Containerize your ASP.NET API

If you have the Docker extension installed in Visual Studio, it will automatically create a container image for your [ASP.NET](http://ASP.NET) API. You can then upload this image to a registry, such as DockerHub. Here’s how you can use Docker Compose to configure and run your container:

```yaml
services:
  yourapiname:
    image: yourusername/yourapi
    ports: 
      - 5556:5000
```

The Standard Port for the [ASP.net](http://ASP.net)[API](http://asp.net/) is 5000 and is only accessible inside the Container or a Container Network. So, in the configuration, port 5000 is published to port 5556. This means port 5556 should be accessible from the browser. Let's check that by running the command `docker-compose up` and verifying if the Swagger file is accessible.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732963259934/627262eb-e47f-4fad-9dd7-3c6cfe43e00f.jpeg align="center")

If the Swagger file is accessible, we can proceed to set up Nginx.

## Set up Nginx (HTTP)

Nginx is a high-performance web server that can also be used as a reverse proxy, load balancer, mail proxy, and HTTP cache. In this setup, we will use Nginx as a reverse proxy to route HTTP requests to our [ASP.NET](http://ASP.NET) API container.

Our goal is to access the Swagger file over HTTP on the standard port 80. We’ll set up an Nginx server to listen on port 80 and configure it to proxy requests to our API container on internal port 5000. Here’s how you can configure Nginx:

```nginx
events {
    worker_connections 1024;
}

http {
    server_tokens off;
    charset utf-8;
    server {
        listen 80;

        server_name _;

        location /swagger/ {
            proxy_pass http://yourapiname:5000/swagger/;
            index  index.html index.htm;
        } 
    }
}
```

Save the file and name it `nginx.conf`.

Now we can update the Docker Compose file:

```yaml
services:
  yourapiname:
    image: yourusername/yourapi

  nginx:
    restart: unless-stopped
    image: nginx
    ports: 
      - 80:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
```

I have removed the port mapping from `stoicquotesmailregistrator` and added a new container `nginx`. For the new container, we have exposed port 80 and mapped the config file into the container. When we now run `docker-compose up -d`, the Swagger file should be available on port 80. Let's check.

The old Page is not accessible anymore:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732963617625/4b1cfee1-296c-46c7-86ad-a88856063894.jpeg align="center")

Port 80 is now working:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732963771214/02683af9-34cd-40a5-810a-324107bfc820.jpeg align="center")

## Create a Certificate with Certbot

Certbot is a free, open-source tool for automatically using Let’s Encrypt certificates on manually-administrated websites. We need to configure Nginx to serve the challenge files that Certbot will use to verify our domain ownership. Here’s how to set up Certbot with Docker Compose.

Add a challenge location for Certbot in the `nginx.conf` file:

```nginx
location ~ /.well-known/acme-challenge/ {
    root /var/www/certbot;
}
```

Also, add two volumes to the Nginx container. These are needed so Certbot can communicate with the Nginx server and manage the SSL certificate:

```yaml
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
```

Then we can add Certbot to the Docker Compose file. Please add your email and your domain in the command:

```yaml
certbot:
    image: certbot/certbot
    volumes: 
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    command: certonly --webroot -w /var/www/certbot --force-renewal --email {mail} -d {domain} --agree-tos
```

When you run `docker-compose up -d`, a certificate should be created.

## Set Up SSL on Nginx (HTTPS)

o set up the SSL connection, we add a new server block with port 443. We also add the path to the certificates and the location with the link we want to publish.

```nginx
    server {
        listen 443 ssl;
        # use the certificates
        ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;
        server_name {domain};

        location /swagger/ {
            proxy_pass http://containerName:5000/swagger/;
            index  index.html index.htm;
        }
    }
```

*Replace* `{domain}` *with your domain.*

This should be it. Run `docker-compose up -d` and open the site with HTTPS. The certificate should be visible in the browser now.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732963858742/5e09c7cf-9932-48fb-90c4-930dd6846f54.jpeg align="center")

## Automate Certificate Renewal

Let’s Encrypt certificates are only valid for 90 days. To ensure continuous security, we need to automate the renewal process. Add the following command to your crontab to schedule automatic renewals (open with `crontab -e`):

```bash
/usr/bin/docker compose -f /root/projects/reverseProxy-nginx-ssl/docker-compose.yml restart
```

To change the certificate properly we need to restart the nginx after the certificate was newly created. For that we can add a dependency between nginx and certbot with the `depends_on` parameter.

```yaml
  nginx:
    restart: unless-stopped
    depends_on: 
      certbot:
        condition: service_completed_successfully
    image: nginx
    ports: 
      - 80:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
```

# Summary

In this guide, we’ve walked through setting up a secure [ASP.NET](http://ASP.NET) API using Docker, Nginx, and Certbot. We configured Nginx to proxy HTTP and HTTPS requests to our API container and set up automatic certificate renewal. Here are the final configurations for Nginx and Docker Compose:

### Nginx Configuration

```nginx
events {
    worker_connections 1024;
}

http {
    server_tokens off;
    charset utf-8;
    
      access_log  /var/log/nginx/access.log;

    server {
        listen 80;

        server_name _;

        location /swagger/ {
            proxy_pass http://containerName:5000/swagger/;
            index  index.html index.htm;
        }

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        location ~ /.well-known/acme-challenge/ {
            root /var/www/certbot;
        } 
    }

    server {
        listen 443 ssl;
        # use the certificates
        ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;
        server_name {domain};

        location /swagger/ {
            proxy_pass http://containerName:5000/swagger/;
            index  index.html index.htm;
        }
    }
}
```

### Docker Compose Configuration

```yaml
services:
  yourapiname:
    image: yourusername/yourapi

  nginx:
    restart: unless-stopped
    depends_on: 
      certbot:
        condition: service_completed_successfully
    image: nginx
    ports: 
      - 80:80
      - 443:443
    volumes:
      - /root/projects/reverseProxy-nginx-ssl/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot

  certbot:
    image: certbot/certbot
    volumes: 
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    command: certonly --webroot -w /var/www/certbot --force-renewal --email <mail> -d <domain> --agree-tos
```

This is my first blog, so please give me feedback! :)
