Deploying with a domain name + SSL

In this post, we are going to set up a domain for our web app and also provide HTTPS support for better security. Let's add some volume mapping in the nginx service and add a new service called certbot in docker-compose-prod.yml

version: '3.8'

services:
  web:
    build:
      context: ./
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    environment:
      - ENV_VAR_NAME=VALUE
    depends_on:
      - redis
    volumes:
      - ./:/app
    command: uvicorn main:app --host 0.0.0.0 --port 8000
    # removed --reload for production
    restart: always

  redis:
    image: redis:latest
    ports:
      - "6379:6379"

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/conf.d/:/etc/nginx/conf.d/:ro
      - ./nginx/certbot/www:/var/www/certbot/:ro
      - ./nginx/certbot/conf/:/etc/nginx/ssl/:ro
    depends_on:
      - web
    restart: always

  certbot:
    image: certbot/certbot:latest
    command: certonly --webroot --webroot-path=/var/www/certbot --force-renewal --email [email protected] --agree-tos --no-eff-email -d algoholic.pro
    volumes:
      - ./nginx/certbot/www/:/var/www/certbot/:rw
      - ./nginx/certbot/conf/:/etc/letsencrypt/:rw

NGINX Service: Exposes ports 80 and 443 for HTTP and HTTPS traffic respectively. volumes: Mounts directories from your host machine into the Nginx container. By defining the volumes we are creating a mapping, Whatever we put in these volumes will be pushed in the docker container. If we put something in the docker container it will appear in the host Virtual machine.  :ro at the end of the volume declaration. ro means "read-only". The container will never have the right to update a file in this folder.

Certbot Service: certonly: Requests and obtains SSL/TLS certificates. --webroot --webroot-path=/var/www/certbot: Specifies webroot authentication method and path. --agree-tos --no-eff-email: Agrees with the terms of service and disables the EFF email subscription. -d algoholic.pro: Specifies the domain for which to obtain the certificate.

Now, let's modify the nginx/nginx.conf file to accomodate for certbot challenge.

worker_processes 4;

events { worker_connections 1024; }

http {
    sendfile on;
    server_tokens off;

    server {
    listen 80;
    listen [::]:80;
    server_name algoholic.pro;

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

    location / {
            proxy_pass http://web:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

    }
}

worker_processes: This directive sets the number of worker processes that Nginx should use. In this case, you've specified 4 worker processes. Nginx uses multiple worker processes to handle incoming client requests efficiently. The worker_connections directive sets the maximum number of connections each worker process can handle.
server: This block defines the configuration for a specific server block. In this case, it's the configuration for the HTTP server on port 80. listen 80; listen [::]:80;: These directives specify that the server should listen on both IPv4 and IPv6 addresses on port 80. location /.well-known/acme-challenge/ { ... }: This location block handles requests to the .well-known/acme-challenge/ path, which is used by Certbot for domain validation during certificate issuance. It specifies that the files for validation are located in the /var/www/certbot directory.

location / { ... }: This location block handles all other requests and acts as a reverse proxy to your FastAPI application running on port 8000. It passes the requests to the web service defined in your Docker Compose configuration. The proxy_set_header directives are used to forward necessary headers to the FastAPI application. Now we can do a dry run and check if we will be able to generate the certificate correctly.

algoholic@algoholic:~/codeshare$ docker-compose -f docker-compose-prod.yml run --rm  certbot certonly --webroot --webroot-path /var/www/certbot/ --dry-run -d algoholic.pro
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): [email protected]

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating a certificate request for algoholic.pro
The dry run was successful.

We can start and check the logs of our docker-compose to verify if everything will work correctly. Start the services with docker-compose -f docker-compose-prod.yml up

Once everything works correctly we can manually check if the certificate is synced to our local VM directory. We can also open the file and check the contents using the below code.

algoholic@algoholic:~/codeshare$ cd nginx/certbot/conf/
algoholic@algoholic:~/codeshare/nginx/certbot/conf$ ls
accounts  archive  live  renewal  renewal-hooks

#to see private key
algoholic@algoholic:~/codeshare/nginx/certbot/conf$ sudo cat ./live/algoholic.pro/privkey.pem  

Warning: if we repeatedly keep starting and shutting down the certbot service then we can hit the max rate-limit of certificate generation. So, once the certificate is generated switch to renew command in the docker-compose-prod.yml file.

certbot:
    image: certbot/certbot:latest
    command: renew   #use renew command after your ssl is configured correctly and you can visit on HTTPS
    volumes: 
      - ./nginx/certbot/www/:/var/www/certbot/:rw
      - ./nginx/certbot/conf/:/etc/letsencrypt/:rw

Finally, we can do a docker-compose -f docker-compose-prod.yml up -d to start the server in background.

Challenge: Set up a cronjob that renews the certificate every 3 months.

Challenge Solution: Please try yourself first.

algoholic@algoholic:~/codeshare$ crontab -e


#add this line
0 0 1 */2 * docker-compose -f /home/full_path_to_prod_.yml run certbot renew


 

FastAPITutorial

Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.

We know, we might make it hard for you but definitely worth the efforts.

Contacts

Refunds:

Refund Policy
Social

Follow us on our social media channels to stay updated.

© Copyright 2022-23 Team FastAPITutorial