Install a Let's Encrypt SSL on a VPS with Certbot

You have a fresh VPS, Nginx is serving your site over plain HTTP, and the browser is showing "Not Secure". The first thing to fix is a Let's Encrypt SSL certificate. Installing a Let's Encrypt SSL on a VPS with Certbot takes about five minutes, and it gives you a free, valid HTTPS certificate with automatic renewal. Here is the exact process on Ubuntu 24.04.
Prerequisites
- A VPS running Ubuntu 24.04 LTS (this works on Debian 12 and 13 with the same commands).
- Root access or a user with sudo privileges.
- A domain name pointing to your VPS IP. Both
example.comandwww.example.comshould resolve via A records. - Ports 80 and 443 open in your firewall. If you use nftables, allow them before you start.
- Nginx already installed and serving your site on port 80.
You can install a Let's Encrypt SSL on a VPS you rent from any provider. The steps are identical whether you run a Linux VPS in Vietnam or elsewhere, because Certbot talks to the Let's Encrypt API over the public internet.
Why use Let's Encrypt instead of a paid certificate
Let's Encrypt issues free certificates valid for 90 days. That short lifetime is a feature: it forces automation, and automation is what keeps certificates from expiring silently. A paid certificate with a one-year validity often expires because nobody tracks the renewal date. With Certbot, renewal happens in the background and you never touch it again.
The only real reason to buy a certificate is if you need extended validation (EV) or organization validation (OV), which display the company name in the browser bar. For a regular website, API, or internal tool, a Domain Validation certificate from Let's Encrypt is cryptographically identical and carries the same padlock.
Step 1 - Install Certbot and the Nginx plugin
Certbot is in the Ubuntu repositories, so installation is one command. The Nginx plugin is what lets Certbot modify your server blocks automatically, instead of making you paste certificate paths by hand.
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
Check the version to confirm the install worked:
certbot --version
Expected output is certbot X.Y.Z. Anything above 2.0 is fine for 2026.
Step 2 - Run Certbot with the Nginx plugin
This single command does everything: it reads your Nginx config, finds the matching server block for your domain, obtains the certificate, and edits the config to enable HTTPS and redirect HTTP to HTTPS.
sudo certbot --nginx -d example.com -d www.example.com
Substitute your actual domain. The -d flags list every domain the certificate must cover. If you change your mind later, you can run Certbot again to add domains, but the current certificate stays valid until renewal.
On first run, Certbot asks for an email address and asks you to accept the terms of service. It also asks whether to redirect HTTP traffic to HTTPS. Answer yes. There is no reason to keep serving plain HTTP in 2026.
Step 3 - Verify the certificate
Certbot prints a success message with the certificate path and expiry date. Verify it yourself with this command:
sudo certbot certificates
Expected output shows your domain, the expiry date, and the paths to the certificate and key. Then test the live site:
curl -I https://example.com
Look for HTTP/2 200 and a location: https:// header if you request the HTTP version. Open the site in a browser and confirm the padlock shows with no warnings.
You can also verify the certificate chain with an external tool:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
Step 4 - Set up automatic renewal
Let's Encrypt certificates last 90 days, so renewal is not optional. Certbot installs a systemd timer that checks twice a day and renews any certificate expiring within 30 days. That means your certificate is effectively renewed every 60 days.
Check that the timer exists and is active:
sudo systemctl status certbot.timer
Expected output: Loaded: loaded and Active: active (waiting). To test the renewal process without actually renewing, use the dry run:
sudo certbot renew --dry-run
If the dry run completes without errors, your setup is done. You never touch it again. If a renewal ever fails, Certbot sends an email to the address you provided and you can inspect the logs at /var/log/letsencrypt/letsencrypt.log.
Step 5 - Add a cron fallback (optional but recommended)
The systemd timer is the modern way, and it works. But if you ever migrate this setup to a system where systemd timers are disabled, or you simply want a redundant path, add a cron job. This is a belt-and-suspenders approach that costs nothing.
sudo crontab -e
Add this line, which attempts renewal twice a day and reloads Nginx only if a renewal actually happened:
0 3,15 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"
Troubleshooting
Certbot says "No matching server block found". Your Nginx config does not have a server_name that matches the domain you passed. Check with nginx -T | grep server_name and fix the server block, then run Certbot again.
Certbot fails with "too many certificates already issued". Let's Encrypt has a rate limit of 50 certificates per registered domain per week. If you hit it, you were testing too aggressively. Wait a few days or use the staging environment for testing: sudo certbot --staging --nginx -d example.com.
Renewal emails include errors with simultaneous_limit. Check the log for the exact error. The most common cause is an expired DNS record or a firewall rule that momentarily blocked port 80. The next scheduled attempt will succeed on its own.
Why port 80 must stay open
Certbot's HTTP-01 challenge works by placing a temporary file at http://example.com/.well-known/acme-challenge/ and asking the Let's Encrypt API to fetch it. If port 80 is closed, the challenge fails even though your site runs fine on HTTPS. This trips up many people who harden their firewall first and install SSL second.
If you run nftables, allow port 80 specifically for the ACME challenge. The HTTP to HTTPS redirect happens after the challenge completes, so the redirect does not break the validation.
What about wildcard certificates
If you need a wildcard for subdomains like *.example.com, the HTTP-01 challenge is not enough. Wildcards require DNS-01 validation, where you prove control of the domain by adding a TXT record. Certbot supports this with the manual plugin or through DNS provider plugins. It is more setup work and not needed for a normal site, so stick with HTTP-01 unless you genuinely have many subdomains.
For a deeper look at automating wildcard certificates, see our guide on automating wildcard SSL with acme.sh and a DNS API.
免费 SSL 证书通过 Certbot 安装并自动续期,无需手动维护。
Free SSL certificates installed with Certbot renew automatically, so you never manage them by hand.
FAQ
How long does a Let's Encrypt certificate last in 2026?
90 days. Certbot automatically renews certificates that expire within 30 days, so your certificate is replaced roughly every 60 days without any action from you.
Is a Let's Encrypt certificate as secure as a paid one?
Yes. Both use the same TLS handshake and provide the same encryption strength. The differences are the validation level and validity period, not the cryptographic security.
Can I use Let's Encrypt on a VPS without Nginx?
Yes. Certbot supports Apache, and the --webroot option works with any web server that can serve a static file. The steps change, but the certificate is identical.
What happens if the automatic renewal fails?
Certbot sends you an email warning. Your certificate keeps working until it expires, then browsers show a security error. Check /var/log/letsencrypt/letsencrypt.log and run sudo certbot renew manually to fix it.
Do I need to open port 443 in the firewall before installing the certificate?
Yes. Port 443 must be open for HTTPS traffic. Port 80 must also stay open because the ACME challenge runs over HTTP. If you close it after the certificate is issued, renewals will fail.
Related articles
- Automate wildcard SSL with acme.sh and DNS API
- Reverse proxy with automatic HTTPS using Caddy
- Enable HTTP/3 and Brotli compression on Nginx
VPS 安装免费 SSL 证书要点
在 VPS 上用 Certbot 安装 Let's Encrypt SSL 证书只需几分钟,且自动续期无需手动维护。关键是保持 80 端口开放,因为 ACME 验证通过 HTTP 进行。安装后可用 certbot certificates 和 curl 验证证书有效性。若需要泛域名证书,则需改用 DNS 验证方式。


