Home / blog / Securing Your Full-Stack App with HTTPS Using Certbot and Docker
Securing Your Full-Stack App with HTTPS Using Certbot and Docker

Securing Your Full-Stack App with HTTPS Using Certbot and Docker

Featured

Securing Your Full-Stack App with HTTPS Using Certbot and Docker

a

admin

Author

30 min read
51 Views
July 09, 2025

Learn how to generate and configure free SSL certificates for your full-stack application using Certbot with Docker. This step-by-step guide covers HTTPS setup for Nginx, explains port requirements, domain configuration, and certificate renewal.

In Part 1 of this deployment series, we set up Nginx as a reverse proxy for your full-stack app (NestJS + Next.js) using Docker. If you haven’t read it yet, check it out here: Understanding Nginx for Fullstack Apps.

Now, it’s time to make your app secure with HTTPS, the standard for modern web applications.

Let’s walk through how to generate and apply an SSL certificate using Let’s Encrypt + Certbot, all inside Docker.


📌 What You Need Before Starting

Before you can set up HTTPS, make sure the following are ready:

  • ✅ You have a domain name (like example.com) purchased from a domain registrar.
  • ✅ Your domain has an A record pointing to your server’s public IP address.
  • ✅ Port 80 (HTTP) is open on your server and not blocked by a firewall.
  • ✅ Docker and Docker Compose are installed on your server.
Example: If your domain is example.com and your server's IP is 192.0.2.1, your A record should be: example.com → 192.0.2.1


🔒 Step 1: Run Certbot in a Temporary Container

Certbot needs to verify your domain via HTTP challenge on port 80. We’ll run Certbot as a one-time container to generate the certificate.

Create a directory to store certificates:

mkdir -p ./certbot/conf
mkdir -p ./certbot/www

Then run Certbot:

docker run --rm \
  -v $(pwd)/certbot/www:/var/www/certbot \
  -v $(pwd)/certbot/conf:/etc/letsencrypt \
  certbot/certbot certonly \
  --webroot -w /var/www/certbot \
  -d example.com -d www.example.com
Replace example.com with your domain. Certbot will create SSL certificates inside ./certbot/conf.

🔍 Why --webroot?

Certbot will place a file inside /var/www/certbot/.well-known/... which Let’s Encrypt must be able to reach via HTTP on port 80. This proves you own the domain.


⚙️ Step 2: Add SSL Configuration to Nginx

Now that you have your certificate files, update your Nginx config to support HTTPS.

Update your nginx/default.conf to:

server {
    listen 80;
    server_name example.com www.example.com;
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location /api/ {
        proxy_pass http://backend:5000/;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
    }

    location / {
        proxy_pass http://frontend:3000/;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
    }
}
Don’t forget to replace example.com with your domain.
Need help understanding this configuration? Review Part 1 of the series: Understanding Nginx for Fullstack Apps


🐳 Step 3: Mount Certbot Volumes in Docker Compose

Update your docker-compose.yml:

  nginx:
    image: nginx:alpine
    container_name: nginx_proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    depends_on:
      - frontend
      - backend

Then restart services:

docker compose up -d --build

Now your site is accessible via https://example.com 🎉


🔁 Step 4: Auto-Renew SSL Certificates

Let’s Encrypt certificates expire every 90 days. Set up a cron job to renew them.

Create a shell script called renew_cert.sh:

#!/bin/bash

docker run --rm \
  -v $(pwd)/certbot/www:/var/www/certbot \
  -v $(pwd)/certbot/conf:/etc/letsencrypt \
  certbot/certbot renew

docker exec nginx_proxy nginx -s reload

Make it executable:

chmod +x renew_cert.sh

Schedule it using crontab:

crontab -e

Add this line to run daily at midnight:

0 0 * * * /path/to/your/renew_cert.sh >> /var/log/cert_renew.log 2>&1
This ensures your certificates never expire.


🧠 Summary

In this post, you learned:

  • How to get free SSL certificates using Certbot
  • How to configure Nginx for HTTPS inside Docker
  • How to mount volumes and reload Nginx
  • How to auto-renew your SSL certificates with a cron job

👉 Your app is now encrypted and production-ready!

📘 Still learning Docker? Read this first: Dockerize NestJS – Dockerfile & Compose

📘 Want to review the Nginx setup? Read Part 1 here: Understanding Nginx for Fullstack Apps

Need help? Reach out at kaisalhusrom.com or message me on LinkedIn.


share this post

Link Copied