Type something to search...
How to set up free SSL with Let's Encrypt?

How to set up free SSL with Let's Encrypt?

To set up free SSL with Let's Encrypt, you point your domain's DNS at your server, install an ACME client such as Certbot, and run a single command that proves you control the domain, obtains a certificate, and configures Nginx or Apache to use it. Certbot then renews the certificate automatically before it expires. On shared hosting, it's even simpler: most control panels have a one-click Let's Encrypt or AutoSSL option that does all of this for you.

Let's Encrypt is a free, automated certificate authority run by the nonprofit Internet Security Research Group (ISRG). Its certificates are trusted by all modern browsers and are exactly as secure as paid domain-validated certificates. This guide covers how Let's Encrypt works, how to install certificates on your own Ubuntu or Debian server with Nginx or Apache, how to get wildcard certificates, how renewal works, and how to fix the most common errors.

How Let's Encrypt Works

Let's Encrypt uses a protocol called ACME (Automatic Certificate Management Environment). An ACME client on your server talks to Let's Encrypt and proves that you control the domain before a certificate is issued. There are two main ways to prove control:

  1. HTTP-01 challenge: Let's Encrypt asks your client to place a specific file at http://yourdomain.com/.well-known/acme-challenge/<token>. If Let's Encrypt can fetch it over port 80, you've proven control. This is the most common method.
  2. DNS-01 challenge: Your client creates a TXT record at _acme-challenge.yourdomain.com. This works even if your server isn't publicly reachable, and it's required for wildcard certificates.

There's also a TLS-ALPN-01 challenge on port 443, used mainly by some specialised clients.

A few important facts:

  • Certificates are domain-validated (DV): They confirm you control the domain, not who your organisation is. That's all a typical website needs.
  • Short lifetimes: Certificates are valid for 90 days today, and Let's Encrypt has announced plans to move to even shorter lifetimes over the next few years. That's why automatic renewal is essential.
  • Rate limits apply: There are limits on how many certificates you can request for the same domain in a given period. Use the staging environment when testing.

Before You Start

Check the following before running any commands:

  • DNS points to your server: Your domain's A record (and AAAA record, if you use IPv6) must point to the server where you're installing the certificate. Check with dig +short example.com or an online DNS lookup tool.
  • Port 80 is reachable: For HTTP validation, port 80 must be open in your firewall and your cloud provider's security group. You'll want port 443 open for HTTPS too.
  • A working web server: Nginx or Apache should already be serving your site over HTTP, with a server block or virtual host that uses your domain name.
  • Root or sudo access: You'll need administrative access to install packages and edit web server configuration.

With UFW on Ubuntu, open the necessary ports like this (make sure SSH is already allowed before enabling UFW):

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Option 1: One-Click SSL on Shared Hosting

If you're on shared or managed hosting, you usually don't need the command line at all.

  • cPanel: Open Security > SSL/TLS Status. Most cPanel servers use AutoSSL, which issues free certificates from Let's Encrypt or Sectigo automatically. Click Run AutoSSL if a domain is missing a certificate.
  • Plesk: Open Websites & Domains, choose your domain, and click SSL/TLS Certificates, then use the Let's Encrypt extension to issue a certificate.
  • Managed WordPress hosts: Most issue Let's Encrypt certificates automatically when you add a domain. Look for an "SSL" or "HTTPS" section in your dashboard.

Once the certificate is installed, enable your host's "Force HTTPS" option if it has one, so visitors are always redirected to the secure version of your site.

Option 2: Install Certbot on Ubuntu or Debian

Certbot, developed by the Electronic Frontier Foundation, is the most popular ACME client. The Certbot team recommends installing it via snap on Ubuntu, which keeps it up to date automatically:

sudo apt update
sudo apt install snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

On Debian, or if you prefer not to use snap, you can install Certbot from the distribution packages instead:

sudo apt install certbot python3-certbot-nginx

For Apache, install python3-certbot-apache instead of the Nginx plugin. On RHEL, Rocky Linux, and AlmaLinux, Certbot is available from the EPEL repository (sudo dnf install epel-release, then sudo dnf install certbot python3-certbot-nginx).

Remove any old certbot-auto or distribution Certbot packages before switching to the snap version, to avoid two copies conflicting.

Get a Certificate for Nginx

Make sure your Nginx server block includes your domain in server_name. For example, /etc/nginx/sites-available/example.com:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}

Test and reload Nginx, then run Certbot:

sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d example.com -d www.example.com

Certbot will ask for an email address (for important account and security notices), ask you to accept the terms of service, and then:

  1. Validate your domains using the HTTP-01 challenge.
  2. Download the certificate to /etc/letsencrypt/live/example.com/.
  3. Update your Nginx config to listen on 443 with the new certificate.
  4. Add an HTTP to HTTPS redirect.

After it finishes, your server block will contain lines like these:

listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

Visit https://example.com in your browser to confirm the padlock appears.

Get a Certificate for Apache

On Apache, make sure your virtual host has a ServerName and any ServerAlias entries, then run:

sudo apachectl configtest
sudo certbot --apache -d example.com -d www.example.com

Certbot creates a new SSL virtual host file (often named example.com-le-ssl.conf), enables mod_ssl if needed, and adds a redirect from HTTP to HTTPS. The resulting virtual host looks roughly like this:

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public

    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Certificate-Only Mode (Webroot)

If you'd rather manage your web server configuration yourself, or you use a server Certbot doesn't have a plugin for, use certonly with the webroot method. Certbot will just place challenge files in your web root and fetch the certificate, without touching your config:

sudo certbot certonly --webroot -w /var/www/example.com/public -d example.com -d www.example.com

Then add the ssl_certificate and ssl_certificate_key lines (or Apache's equivalents) to your configuration manually, pointing at /etc/letsencrypt/live/example.com/.

If your application intercepts all requests (for example, a framework router), make sure requests to /.well-known/acme-challenge/ are served as plain files. In Nginx:

location ^~ /.well-known/acme-challenge/ {
    root /var/www/example.com/public;
    default_type "text/plain";
    try_files $uri =404;
}

Wildcard Certificates With DNS Validation

A wildcard certificate such as *.example.com covers every subdomain at one level. Let's Encrypt only issues wildcards using the DNS-01 challenge, because you need to prove control over the whole domain.

The manual method works for a quick test, but it can't renew automatically:

sudo certbot certonly --manual --preferred-challenges dns -d example.com -d "*.example.com"

Certbot will ask you to create a TXT record at _acme-challenge.example.com. Add it at your DNS provider, wait a minute for it to propagate, then continue.

For automatic renewals, use a DNS plugin that talks to your provider's API. Certbot has plugins for Cloudflare, DigitalOcean, Route 53, Google Cloud DNS, and others. With the Cloudflare plugin installed via snap:

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

Create a credentials file with a Cloudflare API token that only has Zone > DNS > Edit permission for the relevant zone:

sudo mkdir -p /root/.secrets
sudo nano /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your-scoped-api-token

Lock down its permissions, then request the certificate:

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"

Always use a scoped API token rather than a global API key, so a leaked file can only edit DNS for that one zone.

Automatic Renewal

Certbot installs a systemd timer (or a cron job, depending on how it was installed) that checks twice a day and renews any certificate within 30 days of expiry. Check that it exists:

systemctl list-timers | grep certbot

Test the renewal process without actually renewing:

sudo certbot renew --dry-run

If the dry run succeeds, renewals will work. Certbot's Nginx and Apache plugins reload the web server automatically after renewal. With certonly, add a deploy hook so your server picks up the new certificate:

sudo certbot renew --deploy-hook "systemctl reload nginx"

To make the hook permanent for all renewals, drop a script into the deploy hooks directory:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh > /dev/null <<'EOF'
#!/bin/sh
systemctl reload nginx
EOF
sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Let's Encrypt no longer sends expiry reminder emails, so don't rely on email to warn you of a failed renewal. An external uptime or certificate monitoring service that checks your expiry dates is a better safety net.

Managing Your Certificates

A few useful Certbot commands:

# List all certificates and their expiry dates
sudo certbot certificates

# Add a domain to an existing certificate
sudo certbot --nginx --cert-name example.com -d example.com -d www.example.com -d blog.example.com

# Revoke and delete a certificate you no longer need
sudo certbot revoke --cert-name old.example.com
sudo certbot delete --cert-name old.example.com

Never edit or move files inside /etc/letsencrypt/live/ by hand. They're symlinks managed by Certbot, and changing them can break renewals.

Strengthening Your HTTPS Setup

Getting a certificate is the first step. A few extras make your HTTPS setup stronger:

  • Redirect all HTTP traffic to HTTPS: Certbot can do this for you. Confirm that http:// URLs redirect with a 301.
  • Use modern TLS versions: Allow TLS 1.2 and 1.3 only. Certbot's included options files already use sensible settings.
  • Enable HSTS once everything works: HTTP Strict Transport Security tells browsers to always use HTTPS for your domain. Add it only after you're confident every subdomain supports HTTPS.
  • Fix mixed content: If your site loads images or scripts over http://, browsers will warn visitors or block those resources. Update URLs in your content and theme.
  • Test your configuration: Qualys SSL Labs' free server test grades your setup and flags weak settings.

For WordPress, update the site address after enabling HTTPS under Settings > General so both WordPress Address (URL) and Site Address (URL) start with https://.

Other ACME Clients

Certbot isn't the only option. Depending on your setup, you might prefer:

  • acme.sh: A lightweight shell-script client with support for many DNS providers.
  • Caddy: A web server that obtains and renews certificates automatically with no extra configuration.
  • Traefik: A reverse proxy popular with Docker setups, with built-in ACME support.
  • lego: A Go-based ACME client and library.
  • win-acme: A popular client for Windows servers running IIS.

They all use the same Let's Encrypt service. Choose whichever fits your stack best.

Troubleshooting Common Errors

Connection refused or timeout during validation: Let's Encrypt couldn't reach port 80. Check your firewall, your cloud provider's security group, and that your web server is running.

DNS problem: NXDOMAIN or wrong IP: Your domain doesn't resolve, or resolves to a different server. Check A and AAAA records. A stale AAAA record pointing to an old IPv6 address is a surprisingly common cause, because Let's Encrypt prefers IPv6 when it's available.

Unauthorized, 404 on the challenge file: The challenge file isn't being served. This usually means a redirect, rewrite rule, or application router is intercepting /.well-known/acme-challenge/. Add the location block shown earlier.

CAA record prevents issuance: If your domain has a CAA DNS record, it must allow letsencrypt.org. Add a record like example.com. CAA 0 issue "letsencrypt.org" or remove restrictive entries.

Too many certificates already issued: You've hit a rate limit, often from repeated testing. Wait for the limit to reset, and use --staging (or --test-cert) while testing:

sudo certbot --nginx --staging -d example.com

Renewal fails after changing servers: If you moved your site, the old server may still hold the certificate and renewal configuration. Issue a fresh certificate on the new server and remove the old one.


FAQ: Let's Encrypt SSL

Yes. Let's Encrypt is run by a nonprofit and issues certificates at no cost. Some hosts charge for installing or managing certificates, but the certificates themselves are free.

Yes, in terms of encryption. A Let's Encrypt certificate uses the same standards as paid domain-validated certificates. Paid certificates can offer organisation validation, warranties, or support, but they don't encrypt traffic any better.

Currently 90 days, and Let's Encrypt plans to shorten lifetimes further over time. That's why automatic renewal matters. Certbot renews certificates when they're within 30 days of expiry.

Yes, but only with the DNS-01 challenge. Use a Certbot DNS plugin for your provider, such as Cloudflare or Route 53, so the wildcard can renew automatically.

Usually because Let's Encrypt can't reach your server on port 80. Check your firewall, your cloud provider's security rules, and that your domain's A and AAAA records point to the right server.

Run sudo certbot renew --dry-run. If it completes without errors, renewal is set up correctly. You can also run systemctl list-timers to see when the Certbot timer runs next.

Yes. Update both URLs under Settings > General to use https://, then check for mixed content, such as images or scripts still loaded over http://, and fix any you find.


Conclusion

Let's Encrypt has made HTTPS free and automatic for everyone. On shared hosting, it's usually a single click in your control panel. On your own server, installing Certbot and running one command for Nginx or Apache gets you a trusted certificate, a working HTTPS configuration, and automatic renewals in a few minutes.

Once your certificate is in place, confirm renewal with a dry run, redirect all traffic to HTTPS, clean up any mixed content, and consider certificate monitoring so an expiry never takes you by surprise. With those basics in place, your visitors get an encrypted connection every time, and you never have to think about buying or manually renewing a certificate again.

Tags :
Share :

Related Posts

What are the best WordPress security plugins?

What are the best WordPress security plugins?

The best WordPress security plugins for most sites are Wordfence, Sucuri Security, Solid Security, MalCare, All-In-One Security (AIOS), Patchstack, a

Dive Deeper
What are the most common website security threats?

What are the most common website security threats?

The most common website security threats are vulnerable or outdated software, weak and stolen passwords, malware infections, injection attacks like S

Dive Deeper
How does GDPR affect website security?

How does GDPR affect website security?

GDPR affects website security by turning it from a good habit into a legal obligation. If your website collects personal data from people in the EU (

Dive Deeper