Certificates
Every hostname the server serves has a TLS certificate, and the panel gets and renews all of them itself: for its own hosts, for every account's hosts, and for the server's IP addresses. What an account holder sees of theirs is in the account docs.
What gets a certificate
- The server's own hosts.
server:initcreates them under the server hostname: the hostname itself,admin,control,accounts,mail,mail-out,bounces,phpmyadmin,adminer,dns1anddns2. The server owns their certificates. - Every account host: each hostname on Hosts (Hosts and services). The account owns the certificate. A host is served by its own account's certificates or the server's, never another account's, apart from a parent's wildcard covering a subaccount's delegated subdomain.
- The server's IP addresses, so that
https://<address>/shows no warning. See IP addresses.
A host gets two certificates, one RSA and one ECC, and a client negotiates
the one it supports. The files live under /var/lib/elpan/pki/<hostname>/,
root-owned, and every daemon that terminates TLS for the hostname reads them
from there: nginx, Dovecot, Postfix and ProFTPD. Mail and FTP on a hostname
use the same certificate as its website.
How the panel issues
A new host is served at once with a certificate the panel already holds for its domain, and otherwise with a self-signed placeholder while an order runs. The order goes to the server's active ACME account (ACME Client Accounts), Let's Encrypt on a default install.
An automatic order asks for the domain and its wildcard together,
example.com and *.example.com, so every host under the domain shares one
certificate and a new subdomain needs no new order. The wildcard is
validated with a DNS record, which the panel can write only into a zone it
hosts for the same account. Where it can't, the order falls back to the
host's exact name, validated over HTTP. This is the deployment default
(certificate.wildcard_coverage: true); certificate:provision:auto --exact orders each host's own name instead.
A certificate authority limits certificates per registered domain per week. Thirty subdomains ordered one by one are sixty certificates (RSA and ECC each); as one coverage set they are two.
Renewal
A certificate's renewal point is two-thirds of the way through its lifetime
(halfway for a lifetime under 10 days). Every hour, at 23 minutes past, the
panel orders for up to 100 hosts that have no certificate, a self-signed one,
or one past its renewal point, and then for the IP addresses. A host whose
attempt failed is held for two hours and given up on after 24 failures; a
host whose name doesn't work yet (a new host whose DNS is still
publishing) is retried within minutes instead. host:view <hostname> shows
the last outcome, its reason, the last attempt and the failure count.
Where the CA publishes renewal information (ACME Renewal Information;
Let's Encrypt does), an hourly check at 13 minutes past moves the renewal
point into the window the CA suggests, and the renewal order names the
certificate it replaces. certificate:renewal-window:check runs that check
by hand.
A renewal never leaves a daemon without a certificate: each file is written beside the old one and renamed over it, so a reload at any instant reads a whole certificate, old or new.
A certificate authority's rate limits can block a domain for days, so the
panel keeps its deliberate pace after you correct DNS for a host. Don't
force repeated orders; run certificate:provision:auto once if you don't
want to wait for the next hour.
The Certificates screen
System › Certificates lists every certificate on the server, the server's and the accounts', one row per key algorithm: its Common Name, Status, Algorithm, the ACME Provider that issued it, and Valid To. The statuses:
| Status | Meaning |
|---|---|
| Valid | Issued and in its validity period. |
| Issued | Issued but not yet valid. |
| Expired | Past its expiry. |
| Pending | A key with its names, waiting for the CA. |
| Error | Issuance failed. |
| Self-signed | The placeholder, in addition to the status. |
A certificate's page shows whether it is Trusted (its chain validates against the server's trust store), the hosts and IP addresses that use it, and the certificate itself. The screen is read-only; the certificate's lifecycle is the panel's.
IP addresses
A request to https://<address>/ carries no hostname, so it is answered by
the address's default server. The panel gets a certificate for each of the
server's addresses too, from the active ACME account, and serves it there.
Let's Encrypt issues an address certificate for 160 hours, under a week,
under its short-lived profile and only for a public address, so the panel
renews it about every three days. Let's Encrypt also allows five
certificates per exact set of names a week, and those renewals use most of
that; a forced order on top of them can lock the address out until the
oldest ages out, which is why certificate:provision:manual --force asks
before ordering for an address.
Each address has a setting, on System › Shared IP Address Groups ›
the group (Shared IP Address Groups),
under IP Certificates, or with certificate:ip:set:
| Setting | Effect |
|---|---|
| Automatic | The default. A certificate only for a public address. |
| On | A certificate whatever the address's range: for a private certificate authority. |
| Off | None. |
elpanctl certificate:ip:set <address> auto|on|off
An address that stops asking loses its certificate at once: the edge goes
back to the fallback certificate and the files under
/var/lib/elpan/pki/@ip-<address> are removed. The screen also shows what
each address serves, a pending install or removal, and how the last round
ended, including a wait the CA asked for.
Inspection and repair
All of these run in a root shell on the server.
| Command | What it does |
|---|---|
certificate:provision:auto | The hourly round, now. --dry-run lists what it would order, --exact orders each host's own name, --force ignores the six-hour floor on reordering a set and includes hosts held after a failure. |
certificate:provision:manual <name>... | Orders a certificate for the names you type, wildcards included, as typed and without widening, and puts it into service on their hosts. Also for the server's IP addresses. |
certificate:apply <hostname>... [--force] | Chooses the best available certificate for the hosts and installs it. --force rewrites the files and the daemons' configuration even when the choice is unchanged, e.g. after a configuration template changed. |
certificate:audit-ownership [--backfill] | Reports certificates that name hosts of another owner, wildcards whose base host changed owner, or names not hosted here. --backfill hands a server certificate whose names all belong to one account to that account. |
certificate:test-trust [<certificate-id>] | Names, issuer, validity and whether the chain is trusted, for one certificate or for five issued ones. |
certificate:debug-trust <certificate-id> | Each certificate of the chain, and the trust check with and without the intermediates. |
certificate:renewal-window:check | Asks the CAs for the renewal windows of the certificates due to be asked about. |
certificate:expiry:announce | The daily expiry notices, now (see below). |
certificate:purge | Deletes expired certificates that no host uses, and their private keys. A dry run unless --force; keeps those expired within --grace-days (30), at most --limit (1000) per run. |
certificate:provider:list | The server's CA relationships. |
A certificate id is on its page under ID, and in host:view.
Two sweeps run daily: at 06:53 the panel announces the certificates in use
that crossed 30 or 7 days left and are not being renewed by it, or whose
renewal is overdue, as the webhook event certificate.expiring
(Webhooks); at 04:41 it purges expired
certificates that no host uses, a month after their expiry, so that their
private keys don't accumulate.
The certificate page of the site's host tells you which case it is. A
self-signed placeholder on a new host means the order hasn't succeeded yet;
host:view has the reason, which is almost always that the name doesn't
resolve to this server. A valid certificate that is not Trusted was
issued by a CA the server doesn't trust: the staging account, or a private
CA whose root is not installed
(Your own certificate authority).