Or pay $25-$200 per year to your hosting provider. Up to you!
You know the thing where you navigate to a url, and you get one of those “gaahhh return to safety!” warnings on a dark gray screen? It’s usually do to a missing or expired SSL certificate. An SSL certificate allows your site(s) to be delivered over HTTPS, and is a crucial, baseline security feature. It encrypts all traffic between your hosted site and its visitors. It’s also proof that your site is actually your site, and not a spoof/man-in-the-middle attack lying in wait to snatch up all your highly confidential state secrets. Bottom line, you need SSL certificates. Hosting providers know this, and bet on you being spooked enough to fork over tons of loot every year for them to manage them for you. But if you use Certbot to manage SSL certificates, the control is in your hands. And the money is too. So save the money and use Certbot.
Preparation Steps to Use Certbot
As a word of caution to anyone reading this tutorial, I’m assuming you have already purchased a domain from your hosting provider, and added the www subdomain, and made any necessary DNS changes to link your domain to your VPS. Likewise, I recommend securing certificates before doing something like this, so make the certs happen before anything else.
Anyway, let’s get started by installing Certbot and the Certbot Nginx plugin, and creating a root folder for your site.
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
mkdir -p /var/www/yourdomain.here
echo "<h1>Some Temp headline for Your Site.</h1>" > /var/www/yourdomain.com/index.html
Next, if you haven’t already, we’re going to create an Nginx config file and point to the snakeoil certs temporarily, in order to pass the nginx -t
config test.
vim /etc/nginx/sites-available/yourdomain.here
Paste the following (note the snakeoil temp certs):
# Redirect HTTP to HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://yourdomain.com$request_uri;
}
# HTTPS Redirect for www -> naked domain (TEMP: using snakeoil certs, will be auto-replaced by certbot)
server {
listen 443 ssl http2;
server_name www.yourdomain.com;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
return 301 https://yourdomain.com$request_uri;
}
# Main HTTPS server block (TEMP: using snakeoil certs)
server {
listen 443 ssl http2;
server_name yourdomain.com;
root /var/www/yourdomain.com;
index index.html;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
try_files $uri $uri/ =404;
}
}
Run the commands below to generate a symlink, confirm correct syntax, and reboot Nginx:
ln -s /etc/nginx/sites-available/yourdomain.here /etc/nginx/sites-enabled/yourdomain.here
nginx -t
systemctl reload nginx
Just so you know, if you go to your url after this step, it still won’t load correctly. That’s due to the snakeoil temp certs in the nginx config file. We’ll run Certbot now to generate the real certificates.
Run Certbot to Receive SSL Certificates
The command we’ll run next creates a shared, multidomain (aka SAN) certificate for domains & subdomains indicated in the command. While it’s possible to create a wildcard certificate as well, this tutorial won’t be covering that method. It’s a pain in the neck—you can’t use the Nginx plugin, it requires DNS verification, and you have to set TXT records in your DNS manually or via API. So peace to all that noise. Let’s run Certbot like a regular person instead:
certbot --nginx -d yourdomain.com -d www.yourdomain.com
When prompted, give a valid email, agree to the terms, and choose to direct all http traffic to https. If you want to skip the prompts altogether, structure the command like this:
certbot --nginx --non-interactive --redirect --agree-tos --email "my@email.address" -d "yourdomain.here" -d "www.yourdomain.here"
Confirm a Successful Install
First, let’s check the certificate exists with the following command:
certbot certificates
You should see your certificate block print to the terminal. Under “Domains:” you should see your domain and your www subdomain. The “Expiry Date:” section will display the expiration date of the certificate.
Now let’s confirm that the Nginx config file points to the newly-created certificates:
cat /etc/nginx/sites-enabled/yourdomain.here | grep Certbot
You should see the certificate paths changed from the snakeoil temp paths to the path of the real certificates, like /etc/letsencrypt/live/yourdomain.here/fullchain.pem
and /etc/letsencrypt/live/yourdomain.here/privkey.pem
.
Finally, let’s reload Nginx again:
systemctl reload nginx
If you navigate to your domain url, with or without the “www” prefix, you’ll be routed to the index.html
page we created at the beginning of the tutorial, over https. And if you click on the little slider-looking button on the left side of your browser’s url input area, you should now see a “Connection is secure” notification. Congrats! You’re all done.
What about Certificate Renewal?
Well yeah, that’s a fair question. Certbot adds a timer to systemctl, so let’s check that out.
systemctl list-timers | grep certbot
You’ll see something along the lines of:
Wed 2025-07-30 06:44:53 UTC 3h 58min Tue 2025-07-29 23:44:00 UTC 3h 2min ago certbot.timer certbot.service
That timer is running twice a day, every 12 hours, with a randomizer delay baked in as well. It checks the validity of the certificate, and if it’s time to renew, it runs certbot renew
for you. You’re welcome.
And, by default, Certbot will renew a certificate 30 days before expiration date. That’s solid padding, so I recommend leaving that default setting alone.
Conclusion
Implementing certbot to manage SSL certificates is easy. In my opinion, the money saved, and the auto-renewal functionality alone are worth the effort.