How to Install & Auto-Renew Let’s Encrypt SSL on CyberPanel

Recently my two WHMCS dashboards were stuck due to expired SSL certificates. I check

crontab -e

There was

# 0 0 * * 4 /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/renew.py >/dev/null 2>&1

Unfortunately, it was unable to renew SSL. So I came up with a separate solution that fixed that issue.

So, in the guide, we have installed Let’s Encrypt SSL instead of Zero SSL for multiple domains and subdomains and set up a cron job to check the status of SSL and auto-renewal.

Now let’s get started.

1. Requirements

Before you begin, make sure you have the following:

Requirement Details
Operating System Ubuntu 20.04 / 22.04 / 24.04
Web Server OpenLiteSpeed (via CyberPanel)
Control Panel CyberPanel
Root SSH Access Required
Port 80 & 443 Must be open/accessible
DNS Records All domains must point to your server IP

2. Install Certbot

Certbot is the tool that issues and renews Let’s Encrypt SSL certificates. Install it using Snap for the latest version:

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

# Verify installation
certbot --version

You should see output like certbot 5.x.x

3. Open Required Ports

Make sure your firewall allows traffic on ports 80, 443, and 8090 (CyberPanel):

ufw allow 80
ufw allow 443
ufw allow 8090
ufw reload

4. Check DNS Before Issuing SSL

All domains must point to your server’s IP address. Run these checks first:

# Get your server's public IP
curl ifconfig.me

# Check each domain resolves to the same IP
dig +short yourdomain.com
dig +short www.yourdomain.com
dig +short subdomain.yourdomain.com
dig +short cp.yourdomain.com

Cloudflare Users: If your domain uses Cloudflare, make sure to set the DNS record to “DNS Only” (grey cloud), not “Proxied” (orange cloud). Certbot needs direct access to your server on port 80 to verify domain ownership.

5. Issue SSL Certificates

We use standalone mode, which temporarily uses port 80 to verify your domain. This means OpenLiteSpeed must be stopped briefly during the process.

1 Stop OpenLiteSpeed

systemctl stop lsws
fuser -k 80/tcp
sleep 2

# Confirm port 80 is free (should return nothing)
lsof -i :80

2 Issue Certificate for Main Domain

certbot certonly --standalone \
  -d yourdomain.com \
  -d www.yourdomain.com \
  --email your@email.com \
  --agree-tos \
  --no-eff-email

3 Issue a certificate for a subdomain (e.g.dash.yourdomain.com)

certbot certonly --standalone \
  -d dash.yourdomain.com \
  --email your@email.com \
  --agree-tos \
  --no-eff-email

4 Issue Certificate for CyberPanel Subdomain (e.g. cp.yourdomain.com)

certbot certonly --standalone \
  -d cp.yourdomain.com \
  --email your@email.com \
  --agree-tos \
  --no-eff-email

5 Start OpenLiteSpeed Again

systemctl start lsws

6 Verify All Certificates Were Issued

certbot certificates
You should see all your domains listed with their expiry dates (valid for 90 days).

Tip: If you see “live directory exists” errors, the config files may be corrupted. See the Troubleshooting section below.

6. Apply SSL in CyberPanel for Websites

After issuing certificates, apply them to each website through the CyberPanel dashboard:

  1. Log into CyberPanel at https://yourserver:8090
  2. Go to Websites → List Websites
  3. Click on your domain → SSL → Manage SSL
  4. Paste the certificate and private key contents (see commands below)

Get the certificate contents with:

# Certificate (fullchain)
cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem

# Private Key
cat /etc/letsencrypt/live/yourdomain.com/privkey.pem

Repeat this for each domain/subdomain.

7. Apply SSL to CyberPanel Admin Panel Itself

The CyberPanel admin panel (port 8090) uses its own certificate files. First, find the correct file paths:

find /usr/local/CyberCP -name "cert.pem" 2>/dev/null
find /usr/local/CyberCP -name "key.pem" 2>/dev/null

Then copy the certificate:

cp /etc/letsencrypt/live/cp.yourdomain.com/fullchain.pem \
   /usr/local/CyberCP/cert.pem

cp /etc/letsencrypt/live/cp.yourdomain.com/privkey.pem \
   /usr/local/CyberCP/key.pem

# Restart CyberPanel service
systemctl restart lscpd
Visit https://cp.yourdomain.com:8090 — the SSL warning should be gone.

8. Troubleshooting Common Errors

Error: “Could not bind TCP port 80”

OpenLiteSpeed is still running. Force-kill it:

systemctl stop lsws
pkill -f litespeed
fuser -k 80/tcp
lsof -i :80  # Must return nothing

Error: “live directory exists”

Old/broken certificate files exist. Clean and reissue:

# Remove broken config, live, and archive directories
rm /etc/letsencrypt/renewal/yourdomain.com.conf
rm -rf /etc/letsencrypt/live/yourdomain.com
rm -rf /etc/letsencrypt/archive/yourdomain.com

# Then reissue the certificate
certbot certonly --standalone -d yourdomain.com \
  --email your@email.com --agree-tos --no-eff-email

Error: “renewal config file is missing a required file reference”

Same fix as above, remove the broken .conf file from /etc/letsencrypt/renewal/ and reissue.

Error: “ZeroSSL requires –eab-kid and –eab-hmac-key”

You’re using the ZeroSSL ACME server, which requires API credentials. The simplest fix is to remove the --server flag and use Let’s Encrypt instead (default), which requires no extra credentials.

Error: “Webroot 404 / ACME challenge failed”

OpenLiteSpeed is blocking the .well-known directory. Use standalone mode instead (stop OLS first as shown above).

Error Fix
Port 80 in use fuser -k 80/tcp then stop lsws
Live directory exists Delete renewal config + live + archive dirs
ZeroSSL EAB required Remove --server flag to use Let’s Encrypt
Webroot 404 Switch to --standalone mode
DNS not resolving Update A record, disable Cloudflare proxy
CyberPanel cert path wrong Use find to locate correct cert.pem path

9. Set Up Auto-Renewal with Pre/Post Hooks

Since standalone mode needs port 80 free, we use pre and post hooks that automatically stop OpenLiteSpeed before renewal and restart it after. This means SSL auto-renews without any manual intervention.

1 Create Hook Directories

mkdir -p /etc/letsencrypt/renewal-hooks/pre
mkdir -p /etc/letsencrypt/renewal-hooks/post
mkdir -p /etc/letsencrypt/renewal-hooks/deploy

2 Create Pre-Hook (Stops OLS Before Renewal)

nano /etc/letsencrypt/renewal-hooks/pre/stop-lsws.sh

Paste the following content:

#!/bin/bash
systemctl stop lsws
sleep 3
fuser -k 80/tcp
sleep 2

3 Create Post-Hook (Starts OLS After Renewal)

nano /etc/letsencrypt/renewal-hooks/post/start-lsws.sh

Paste the following content:

#!/bin/bash

# Start OpenLiteSpeed
systemctl start lsws

# Copy renewed cert to CyberPanel panel
cp /etc/letsencrypt/live/cp.yourdomain.com/fullchain.pem \
   /usr/local/CyberCP/cert.pem

cp /etc/letsencrypt/live/cp.yourdomain.com/privkey.pem \
   /usr/local/CyberCP/key.pem

# Restart CyberPanel
systemctl restart lscpd

echo "SSL renewed and services restarted at $(date)" >> /var/log/ssl-renew.log

4 Make Both Hooks Executable

chmod +x /etc/letsencrypt/renewal-hooks/pre/stop-lsws.sh
chmod +x /etc/letsencrypt/renewal-hooks/post/start-lsws.sh

5 Verify Renewal Config Uses Standalone

cat /etc/letsencrypt/renewal/yourdomain.com.conf

Check that it contains authenticator = standalone. If not, fix it:

sed -i 's/authenticator = .*/authenticator = standalone/' \
  /etc/letsencrypt/renewal/yourdomain.com.conf

10. Add Cron Job for Daily Auto-Renewal

crontab -e

Add this line at the bottom:

# Auto-renew SSL daily at 3 AM
0 3 * * * certbot renew --quiet >> /var/log/ssl-renew.log 2>&1

💡 Note: Certbot only actually renews certificates when they are within 30 days of expiry. Running the cron daily is safe, it simply checks and skips if renewal is not needed yet.

Disable CyberPanel’s Built-in SSL Renewal (Prevent Conflicts)

CyberPanel has its own SSL renewal cron that may conflict. Disable it:

crontab -e

Find and comment out this line by adding # at the start:

# 0 0 * * 4 /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/renew.py >/dev/null 2>&1

11. Verify Everything Works

Test Dry Run (Simulates Renewal Without Actually Renewing)

certbot renew --dry-run
You should see: “Congratulations, all simulated renewals succeeded”

Check SSL on All Domains

for DOMAIN in yourdomain.com subdomain.yourdomain.com cp.yourdomain.com; do
  echo "=== $DOMAIN ==="
  echo | openssl s_client -connect $DOMAIN:443 2>/dev/null \
    | openssl x509 -noout -issuer -dates
  echo ""
done

Check Renewal Logs

cat /var/log/ssl-renew.log

12. Final Summary

Here is a complete overview of what we set up:

Component Details Status
Certbot installed via Snap (latest version)
SSL for main domain yourdomain.com + www
SSL for subdomain dash.yourdomain.com
SSL for CyberPanel panel cp.yourdomain.com:8090
Pre-hook Auto-stops OLS before renewal
Post-hook Auto-starts OLS + copies panel cert
Cron job Daily at 3 AM
CyberPanel conflict Built-in renew.py disabled
Downtime on renewal ~5–10 seconds every 3 months

🎉 Congratulations! Your SSL certificates are now installed and will auto-renew every 90 days without any manual action needed. Your websites, subdomains, and CyberPanel admin panel are all secured with HTTPS.

FAQ

Can I use this guide for multiple servers?

Yes. Repeat the entire process on each VPS/server. Each server needs its own Certbot installation, certificates, hooks, and cron job. Domains must point to the correct server’s IP.

What if Let’s Encrypt rate-limits me?

Let’s Encrypt allows 5 duplicate certificates per week per domain. If you hit the limit, either wait a week or switch to ZeroSSL by registering at app.zerossl.com and using the --server https://acme.zerossl.com/v2/DV90 flag along with your EAB credentials.

Does OLS go down during renewal?

Yes, briefly around 5–10 seconds. This happens only when the certificate is actually renewed (once every ~3 months). The pre/post hooks handle this automatically.

How do I check when my SSL expires?

certbot certificates

What email should I use for Certbot?

Use an email on your own domain (e.g. admin@yourdomain.com) for professionalism. Make sure it’s a working inbox so you receive expiry warnings from Let’s Encrypt.

Leave a Comment

Problogguru uses cookies to make its website easier to use. Learn more.