HTTPS Setup Guide with Let's Encrypt (Certbot + Nginx + Docker)
-
Jason Yang - 25 Mar, 2026
- Views —
What is Certbot and Why Use It with Nginx?
When deploying web services, enabling HTTPS is no longer optional — it’s a baseline requirement for security, privacy, and even SEO.
To enable HTTPS, you need an SSL/TLS certificate. Traditionally, obtaining and renewing certificates was a manual and often costly process. Today, this is solved by Let’s Encrypt, a free and automated certificate authority.
What is Certbot?
Certbot is an official client tool provided by Let’s Encrypt that:
- Automatically issues SSL certificates
- Handles domain ownership verification
- Renews certificates before expiration (every 90 days)
In short, Certbot removes almost all manual work involved in managing HTTPS certificates.
Why Use Certbot with Nginx?
Nginx is one of the most widely used web servers and reverse proxies in production systems.
Certbot integrates very well with Nginx and is commonly used in the following ways:
- Issue certificates for Nginx-hosted domains
- Automatically configure HTTPS (in non-Docker environments)
- Work alongside containerized setups (like Docker Compose)
1. Prerequisites
Before issuing a certificate, make sure:
- Your domain is pointing to your server IP (DNS or DDNS)
- Port 80 is open (required for domain validation)
2. Stop Nginx (Avoid Port Conflict)
Certbot standalone mode uses port 80.
docker compose stop nginx
3. Issue SSL Certificate
docker run --rm -p 80:80 \
-v /etc/letsencrypt:/etc/letsencrypt \
certbot/certbot certonly \
--standalone \
--domain your-domain.example.com \
--email your@email.com \
--agree-tos \
--non-interactive
Why standalone mode?
- Runs a temporary web server for validation
- No need to modify existing Nginx config
The trade-off is right there in step 2: standalone binds port 80 itself, so you have to stop Nginx during issuance and renewal — a few seconds of downtime. If you can’t afford that, use the webroot plugin instead: it drops the challenge files into a directory Nginx already serves (--webroot -w /var/www/html), so Nginx keeps running and you never take the site down. Standalone is simpler; webroot is the zero-downtime option.
Wildcards need a different challenge
Both methods above use the HTTP-01 challenge, which can’t issue a wildcard certificate (*.example.com). For that you need the DNS-01 challenge — proving domain ownership by creating a TXT record — which means a Certbot DNS plugin for your provider (Cloudflare, Route 53, etc.) rather than the port-80 dance.
4. Certificate Location
/etc/letsencrypt/live/your-domain.example.com/fullchain.pem
/etc/letsencrypt/live/your-domain.example.com/privkey.pem
5. Restart Nginx
docker compose up -d nginx
6. Renew Certificate (Every 90 Days)
docker compose stop nginx
docker run --rm -p 80:80 \
-v /etc/letsencrypt:/etc/letsencrypt \
certbot/certbot renew
docker compose start nginx
7. Automate Renewal (Cron)
Edit root cron:
sudo crontab -e
0 3 1 * * docker stop nginx && \
docker run --rm -p 80:80 \
-v /etc/letsencrypt:/etc/letsencrypt \
certbot/certbot renew --quiet && \
docker compose -f /home/your-path/docker-compose.yml up -d nginx
⚠️ Important Notes
1. Rate Limits
Let’s Encrypt has strict rate limits.
Avoid frequent re-issuance.
2. Use Staging for Testing
--staging
🚀 Result
With this setup:
- Certificates are issued automatically
- Renewed every 90 days
- Fully Docker-based (no host dependency)
If this feels like a lot of moving parts — stop Nginx, issue, restart, cron the renewal — that’s because it is. A reverse proxy like Caddy folds all of it (issuance, renewal, and the HTTP→HTTPS redirect) into a two-line config with no cron job at all. Certbot + Nginx is the right choice when you’re already committed to Nginx; Caddy is worth a look when you’re starting fresh.