DEV Community

Cover image for How to Automatically Renew Let’s Encrypt SSL Certs with Certbot on Ubuntu 🔐
Dima Zaichenko
Dima Zaichenko

Posted on

How to Automatically Renew Let’s Encrypt SSL Certs with Certbot on Ubuntu 🔐

“I’m not a DevOps engineer, but I play one in production.”

Tired of manually renewing SSL certs every 90 days like it’s a Tamagotchi from 2005?

This guide is for you: developers who want HTTPS without DevOps nightmares.


🤔 Why Certbot?

Because:

  • It's free (thanks, Let's Encrypt).
  • It works (thanks, Certbot).
  • It renews itself (mostly).
  • And most importantly: you can get back to writing code instead of deciphering NGINX logs at 3AM.

🧪 Step 1 — Install Certbot

sudo apt update
sudo apt install certbot
Enter fullscreen mode Exit fullscreen mode

Boom. That’s it. The easy part.


📜 Step 2 — Get your first SSL cert

sudo certbot certonly --standalone \
  -d yourdomain.com -d www.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

Check what you got:

sudo certbot certificates
Enter fullscreen mode Exit fullscreen mode

🧠 Heads-up: --standalone runs a temporary HTTP server on port 80.

If you're using Nginx or Docker, stop them first or use --webroot.

Image description

More information about plugins can be found in the official documentation.


🔁 Step 3 — Let it renew itself (like magic)

Certbot installs a systemd timer by default:

systemctl list-timers | grep certbot
Enter fullscreen mode Exit fullscreen mode

You can see output like:

Mon 2025-03-10 03:12:00 UTC  10h left  Mon 2025-03-09 03:12:00 UTC  certbot.timer  certbot.service
Enter fullscreen mode Exit fullscreen mode

Test if it works:

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

You should see something like:

Certbot dry-run was successful.
Enter fullscreen mode Exit fullscreen mode

📅 Certbot renews certificates when they’re 30 days from expiry.

Latest update logs:

journalctl -u certbot.service --no-pager --since "2 days ago"
Enter fullscreen mode Exit fullscreen mode

🧓 Prefer old-school cron? No problem

Disable the timer:

sudo systemctl stop certbot.timer
sudo systemctl disable certbot.timer
Enter fullscreen mode Exit fullscreen mode

Then add this to your crontab (sudo crontab -e):

0 0 1 * * /usr/bin/certbot renew --standalone --quiet
Enter fullscreen mode Exit fullscreen mode

To find out the exact path to certbot, use:

which certbot
Enter fullscreen mode Exit fullscreen mode

Because nothing says “legacy and proud” like a 1AM cron job.


🧙 Use Hooks Like a Wizard

Automatically stop/start your services when certs are renewed.

Open your renewal config:

sudo nano /etc/letsencrypt/renewal/yourdomain.com.conf
Enter fullscreen mode Exit fullscreen mode

Add:

pre_hook = systemctl stop your-app.service
deploy_hook = systemctl reload your-app.service
post_hook = systemctl start your-app.service
Enter fullscreen mode Exit fullscreen mode

Perfect when you want Certbot to renew certs and do the dishes.


🛠 Bonus: Bash Script of Champions

This is what you actually wanted — a copy-pasteable script to handle everything:

#!/bin/bash
APP_PATH="/home/you/yourapp"
DOMAIN="yourdomain.com"

FULL_CHAIN="/etc/letsencrypt/live/${DOMAIN}/fullchain.pem"
PRIVATE_KEY="/etc/letsencrypt/live/${DOMAIN}/privkey.pem"

CRT_DEST="${APP_PATH}/ssl/${DOMAIN}.crt"
KEY_DEST="${APP_PATH}/ssl/${DOMAIN}.key"

echo "[$(date)] Stopping the service..."
systemctl stop your-app.service

echo "Renewing certs silently..."
/usr/bin/certbot renew --standalone --quiet

echo "Copying certs like a pro..."
cp -f "$FULL_CHAIN" "$CRT_DEST"
cp -f "$PRIVATE_KEY" "$KEY_DEST"
chmod 644 "$CRT_DEST" "$KEY_DEST"

echo "Starting the service again..."
systemctl start your-app.service

echo "🎉 All done. Go grab a coffee."
Enter fullscreen mode Exit fullscreen mode

Crontab it like a boss:

0 0 1 * * /bin/bash /home/you/scripts/renew-ssl.sh >> /var/log/certbot.log 2>&1
Enter fullscreen mode Exit fullscreen mode

🧠 Final Thoughts

SSL shouldn't be harder than writing JavaScript regex.

Certbot + Let’s Encrypt is one of those rare tools that actually “just works” — if you let it.

✅ Works with cron

✅ Supports systemd

✅ Has deploy hooks

✅ Costs $0

Just test it every now and then. Let automation do its thing.

And for the love of uptime — back up your certs.


✨ Bonus Links

Top comments (1)

Collapse
 
bladearya profile image
Amit Kumar Rout

Very Helpful Article