Server

Automating SSL Certificates (Let’s Encrypt) for Dockerized Apps: A Complete Guide for Nepali Developers

Sonam Lama

Administrator

Introduction

Let's Encrypt

Remember the days when setting up SSL certificates meant hours of manual configuration, expensive certificate purchases, and the constant anxiety of forgetting renewal dates? Yeah, those days are thankfully behind us. Today, we’re diving into how you can completely automate SSL certificate management for your Dockerized applications using Let’s Encrypt, and trust me, once you set this up, you’ll wonder how you ever lived without it.

As Nepal’s digital landscape continues to grow and more businesses move online, having proper SSL certificates isn’t just a nice-to-have anymore; it’s absolutely essential. Whether you’re running an e-commerce site in Kathmandu or a SaaS platform serving clients across South Asia, your users expect that green padlock in their browser.

Why Automate SSL Certificates?

Let’s be honest, manual certificate management is a pain. I’ve seen too many websites go down because someone forgot to renew their SSL certificate. It’s embarrassing, bad for business, and completely avoidable in 2025.

Here’s what manual SSL management typically looks like:

  • Purchase certificates annually (expensive!)
  • Manual installation and configuration
  • Setting calendar reminders for renewal
  • Potential downtime during updates
  • Risk of human error

With automation, you get:

  • Free certificates from Let’s Encrypt
  • Automatic renewal every 60-90 days
  • Zero downtime during certificate updates
  • Better security with always up-to-date certificates
  • Peace of mind knowing your sites stay secure

Understanding Let’s Encrypt and Docker

Let’s Encrypt revolutionized SSL certificates by making them free and automatable. They issue certificates that are valid for 90 days, but here’s the genius part: they’re designed to be renewed automatically every 60 days.

When you combine this with Docker, you get a powerful, portable solution that works consistently across development, staging, and production environments. Whether you’re deploying on a VPS in Singapore or a dedicated server in Kathmandu, the setup remains the same.

The Tools We’ll Use

For this setup, we’ll be working with:

ToolPurposeWhy We Choose It
CertbotLet’s Encrypt clientOfficial client, well-maintained
Docker ComposeContainer orchestrationEasy multi-container management
NginxReverse proxy/web serverLightweight, excellent for SSL termination
Cron or Systemd TimerRenewal schedulingBuilt into most Linux systems

Method 1: Using Certbot Container with Nginx

This is probably the most straightforward approach and works great for most scenarios.

Step 1: Project Structure

First, let’s set up our project structure:

ssl-docker-app/
├── docker-compose.yml
├── nginx/
│   ├── nginx.conf
│   └── ssl.conf
├── certbot/
│   └── (certificates will go here)
├── web/
│   └── (your app files)
└── scripts/
    └── renew-certs.sh

Step 2: Docker Compose Configuration

Here’s a solid docker-compose.yml that handles both your app and SSL automation:

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/ssl.conf:/etc/nginx/ssl.conf
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    depends_on:
      - app
    restart: unless-stopped

  app:
    build: ./web
    container_name: your-app
    expose:
      - "3000"
    restart: unless-stopped

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    command: certonly --webroot --webroot-path=/var/www/certbot --email your-email@example.com --agree-tos --no-eff-email -d yourdomain.com -d www.yourdomain.com

Step 3: Nginx Configuration

Your nginx.conf should handle both HTTP and HTTPS traffic:

events {
    worker_connections 1024;
}

http {
    upstream app {
        server app:3000;
    }

    # HTTP server - handles ACME challenges and redirects
    server {
        listen 80;
        server_name yourdomain.com www.yourdomain.com;

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

        location / {
            return 301 https://$server_name$request_uri;
        }
    }

    # HTTPS server
    server {
        listen 443 ssl http2;
        server_name yourdomain.com www.yourdomain.com;

        ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
        
        include /etc/nginx/ssl.conf;

        location / {
            proxy_pass http://app;
            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;
        }
    }
}

Step 4: SSL Security Configuration

Create an ssl.conf file for enhanced security:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Method 2: Using Traefik for Automatic SSL

If you want something even more automated, Traefik is fantastic. It handles SSL certificate generation and renewal automatically based on container labels.

Traefik Docker Compose Example

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik/acme.json:/acme.json
      - ./traefik/traefik.yml:/traefik.yml
    restart: unless-stopped

  app:
    build: ./web
    container_name: your-app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`yourdomain.com`)"
      - "traefik.http.routers.app.tls=true"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"
    restart: unless-stopped

Setting Up Automatic Renewal

The beauty of this setup is in the automation. Here’s how to ensure your certificates renew automatically:

Option 1: Cron Job

Create a script /scripts/renew-certs.sh:

#!/bin/bash

# Navigate to your project directory
cd /path/to/your/ssl-docker-app

# Renew certificates
docker-compose exec certbot certbot renew --quiet

# Reload nginx to use new certificates
docker-compose exec nginx nginx -s reload

# Log the renewal attempt
echo "$(date): SSL renewal attempted" >> /var/log/ssl-renewal.log

Add to crontab (runs twice daily):
0 12 * * * /scripts/renew-certs.sh
0 0 * * * /scripts/renew-certs.sh

Option 2: Systemd Timer

Create /etc/systemd/system/ssl-renewal.service:

[Unit]
Description=SSL Certificate Renewal
After=docker.service

[Service]
Type=oneshot
ExecStart=/scripts/renew-certs.sh
User=your-user

And /etc/systemd/system/ssl-renewal.timer:
[Unit]
Description=Run SSL renewal twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
Persistent=true

[Install]
WantedBy=timers.target

Enable with: sudo systemctl enable ssl-renewal.timer

Common Issues and Troubleshooting

Issue 1: Rate Limiting

Let’s Encrypt has rate limits. During testing, use their staging environment:

docker-compose exec certbot certbot certonly --staging --webroot --webroot-path=/var/www/certbot --email your-email@example.com --agree-tos -d yourdomain.com

Issue 2: DNS Propagation

Make sure your domain points to your server before requesting certificates. You can check with:

dig yourdomain.com

Issue 3: Firewall Issues

Ensure ports 80 and 443 are open:

sudo ufw allow 80
sudo ufw allow 443

Security Best Practices

  1. Keep Docker Images Updated: Regularly update your nginx and certbot images
  2. Monitor Certificate Expiry: Set up monitoring even with automation
  3. Use Strong SSL Configuration: Follow the SSL config we provided above
  4. Regular Backups: Back up your certificate directory
  5. Test Renewals: Regularly test your renewal process

Performance Considerations

For High-Traffic Sites

If you’re running high-traffic applications (which we see more of in Nepal’s growing tech scene), consider:

  • SSL Session Resumption: Already configured in our SSL setup
  • HTTP/2: Enabled in our nginx configuration
  • OCSP Stapling: Reduces SSL handshake time
  • Certificate Caching: Nginx handles this automatically

Resource Usage

This setup is quite lightweight:

  • Nginx container: ~10MB RAM
  • Certbot container: Only runs during renewal
  • Minimal CPU usage outside of renewal periods

Monitoring and Maintenance

Set up basic monitoring to ensure everything’s working:

#!/bin/bash
# Check certificate expiry
EXPIRY=$(openssl x509 -enddate -noout -in /path/to/cert.pem | cut -d= -f2)
EXPIRY_DATE=$(date -d "$EXPIRY" +%s)
CURRENT_DATE=$(date +%s)
DAYS_LEFT=$(((EXPIRY_DATE - CURRENT_DATE) / 86400))

if [ $DAYS_LEFT -lt 30 ]; then
    echo "Certificate expires in $DAYS_LEFT days!" | mail -s "SSL Certificate Warning" admin@yourdomain.com

Conclusion

SSL certificates

Automating SSL certificates for your Dockerized applications isn’t just a nice-to-have – it’s essential for any serious deployment in 2025. With this setup, you get free, automatically renewing certificates that keep your applications secure without any manual intervention.

The initial setup might seem a bit involved, but once it’s running, you can literally forget about SSL certificate management. Your certificates will renew automatically, your users will see that green padlock, and you’ll sleep better knowing your applications are secure.

Whether you’re a startup in Pokhara or an enterprise in Lalitpur, this approach scales beautifully and works consistently across different hosting environments. At Nest Nepal, we’ve seen firsthand how proper SSL automation reduces support tickets and improves overall application reliability.

Remember to test your setup thoroughly in a staging environment first, and don’t hesitate to reach out if you run into any issues. Happy containerizing, and may your SSL certificates always be green!

Need help implementing SSL automation for your Dockerized applications? Our team at Nest Nepal specializes in secure, scalable hosting solutions for businesses across Nepal and beyond. Get in touch to learn how we can help secure your digital presence.

Leave a Reply

Your email address will not be published. Required fields are marked *