Running a CyberPanel mail server with acme.sh and Cloudflare

This is the full route to a CyberPanel mail server with valid TLS: Cloudflare DNS, one Let’s Encrypt certificate for mail.example.com issued by acme.sh, Postfix and Dovecot both serving it, and automatic renewal.

Replace example.com with your domain and SERVER_IP with your server’s public IP. Run every command as root.

1. Create the mailbox in CyberPanel

  1. Log in at https://SERVER_IP:8090.
  2. Open Websites → List Websites and confirm example.com is listed (create it if not).
  3. Open Email → Create Email Account, choose the domain, type a username (for example sales) and set a strong password.
  4. Click Create Email. The address is now [email protected].

Menu names can differ slightly between CyberPanel versions.

2. Set up DNS in Cloudflare

In the Cloudflare dashboard open example.com → DNS → Records and add:

TypeNameContentProxy status
AmailSERVER_IPDNS only (grey cloud)
MX@mail.example.com, priority 10DNS only
TXT@v=spf1 mx ~allDNS only
TXT_dmarcv=DMARC1; p=none; rua=mailto:[email protected]DNS only
TXTdefault._domainkeyDKIM value from CyberPanelDNS only

Cloudflare’s proxy only handles web traffic. Keep the mail record on the grey cloud: an orange cloud breaks IMAP, SMTP and certificate issuance.

For the DKIM value, open Email → DKIM Manager in CyberPanel, select the domain, generate the key and copy the TXT value. Use the record name CyberPanel shows (normally default._domainkey).

Also make sure ports 80, 25, 465, 587 and 993 are open, both in CyberPanel’s firewall and at your hosting provider.

Check the records from the server. The first result must equal the last:

dig +short mail.example.com
dig +short MX example.com
dig +short TXT example.com
dig +short TXT _dmarc.example.com
curl -4 ifconfig.me

If dig prints nothing, wait for DNS to update before going further.

3. Install acme.sh

Skip the first command if acme.sh is already installed. Version 3.x defaults to ZeroSSL, so set Let’s Encrypt as the default CA.

curl https://get.acme.sh | sh -s [email protected]
/root/.acme.sh/acme.sh --version
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

4. Issue the certificate

Pick one option. Option B is better for renewals because it never touches the web server.

Option A: standalone (briefly stops OpenLiteSpeed)

Port 80 must be free. On CyberPanel, systemctl stop lsws can leave worker processes running, so stop and verify:

systemctl stop lsws
/usr/local/lsws/bin/lswsctrl stop
sleep 2
ss -tlnp | grep ':80 '        # must print nothing
pkill -9 litespeed            # only if something is still listening

/root/.acme.sh/acme.sh --issue --standalone -d mail.example.com --server letsencrypt \
  --pre-hook  "systemctl stop lsws; /usr/local/lsws/bin/lswsctrl stop; sleep 2" \
  --post-hook "systemctl start lsws"

systemctl start lsws          # always bring the websites back, even if issuing failed

The hooks are saved, so every automatic renewal frees port 80 first and restarts the web server afterwards. Without them, renewal fails because OpenLiteSpeed holds port 80.

Option B: DNS-01 through the Cloudflare API (no downtime)

In Cloudflare create an API token: My Profile → API Tokens → Create Token → Edit zone DNS, limited to the example.com zone. Then:

export CF_Token="your-cloudflare-api-token"
/root/.acme.sh/acme.sh --issue --dns dns_cf -d mail.example.com --server letsencrypt

acme.sh stores the token and reuses it for renewals. Port 80 and the web server are not involved.

5. Install the certificate to a stable path

Don’t point services at acme.sh’s internal folders. Copy the files out and register a reload command, so each renewal is applied automatically:

mkdir -p /etc/ssl/mail.example.com
/root/.acme.sh/acme.sh --install-cert -d mail.example.com --ecc \
  --key-file       /etc/ssl/mail.example.com/privkey.pem \
  --fullchain-file /etc/ssl/mail.example.com/fullchain.pem \
  --reloadcmd      "systemctl reload postfix; systemctl reload dovecot"
chmod 600 /etc/ssl/mail.example.com/privkey.pem
ls -l /etc/ssl/mail.example.com/

6. Point Postfix at it

Use postconf -e rather than editing main.cf by hand. Clear the legacy cert settings, or Postfix ignores smtpd_tls_chain_files. Leave the SNI map empty: a single hostname doesn’t need one.

cp /etc/postfix/main.cf /etc/postfix/main.cf.bak

postconf -e "smtpd_tls_chain_files = /etc/ssl/mail.example.com/privkey.pem, /etc/ssl/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_cert_file ="
postconf -e "smtpd_tls_key_file ="
postconf -e "tls_server_sni_maps ="

postconf smtpd_tls_chain_files smtpd_tls_cert_file smtpd_tls_key_file tls_server_sni_maps
postfix check && systemctl restart postfix
tail -15 /var/log/mail.log

The log should show no malformed BASE64 or legacy … will be ignored warnings. postfix.service showing active (exited) is normal on Ubuntu; the real daemon is postfix@-.

7. Point Dovecot at it

Dovecot has a global default certificate, plus optional local_name blocks per hostname. Set the global default to the mail certificate so every client gets a matching one, whatever name or SNI it sends:

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.bak

grep -n "^ssl_cert\|^ssl_key\|local_name" /etc/dovecot/dovecot.conf
grep -rn "letsencrypt/live/mail" /etc/dovecot /etc/postfix

sed -i 's|^ssl_cert *=.*|ssl_cert = </etc/ssl/mail.example.com/fullchain.pem|; s|^ssl_key *=.*|ssl_key = </etc/ssl/mail.example.com/privkey.pem|' /etc/dovecot/dovecot.conf

doveconf ssl_cert ssl_key
doveconf -n > /dev/null && echo "dovecot config OK"
systemctl restart dovecot
systemctl status dovecot --no-pager | grep Active

The < before each path is Dovecot syntax and tells it to read the file; Postfix paths never have it. If the second grep finds an old local_name block pointing at a missing /etc/letsencrypt/live/mail… folder, delete or comment it out, because Dovecot won’t start while a referenced file is missing.

Optional: if some clients still connect using the bare domain as the server name, add a block that serves the main domain’s own certificate for that name:

cat >> /etc/dovecot/dovecot.conf << 'EOF'

local_name example.com {
  ssl_cert = </etc/letsencrypt/live/example.com/fullchain.pem
  ssl_key = </etc/letsencrypt/live/example.com/privkey.pem
}
EOF

doveconf -n > /dev/null && systemctl restart dovecot

8. Test what each service actually serves

Files on disk only prove the files are valid. Check the live endpoints. Every result should show CN = mail.example.com:

# IMAP
openssl s_client -connect mail.example.com:993 -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates

# IMAP without SNI (what a client sending no hostname receives)
echo | openssl s_client -connect 127.0.0.1:993 -noservername 2>/dev/null | openssl x509 -noout -subject

# SMTP
for p in 25 587; do
  echo "port $p"
  openssl s_client -starttls smtp -connect mail.example.com:$p -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
done
openssl s_client -connect mail.example.com:465 -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates

9. Connect Outlook

  1. In Outlook, open File → Add Account.
  2. Type [email protected], then choose Advanced options → Let me set up my account manually.
  3. Choose IMAP.
  4. Enter these settings:
SettingValue
Incoming (IMAP) servermail.example.com, port 993, SSL/TLS
Outgoing (SMTP) servermail.example.com, port 587 with STARTTLS (or 465 with SSL/TLS)
Usernamethe full email address
Passwordthe one you set in CyberPanel
  • Click Connect.

The port and encryption must pair correctly: 993 with SSL/TLS, or 143 with STARTTLS. Port 143 with SSL/TLS fills the log with Too many invalid commands. Watch a connection attempt with:

tail -f /var/log/mail.log | grep -E "imap-login|auth|TLS"

A Login: user=<[email protected]> … TLS line means it worked. auth failed means a wrong username or password, not a certificate problem.

10. Confirm automatic renewal

crontab -l | grep acme
/root/.acme.sh/acme.sh --list
/root/.acme.sh/acme.sh --info -d mail.example.com --ecc | grep -iE "reload|hook"

You want a daily acme.sh cron entry, a renewal date about 60 days after issue, and Le_ReloadCmd showing the Postfix and Dovecot reload (plus the hooks if you used Option A). Let’s Encrypt certificates last 90 days.

11. Audit every certificate

for c in /etc/letsencrypt/live/*/fullchain.pem /etc/ssl/mail.example.com/fullchain.pem; do
  echo "== $c"
  openssl x509 -in "$c" -noout -subject -enddate -ext subjectAltName 2>/dev/null | grep -E "subject=|notAfter|DNS:"
done

for c in /etc/letsencrypt/live/*/fullchain.pem /etc/ssl/mail.example.com/fullchain.pem; do
  openssl x509 -in "$c" -noout -checkend 2592000 >/dev/null && echo "OK       $c" || echo "EXPIRING $c"
done

The website certificates under /etc/letsencrypt/live/ are renewed by CyberPanel itself; the mail certificate is renewed by acme.sh.

12. Finish

  • Reverse DNS: at your hosting provider, set the PTR record for the server IP to mail.example.com. Receiving servers check it.
  • Test mail: send to and from an outside address, then check tail -30 /var/log/mail.log.
  • Don’t use CyberPanel’s MailServer SSL button afterwards. It can overwrite the paths above; if you do, repeat steps 6 and 7.
  • Clean up: delete the .bak files once everything is stable.

If a service won’t start, these four commands name the cause:

doveconf -n 2>&1 | head
postfix check
journalctl -xeu dovecot.service --no-pager | tail -30
tail -40 /var/log/mail.log

Rank your Website in 1 hour

In today’s search landscape, visibility comes from a combination of traditional SEO and Answer Engine Optimization (AEO) — optimizing not just for Google Search, but also for AI summaries, featured snippets, and conversational search results.

Modern search engines and AI platforms prioritize:

  • Fresh content
  • Clear topical relevance
  • Well-structured answers
  • Pages that satisfy search intent quickly

If you remove technical barriers and publish content that is easy to crawl, easy to understand, and easy to extract answers from, visibility can happen far faster than most people expect.

The Two Pillars: SEO + AEO

To rank quickly, you need to optimize for both systems that now drive discovery:

SEO (Search Engine Optimization)

  • Helps search engines crawl, index, and rank your page
  • Focuses on keywords, technical setup, internal linking, and on-page signals

AEO (Answer Engine Optimization)

  • Helps AI systems understand and extract answers from your content
  • Focuses on clarity, structure, entities, and direct responses to search intent

When combined, SEO gets your page seen, and AEO helps it get chosen.

One-Hour SEO Checklist

1. Optimise Page Titles & Meta Descriptions – 10–15 mins

  • Add a clear, descriptive title for each page
  • Include your main keyword naturally
  • Write compelling meta descriptions to encourage clicks

2. Improve Headings & Content Structure – 10–15 mins

  • Ensure one H1 per page summarises the topic
  • Use H2/H3 headings to organise content
  • Sprinkle relevant keywords naturally throughout the text

3. Internal Linking – 5–10 mins

  • Link related pages and blog posts to each other
  • Use descriptive anchor text, avoid “click here”
  • Boosts navigation for users and search engine crawling

4. Optimise Images – 10 mins

  • Compress large images for faster loading
  • Add descriptive alt text including relevant keywords
  • Enhances accessibility and page speed

5. Check Mobile-Friendliness – 5 mins

  • Ensure text is readable without zooming
  • Buttons and links are easy to tap
  • Page loads quickly on mobile devices

6. Submit or Update Sitemap – 5 mins

  • Submit or refresh your sitemap in Google Search Console
  • Helps search engines index your site faster
  • Makes your updates visible in search results sooner

How We Help Brands Achieve Faster Search Visibility

If you’re looking to apply these strategies with expert guidance, explore our related services:

  • SEO & AEO Services – Technical, on-page, and content-led SEO built for long-term visibility, and conversational search
  • Web Development – SEO-ready websites designed for speed, structure, and conversions

Looking for tailored advice?
Get in touch with our team to discuss your goals and discover opportunities for faster, measurable growth.

What Does a Digital Marketing Agency Actually Do?

Running a business today is challenging enough — figuring out how to stand out online shouldn’t be another headache. That’s where a digital marketing agency comes in. Think of us as your partner in growth, helping your business reach the right people, at the right time, with the right message.

Here’s how we help:

  • We Plan Your Strategy: We take the time to understand your business, your audience, and your competitors, then create a clear roadmap to help you grow online.
  • We Make You Visible: Through SEO and content optimisation, we make sure your website can be found when customers are looking for what you offer.
  • We Manage Your Social Presence: From Facebook and Instagram to LinkedIn and TikTok, we create campaigns that engage your audience and bring real results.
  • We Create Content That Connects: Blogs, videos, infographics, emails — all designed to attract, inform, and build trust with your customers.
  • We Optimise Ads for ROI: Paid campaigns are carefully managed so your budget goes further and reaches the right people at the right time.
  • We Track & Improve Everything: Using analytics, we measure performance, make improvements, and show you exactly what’s working.
  • We Make Your Website Work Harder: Fast, mobile-friendly, and user-focused design ensures visitors stay longer, engage more, and convert.

At the end of the day, a digital marketing agency isn’t just about clicks and likes — it’s about helping your business grow sustainably. We take care of the technical, creative, and strategic side of things so you can focus on what you do best: running your business.

Ready to see your business grow online? Let’s start the conversation.