DEV Community

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

Posted on

4 1

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

I ❤️ building dashboards for my customers

I ❤️ building dashboards for my customers

Said nobody, ever. Embeddable's dashboard toolkit is built to save dev time. It loads fast, looks native and doesn't suck like an embedded BI tool.

Get early access

Top comments (1)

Collapse
 
bladearya profile image
Amit Kumar Rout

Very Helpful Article

Developer-first embedded dashboards

Developer-first embedded dashboards

Embed in minutes, load in milliseconds, extend infinitely. Import any chart, connect to any database, embed anywhere. Scale elegantly, monitor effortlessly, CI/CD & version control.

Get early access

👋 Kindness is contagious

Dive into this thoughtful piece, beloved in the supportive DEV Community. Coders of every background are invited to share and elevate our collective know-how.

A sincere "thank you" can brighten someone's day—leave your appreciation below!

On DEV, sharing knowledge smooths our journey and tightens our community bonds. Enjoyed this? A quick thank you to the author is hugely appreciated.

Okay