TR/EN
Blog

How to Install a Free SSL Certificate with Let's Encrypt (Certbot) on Nginx and Apache

Published: · 12 min read

Today, when you open a site without HTTPS, the browser shows a "Not secure" warning in the address bar, visitors get nervous about entering info into forms, and Google uses HTTPS as a ranking signal. In short, an SSL certificate is no longer a luxury, it's a must. The good news is you don't have to pay for it: Let's Encrypt is a non-profit certificate authority that issues free SSL certificates, and Certbot is the tool that gets the certificate, installs it on your web server with a few commands and renews it automatically. In this post we walk through free SSL setup with Let's Encrypt for Nginx and Apache, step by step.

Let's Encrypt or a Paid SSL?

CriteriaLet's EncryptPaid SSL
PriceFreeYearly fee
Validation typeDV only (domain validation)DV, OV (organization) and EV
Validity90 days (gradually dropping to 45)Max 200 days (since March 2026), and shrinking too
AutomationFully automatic with ACMEDepends on the provider
Wildcard (*.domain)Yes (with DNS validation)Yes
Encryption strengthSameSame
Warranty / insuranceNoUsually yes
When?Sites, APIs, panels, most use casesWhen organization details must appear on the certificate

There's no difference in encryption; the visitor's connection is protected just as strongly. What paid certificates add is organization validation and extra services. For most websites and apps, Let's Encrypt is more than enough.

Prerequisites

  • Your domain's A (and AAAA, if any) record must point to your server's IP.
  • Ports 80 and 443 must be open (UFW and the provider firewall).
  • A working site config for this domain in Nginx or Apache.
  • root or sudo access. Examples are on Ubuntu 24.04.

Step 1: Install Certbot

Certbot officially recommends the snap package; this way you always have the latest version and the auto-renewal timer is set up automatically:

sudo apt remove -y certbot            # remove the old apt version if installed
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
certbot --version

Step 2: Get and Install the Certificate

One command gets the certificate and updates the web server config:

# Nginx
sudo certbot --nginx -d example.com -d www.example.com

# Apache
sudo certbot --apache -d example.com -d www.example.com

On the first run Certbot asks for an email address and for you to accept the terms. Then it verifies that you control the domain, gets the certificate, adds the SSL lines to the site config and sets up the HTTP to HTTPS redirect. The certificate files live under /etc/letsencrypt/live/example.com/: fullchain.pem is the certificate chain and privkey.pem is the private key. Never share the private key.

Step 3: Automatic Renewal

Let's Encrypt certificates are short-lived, so renewal has to be automatic. The snap install sets this up for you with a systemd timer; Certbot checks twice a day and renews certificates close to expiry. To check:

systemctl list-timers | grep certbot     # is the auto-renewal timer installed?
sudo certbot renew --dry-run             # test renewal without getting a real certificate

# for services other than Nginx/Apache: reload script after renewal
printf '#!/bin/sh\nsystemctl reload postfix\n' | \
  sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-postfix.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-postfix.sh

For certificates obtained with --nginx or --apache, Certbot reloads the web server itself after renewal. If other services like Postfix or Dovecot use the same certificate, add a deploy hook like above, otherwise the service keeps running with the old certificate.

Don't use fixed-date cron jobs. Hand-written cron jobs like "renew every 60 days" will let certificates expire as lifetimes get shorter. Certbot's own renew logic decides based on the remaining lifetime, so it isn't affected by these changes.

Validation Methods

Before issuing a certificate, Let's Encrypt has to verify that you control the domain. There are a few ways to do this:

MethodHow it worksPortWildcardWhen?
HTTP-01 (--nginx / --apache)Certbot temporarily configures the web server80NoEasiest path for most sites
WebrootPuts the validation file in the site's root directory80NoIf you manage the web server config yourself
StandaloneCertbot runs its own temporary web server80 (must be free)NoIf there's no web server on the machine
DNS-01A temporary TXT record is added to DNSNot neededYesWildcards, internal servers, or when 80 is closed
# webroot: just get the certificate without touching the running web server
sudo certbot certonly --webroot -w /var/www/example -d example.com -d www.example.com

# standalone: if port 80 is free, Certbot runs its own temporary server
sudo certbot certonly --standalone -d example.com

Wildcard Certificate (DNS-01)

A certificate covering all subdomains like *.example.com needs DNS validation. If your DNS is on Cloudflare, you can automate it with Certbot's plugin:

sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare

# use an API token that can only edit DNS
sudo mkdir -p /root/.secrets
echo 'dns_cloudflare_api_token = CLOUDFLARE_TOKEN' | sudo tee /root/.secrets/cloudflare.ini
sudo chmod 600 /root/.secrets/cloudflare.ini

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

There are similar plugins for other DNS providers. Always set the API token file's permissions to 600; anyone who can read it can change your DNS records.

Managing Certificates

sudo certbot certificates                                   # list certificates and expiry dates
sudo certbot --nginx --expand -d example.com -d www.example.com -d api.example.com   # add a domain to an existing certificate
sudo certbot delete --cert-name example.com                    # delete a certificate

What's Changing at Let's Encrypt in 2026?

  • Shorter certificate lifetimes: Default certificates are currently 90 days. Since May 2026 there's an optional 45-day profile; on February 10, 2027 the default drops to 64 days and on February 16, 2028 to 45 days. If auto-renewal works properly, nothing changes for you.
  • Short-lived and IP certificates: Since January 2026, 6-day short-lived certificates and certificates for IP addresses instead of domain names are available as opt-in options.
  • No more expiry emails: Let's Encrypt stopped sending expiry warning emails in 2025. If renewal breaks somehow you might not notice, so we recommend tracking certificate expiry with an uptime/monitoring tool.

Test Your Setup

You can check that the certificate is installed correctly and see its expiry date from the command line:

openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -dates

For a more detailed review, use free test tools like SSL Labs. Make sure only TLS 1.2 and 1.3 are enabled on your server. The HSTS header improves security, but since browsers remember it for a long time, don't add includeSubDomains and preload until you're sure all your subdomains work over HTTPS.

Common Errors

Error / SymptomLikely causeFix
DNS problem: NXDOMAINThe domain has no DNS record or it hasn't propagated yetCheck the A record and wait for propagation
Timeout during connectPort 80 is closedOpen 80 in UFW and the provider firewall
unauthorized / 404Wrong webroot path or another server answersCheck the webroot path and that the A record points to the right server
Redirect loop (behind Cloudflare)Cloudflare SSL mode is "Flexible"After installing the certificate on the server, switch to "Full (strict)"
too many certificates already issuedWeekly limit reached (5 duplicates per week for the same names)Wait a week; use --dry-run when testing
Old certificate still shows after renewalThe service wasn't reloadedAdd a deploy hook or reload the service

With the Cloudflare proxy (orange cloud) on, HTTP validation usually works fine; if you run into trouble, use the DNS-01 method.

SSL on VECDC Servers

VECDC virtual servers come with NVMe disks and a 1 Gbps connection from $6/month, are ready in about 5 minutes with automated setup, and you can choose the location when ordering; as soon as the server is up you can move your site to HTTPS with the steps in this post. If you use a platform like Coolify on the Developer VDS that comes with Docker, SSL is already automatic; details in our what is Coolify post. If you prefer a control panel, see our CyberPanel, aaPanel and HestiaCP post, and for an SSL example behind an Nginx reverse proxy, check our Ollama on a VPS post.

Frequently Asked Questions

Is Let's Encrypt really free and secure?

Yes. Let's Encrypt is a non-profit certificate authority trusted by all browsers. Its certificates provide the same encryption strength as paid ones; the only difference is the validation type (domain validation only) and extra services like warranties.

How often are Let's Encrypt certificates renewed?

Default certificates are currently valid for 90 days, and the lifetime gradually drops to 45 days by 2028. Since Certbot renews automatically based on the remaining lifetime, you don't need to do anything by hand; you can test that auto-renewal works with certbot renew --dry-run.

Can I get a wildcard certificate with Let's Encrypt?

Yes. Wildcard certificates like *.domain.com require DNS-01 validation. With Certbot plugins for DNS providers like Cloudflare, this can be fully automated.

Do I need SSL on the server if I use Cloudflare?

Yes, it's recommended. Cloudflare encrypts the connection between the visitor and itself; to also encrypt the connection between Cloudflare and your server, install a valid certificate on the server and set the SSL mode to Full (strict).

In Short

Free SSL setup with Let's Encrypt and Certbot takes a few minutes: install Certbot with snap, get the certificate with certbot --nginx or --apache, and test auto-renewal with renew --dry-run. Use DNS validation for wildcards, don't write fixed-date cron jobs, and since expiry emails don't come anymore, track certificate expiry with a monitoring tool. Theres no need to pay for basic SSL anymore. If you get stuck, drop us a message.

Your Virtual Server, Ready in 5 Minutes

NVMe virtual servers with dedicated resources start at $6/month.

See Packages →