Skip to content

SSL/TLS Certificates

CorePanel issues and renews SSL/TLS certificates automatically, with no manual ACME client to run. Understanding how it issues them explains an important operational detail: some hostnames (like mail.example.com) are secured differently from the website, and a domain whose DNS lives on an external provider (Cloudflare, Route 53, etc.) needs specific handling for its mail certificate.

This page is for server administrators. It covers the issuance model, the delegation requirement, why web and mail behave differently, and the concrete setups that produce a valid certificate on mail.<domain>.

CorePanel’s certificate manager (part of corepanel-sys) obtains certificates from an ACME CA (Let’s Encrypt by default) using the DNS-01 challenge only. It never uses HTTP-01.

For each domain it requests a single wildcard certificate covering the wildcard plus the apex:

*.example.com
example.com

That one certificate covers every direct hostname of the domain — www, mail, webmail, ftp, and so on — from a single issuance. There is no separate certificate per service hostname.

PropertyValue
Challenge typeDNS-01 (only)
CALet’s Encrypt (ACME endpoint is configurable)
Coverage*.example.com + example.com
DNS providerLocal PowerDNS (via its HTTP API)
Store path/var/lib/cp-sys/ssl/certs/<domain>/{fullchain,privkey}.pem
RenewalAutomatic (background worker; renews before expiry)

Because issuance is DNS-01 through the server’s own PowerDNS, CorePanel can only complete the challenge when it is authoritative for the domain — that is, when the domain’s nameservers are delegated to this server.

Before every DNS-01 order, the certificate manager runs an authority pre-check: it resolves the domain’s NS records through public resolvers (Cloudflare, Google, Quad9) and confirms they point back to this server’s configured public IP addresses.

Subdomains inherit the delegation of the zone that holds them. api.example.com almost never carries NS records of its own — it lives inside its parent’s zone — so the check reads the zone name from the SOA the resolver returns and verifies the nameservers of that zone. A subdomain of a zone delegated here counts as delegated; a subdomain of a zone that lives elsewhere does not. The walk stops before a bare TLD, so an unregistered domain is never mistaken for a delegated one.

When a domain is not delegated to the server, CorePanel does not fire a failing ACME order (that would burn the CA’s failed-validation rate limit). Instead it parks the domain and re-checks delegation every 30 minutes, waiting indefinitely without consuming the retry budget. The moment you point the domain’s NS at the server, the certificate is issued on the next check.

The IPs used for this check are the server’s own public IPs. They are configured automatically during initial setupcorepanel system init detects the main public IP (plus any additional IPs) and records them in the certificate manager. If the server’s public IP later changes, re-run initial setup so the delegation check compares against the correct addresses: a nameserver that resolves to an IP not in this list is treated as not pointing here.

CorePanel uses two independent issuance paths with different triggers. Knowing which one fires — and when — explains why a freshly added site is already on HTTPS while its mail hostname may not be.

The wildcard (DNS-01) — issued proactively when the domain is added

Section titled “The wildcard (DNS-01) — issued proactively when the domain is added”

The certificate manager does not wait for a visit. The moment a domain is provisioned (account creation, or adding a domain to an account) it queues an issuance attempt in the background:

  • Delegated → it publishes the _acme-challenge TXT record in the server’s PowerDNS, waits for it to propagate, and obtains the *.example.com + apex wildcard — typically within seconds to a couple of minutes of adding the domain, with no traffic required. As soon as it lands, every hostname (www, mail, webmail, ftp) is covered and Dovecot’s per-domain SNI block is generated.
  • Not delegated → no ACME order is fired. The domain is parked and re-checked every 30 minutes; issuance happens automatically on the first re-check after you point the domain’s NS at the server.

There is no visit-triggered issuance for the wildcard and no manual “issue now” step: once the domain is delegated to the server, the next 30-minute delegation re-check obtains the certificate on its own.

While a domain is in that parked state the panel’s SSL view shows it as having no certificates yet — an empty list, not an error. That is the honest reading: nothing has been issued, and nothing is wrong that waiting or delegating will not fix. The same is true for the few minutes between adding a delegated domain and the first issuance landing.

The web certificate (TLS-ALPN-01) — issued on the first HTTPS request

Section titled “The web certificate (TLS-ALPN-01) — issued on the first HTTPS request”

Independently, CoreHttpd obtains the website’s certificate on demand, at the first HTTPS (port 443) handshake for a hostname it serves:

  1. A browser opens the first https:// connection to the host.
  2. CoreHttpd asks the CA for a certificate and answers the CA’s acme-tls/1 validation probe inside that same handshake (TLS-ALPN-01).
  3. The original handshake then completes with the just-issued certificate — the first HTTPS hit is what triggers issuance.

That first handshake blocks for up to ~30 s while issuing. If it takes longer, the connection falls back to the default certificate and issuance continues in the background, so a retry a few seconds later succeeds. Issuance is gated to hostnames CoreHttpd actually serves (a site must exist) — the abuse guard against ACME orders for arbitrary names.

This path:

  • fires on the first HTTPS request only — a plain HTTP (port 80) visit does not trigger it;
  • covers the web hostname that was hit, nothing else — it never produces a certificate for mail.* or an FTP hostname;
  • needs port 443 for the host to terminate on this server (an external proxy in front breaks it — see the caution in the next section).

For a delegated domain the wildcard usually issues before anyone visits, so the site serves its real certificate from the first hit and mail is covered by the same wildcard. For a non-delegated domain the wildcard never issues, so the website is carried entirely by the on-demand path (first HTTPS visit) while mail and FTP have no automatic certificate — the gap the next sections address.

certmanager (DNS-01) has preference: when it later issues a wildcard, that certificate takes over and owns renewal. Renewals are automatic on both paths — certmanager renews before expiry on its schedule, and CoreHttpd proactively renews its cached web certificates in the background (re-armed on startup, so a certificate issued in a previous run is renewed on schedule rather than only when traffic next arrives).

Two layers: the website vs. everything else

Section titled “Two layers: the website vs. everything else”

The delegation gate matters differently for the website than for mail/FTP, because the website has an on-demand fallback and mail does not.

The origin web server, CoreHttpd, obtains the website’s certificate on demand using TLS-ALPN-01 on port 443. TLS-ALPN-01 is solved inside the TLS handshake itself — it needs no DNS record — so the website gets a valid certificate even when the domain is not delegated to the server, as long as the A record points at the server.

Mail (Postfix/Dovecot), FTP and other service daemons do not have an on-demand challenge. They can only present a certificate that already exists in the store — which means a DNS-01-issued certificate. There is no TLS-ALPN-01 fallback on the mail or FTP ports.

Both Dovecot and Postfix select their certificate by SNI, from the same set of names:

  • For each domain that has a certificate in /var/lib/cp-sys/ssl/certs/, the names that certificate is valid for are published — a local_name block in /etc/dovecot/conf.d/99-corepanel-ssl.conf for Dovecot, an entry in the tls_server_sni_maps table at /etc/postfix/corepanel_sni.map for Postfix. A *.example.com wildcard is expanded into mail., webmail., imap., smtp., pop. and pop3., because neither daemon matches wildcards in an SNI table.
  • Connections with no matching SNI fall back to the default host certificate — the server’s own hostname certificate at /var/lib/corehttpd/hostcert/, obtained by CoreHttpd and kept on that path by corepanel-sys. That certificate is self-signed until the server’s hostname itself obtains an ACME certificate, or until one of the domain certificates on disk is found to cover the hostname; it is replaced within seconds of either.

The practical consequence: mail.example.com presents a valid certificate only when a certificate for example.com exists in the store — i.e. only after DNS-01 has succeeded, i.e. only when the domain is delegated to the server. If it is not, the mail daemons fall back to the server’s host certificate, whose name does not match mail.example.com.

Seeing the host certificate: SSL certificates → Automatic

Section titled “Seeing the host certificate: SSL certificates → Automatic”

Because it belongs to no domain, the host certificate is not in the per-domain table — that table is built from certmanager’s DNS-01 store, and the host certificate comes from CoreHttpd’s own on-demand store. It has its own card at the top of SSL certificates → Automatic, above the domain selector:

  • Trusted — a real certificate from a public CA. Nothing to do.
  • Self-signed — CoreHttpd’s bootstrap certificate. It is written so the mail services have something rather than falling back to the distribution’s default, and it is replaced automatically once the panel’s own hostname has been served over HTTPS and its certificate issued. Every mail client connecting to this server sees a warning until then, whatever the individual domains’ certificates say.
  • Expired, Missing, Unreadable — the file on /var/lib/corehttpd/hostcert/fullchain.pem needs looking at.

The SSL certificates page, Automatic tab. Above the domain selector sits a card headed "This server&#x27;s own certificate", explaining that it is presented by the mail services on ports 25, 465, 587, 993 and 995 for every account on the server and belongs to no domain. Its verdict reads "Self-signed: mail clients show a warning. The certificate names server.example.com and nothing vouches for it", followed by the note that this is the bootstrap certificate and is replaced once the panel hostname has been served over HTTPS, then the path /var/lib/corehttpd/hostcert/fullchain.pem and its expiry. Below it the usual domain selector is still empty.

The card names the ports the certificate is served on (25, 465, 587, 993, 995) and the path it lives on, because the answer to “why is my mail untrusted” is usually one file.

If the card says self-signed on a server whose panel loads over HTTPS without a browser warning, the promotion has not happened: visit the panel over https:// under its own hostname, which is what triggers issuance, and the certificate is picked up within five minutes.

Worked example: external DNS (Cloudflare) with only A + MX

Section titled “Worked example: external DNS (Cloudflare) with only A + MX”

This is the common case: a customer keeps their DNS at Cloudflare and simply adds an A record and an MX record pointing at the CorePanel server. Here is exactly what happens:

EndpointResultWhy
example.com / www (web)✅ Valid certificateCoreHttpd issues it on demand via TLS-ALPN-01 on port 443 (requires DNS-only, not proxied)
mail.example.com (IMAP/POP3/SMTP)⚠️ Certificate name mismatchNo DNS-01 cert in the store (domain not delegated), so mail falls back to the server host certificate
ftp.example.com (FTPS)⚠️ Certificate name mismatchSame reason as mail

So a Cloudflare domain with only A + MX works for the website but produces an untrusted / name-mismatch warning in mail clients that connect to mail.example.com. The website is fine; the mail hostname is the one that needs attention.

Choose one of the following to get a valid certificate on the mail (and FTP) hostname:

1. Delegate the domain’s DNS to CorePanel (full automation)

Section titled “1. Delegate the domain’s DNS to CorePanel (full automation)”

Point the domain’s NS records at the server. Once the delegation is visible in public DNS, the next 30-minute delegation check issues the wildcard, the per-domain Dovecot local_name block is generated, and mail.example.com presents a valid certificate automatically. This is the intended, zero-maintenance path.

2. Keep external DNS, but use the server’s canonical hostname for mail

Section titled “2. Keep external DNS, but use the server’s canonical hostname for mail”

If the customer must keep DNS at Cloudflare (or another external provider), configure mail clients to use the server’s own hostname (for example mail.yourhosting.tld) as the incoming/outgoing server, instead of mail.customerdomain.tld. The server hostname always has a matching, valid certificate (the host certificate), so clients connect without warnings. This is the standard “one mail hostname for all accounts” model and needs no per-domain delegation.

3. Migration preserves an existing certificate

Section titled “3. Migration preserves an existing certificate”

When you migrate an account from cPanel, a still-valid certificate found in the archive is imported verbatim (sys.ImportCertificate) and tracked for renewal, so the site keeps serving TLS through the cutover without a re-issue.

Using your own certificate (commercial SSL)

Section titled “Using your own certificate (commercial SSL)”

Everything above is about the certificate CorePanel issues and renews for free. Sometimes that is not the certificate you have to serve: an organisation buys an OV or EV certificate for the identity information it carries, a corporate policy names a specific CA, or a customer arrives with a certificate they have already paid for.

For those cases, upload the certificate from the panel or with corepanel ssl upload. Installing one is available on Pro and Business; inspecting and removing certificates works on every edition, so a lapsed licence never traps you with a certificate you cannot take off.

Uploaded certificates are reachable from three places:

  • Accounts → the account → SSL. Under the per-domain status table, listing the certificates installed on the hosts that account owns — its domains, aliases, addons and subdomains. This is the everyday route: a customer sends you their certificate and you are already in their workspace. Super-administrators only: installing a certificate hands the server a private key and decides what every visitor of that site sees, so an administrator without the super flag does not see this block.
  • The customer’s own panel → SSL. The same section, seen by the account holder. They install their own certificates on their own domains without going through you — see below.
  • SSL certificates → the Uploaded tab. Every uploaded certificate on the server, including hosts that belong to no account — the panel’s own hostname, mail, webmail. Those are only reachable here, and so is this tab: it describes every tenant on the machine, so it is super-administrators only.

Either way the button is Install certificate. From the account it starts on that account’s primary domain, and you can change it to any of its addon domains or subdomains; from a row’s Replace, the host is fixed to that certificate’s.

The person who bought the certificate is usually the customer, and they are the one who will have to buy the next one. So the client panel offers the same Install certificate button, on their own domains only, and it is on by default.

That default is the opposite of the one customer-started backups get, and the difference is what the two settings cost. A backup writes an archive to this server’s disk, outside anybody’s quota, so you have to agree to the space first. Installing a certificate spends nothing: it is a file the customer already paid a CA for, on a name they already own, validated on the way in exactly as yours is. Shipping it off would mean every OV certificate on the box arrives as a support ticket instead.

Turn it off in Server → Settings → Client panel if you would rather handle certificates yourself. What that switch does and does not do:

  • It stops installing. It does not stop reading or removing — a customer who already installed a certificate must always be able to take it off, or flipping the switch would leave them holding one they can neither renew nor remove.
  • It never applies to you. It is your switch, not a rule about the server.
  • It cannot reach beyond the account. A customer may only name a host their own account owns, and one hostname is excluded even from the account that owns the zone under it: the panel’s own hostname. That name carries the server’s identity — the HELO Postfix announces, the certificate the panel itself is reached on — so whoever holds its certificate decides how the server presents itself to every other account. It stays yours.

Four rules cover the whole feature, and the second is the one worth remembering:

  1. Your certificate wins. It is stored separately from the automatic one and is served ahead of it for that host, from the next connection on. No restart, no reload.
  2. A renewal never overwrites it. Nothing automatic writes to the store your certificate lives in, so there is no setting to protect and no race to lose. Meanwhile the automatic certificate underneath keeps renewing itself, which is what makes the next point work.
  3. Expiry degrades — as long as there is something to degrade to. A bought certificate does not renew itself. If yours lapses, the web server falls back at the next handshake to the automatic certificate, which has been renewing itself underneath all along, and the site keeps serving valid TLS under a different issuer. That safety net needs an automatic certificate to exist. See the warning below.
  4. Removing it is instant and safe. Deleting your certificate returns the host to the automatic one immediately. It is the way back if an installed certificate turns out to be wrong.

Your certificate authority will ask for a CSR (certificate signing request). CorePanel does not generate it, and that is deliberate: the private key would then have to exist on the server before the certificate did, and the one property worth paying for — that the key has never been anywhere you did not put it — would be gone.

Generate the pair on any machine with openssl. The install dialog shows this command already filled in with the hostname you typed:

Terminal window
openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key -out example.com.csr \
-subj "/CN=example.com"

Send the .csr to your CA and keep the .key: without it, the certificate they issue cannot be installed anywhere. When the certificate comes back, install it together with that key.

The step before the CSR is not CorePanel’s either, and it is worth saying plainly: your CA has to validate that you control the domain, usually by asking you to publish a DNS record or serve a file. If CorePanel manages the domain’s DNS, add the record in DNS; if the domain uses external DNS, add it wherever its zone actually lives. The file method works as soon as the domain resolves to this server.

You need the certificate and its private key; whether you also need the CA bundle depends on your issuer. Some CAs append the intermediate to the certificate file, others mail it separately.

In the panel, Install certificate takes the host and those files — pasted as PEM or picked from disk — and validates everything before writing. From a shell it is one command:

Terminal window
corepanel ssl upload example.com \
--cert /root/example.com.crt \
--key /root/example.com.key \
--chain /root/example.com.ca-bundle

Applying a renewal is the same command with the new files — it replaces the certificate in place.

The certificate is checked before anything is written, so a rejected upload leaves the site exactly as it was:

Refused whenWhy it matters
The chain does not reach a trusted CAThe classic one. Without the intermediate, the site works in the browser you test with — it cached the issuer from another site — and fails on Android and curl
The key does not match the certificateWould take TLS down on the next handshake
The certificate does not cover the hostName mismatch in every browser
It is expired, or not yet validCannot secure anything
It is self-signedA trust error for every visitor

The panel flags a certificate inside its 30-day window, the server logs a daily warning, and a notification goes out at 30, 14, 7, 3 and 1 days and again when it expires — five reminders rather than one a day for a month.

The notification reaches the administrator, the reseller and the account that owns the host, which is the point: since customers install their own certificates, the customer is usually the only person who can buy the renewal. Its wording follows the same distinction as the caution above — one message says the site will change issuer, the other says it will lose HTTPS — so nobody has to work out which case they are in.

The one case that keeps reminding you daily is an expired certificate with no automatic certificate underneath it: the site has no valid TLS at that point, and that stays true until somebody acts.

From a monitoring script, the exit status is enough:

Terminal window
corepanel ssl list >/dev/null || echo "a certificate needs attention"

This is for web hosts — HTTPS, and nothing else. Mail (mail.<domain>) and FTPS keep using the automatic wildcard described earlier in this page. Installing a web certificate does not change what Dovecot, Postfix or pure-ftpd present, on purpose: a certificate covering example.com alone would break STARTTLS on mail.example.com.

It is worth telling a customer this before they buy. Somebody who buys an OV certificate to stop a mail client warning will still see the warning, and the install dialog says so at the moment they are about to paste the key in.

A restored backup does not carry the uploaded certificate either — the archive covers the account’s files, databases and settings, not the server’s TLS store — so a restored site comes back on its automatic certificate and the commercial one has to be installed again.

The panel surfaces per-domain certificate status through the certificate manager (internally, the sys.GetDomainSSLStatus / sys.GetDomainSSLCertificates JSON-RPC methods on corepanel-sys). From a shell you can inspect the live certificates directly, which is the most reliable check:

Terminal window
# Web: which certificate the site presents on 443
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -dates
# Mail: which certificate IMAPS presents for the mail hostname
openssl s_client -connect mail.example.com:993 -servername mail.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -dates

If the mail hostname reports a subject that is the server’s hostname rather than example.com, the domain has no per-domain certificate in the store — the delegation gate. Confirm it:

Terminal window
# The domain's nameservers as seen by the public hierarchy
dig +short NS example.com
# Where those nameservers resolve — must match the server's public IPs
dig +short A ns1.example.com
# Is there a per-domain certificate on disk at all?
ls -l /var/lib/cp-sys/ssl/certs/example.com/

Mail client shows the wrong or untrusted certificate for mail.<domain>

Section titled “Mail client shows the wrong or untrusted certificate for mail.<domain>”

This is expected when the domain is not delegated to the server (see the Worked example above); apply one of the recommended setups.

Check reading and sending separately. They are served by different daemons from different configuration, so one can be right while the other is wrong — and the symptom a user reports (“it won’t take my password”) is the same either way:

Terminal window
# Reading (Dovecot, IMAPS)
openssl s_client -connect mail.example.com:993 -servername mail.example.com \
</dev/null 2>/dev/null | openssl x509 -noout -subject
# Sending (Postfix, submission)
openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com \
</dev/null 2>/dev/null | openssl x509 -noout -subject

To confirm what each daemon is configured to serve:

Terminal window
# Dovecot: per-domain local_name blocks + the default (host) certificate
cat /etc/dovecot/conf.d/99-corepanel-ssl.conf
# Postfix: the SNI table, and that it is actually referenced from main.cf
cat /etc/postfix/corepanel_sni.map
postconf -h tls_server_sni_maps

Both files are generated from one scan of the certificate store, so they should always list the same names; if they do not, systemctl restart corepanel-sys regenerates both. An empty tls_server_sni_maps on a server with certificates means Postfix is older than 3.4 — check postconf mail_version and the corepanel-sys journal for the warning.

When a certificate is issued, CorePanel regenerates both files and reloads Postfix and Dovecot automatically (internally, via sys.ReloadMailTLS), so a valid mail.<domain> certificate is picked up without manual steps. To force the running daemons to re-read their configuration yourself:

Terminal window
systemctl reload dovecot postfix