Knowledge
How to install Certbot
#Security
Certbot issues free, trusted SSL certificates from Let's Encrypt and renews them before they expire. Here is how to install it on Ubuntu, issue your first certificate, and keep it renewing on its own.
Published by Mark van Eijk on June 30, 2026 · 4 minute read
- Install Certbot in a virtual environment
- Issue your first certificate
- The HTTP challenge (webroot)
- The DNS challenge
- Point Nginx at the certificate
- Keep it renewing automatically
- Confirm it's working
- Let Rocketeers handle it
A trusted SSL certificate is no longer optional — without one every visitor gets a your connection is not private warning, and browsers refuse to load the page. Certbot is the official client for Let's Encrypt, which hands out free certificates that every browser trusts. The catch is that those certificates only last 90 days, so installing Certbot is really about setting up a process that renews them forever.
We assume you already have a Ubuntu server with Nginx installed and a domain pointed at it.
Install Certbot in a virtual environment
You'll find guides that install Certbot with apt install certbot or through snap. Both work, but the apt package is often stuck on an old release, and snap drags in its own runtime. The cleanest approach — and the one that gives you the DNS plugins you'll want later — is to install Certbot into its own Python virtual environment.
First install Python and the tools to create the environment:
DEBIAN_FRONTEND=noninteractive sudo apt-get install -y openssl python3 python3-venv
Create the virtual environment in /opt/certbot and upgrade pip inside it:
sudo python3 -m venv /opt/certbot
sudo /opt/certbot/bin/pip install --upgrade pip
Now install Certbot itself, along with the DNS provider plugins you might need:
sudo /opt/certbot/bin/pip install --upgrade \
certbot \
certbot-dns-cloudflare \
certbot-dns-digitalocean \
certbot-dns-dnsimple \
certbot-dns-hetzner
Finally, symlink the binary onto your PATH so you can just type certbot:
sudo ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot
Check it worked:
certbot --version
Issue your first certificate
There are two ways to prove to Let's Encrypt that you actually control the domain: the HTTP challenge and the DNS challenge.
The HTTP challenge (webroot)
The HTTP challenge has Let's Encrypt fetch a token from a file Certbot drops in your web root. Create the directory it serves the challenge from, then request the certificate:
sudo mkdir -p /var/www/example.com/.well-known/acme-challenge
sudo certbot certonly \
--webroot --webroot-path /var/www/example.com \
--preferred-challenges http \
--cert-name example.com \
--domains example.com,www.example.com \
--email you@example.com \
--rsa-key-size 4096 \
--agree-tos \
--non-interactive
This needs your domain's DNS already pointing at the server and port 80 reachable.
The DNS challenge
The DNS challenge proves control by creating a temporary TXT record through your DNS provider's API. It's the only option for wildcard certificates (*.example.com) and it works before your domain even points at the server. Store your provider credentials in a file and lock it down:
sudo mkdir -p /root/.secrets
echo "dns_cloudflare_api_token = your-token-here" | sudo tee /root/.secrets/cloudflare.ini
sudo chmod 600 /root/.secrets/cloudflare.ini
Then issue the certificate using the matching plugin:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
--cert-name example.com \
--domains example.com,*.example.com \
--email you@example.com \
--rsa-key-size 4096 \
--agree-tos \
--non-interactive
Either way, your certificate and private key land in /etc/letsencrypt/live/example.com/.
Point Nginx at the certificate
Reference the issued files in your server block, then reload Nginx:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
sudo nginx -t && sudo service nginx reload
Always run nginx -t first — reloading with a broken config can leave you with a 502 Bad Gateway or worse.
Keep it renewing automatically
Let's Encrypt certificates expire after 90 days, so renewal isn't a nice-to-have — it's the whole point. Certbot can renew every certificate it manages with one command:
sudo certbot renew --quiet
Test it without touching anything real first:
sudo certbot renew --dry-run
To make it happen on its own, drop a cron job that renews daily and reloads Nginx afterwards so it picks up the fresh certificate:
echo '0 0 * * * root /usr/local/bin/certbot renew --quiet --post-hook "service nginx reload" > /dev/null 2>&1' \
| sudo tee /etc/cron.d/certbot
Certbot only actually renews a certificate when it's within 30 days of expiry, so running daily is safe and gives you a wide margin if a renewal ever fails. We cover the renewal setup in more depth in renew SSL certificates automatically.
Confirm it's working
Check what Certbot is managing and when each certificate expires:
sudo certbot certificates
You can also verify the live certificate the way a browser sees it — see how to check SSL certificate expiration.
Let Rocketeers handle it
Installing Certbot is the easy part. The work that never ends is the part around it: storing each provider's API credentials securely, picking the right challenge per domain, wiring the renewal hook into Nginx, and noticing when a renewal silently fails three months from now. Rocketeers provisions Certbot with every DNS plugin, issues certificates over HTTP or DNS automatically, and renews them in the background for every site on every server you run — so a certificate never lapses and you never think about it again.
Subscribe to our newsletter
Do you want to receive regular updates with fresh and exclusive content to learn more about web development, hosting, security and performance? Subscribe now!