Skip to main content

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:init creates them under the server hostname: the hostname itself, admin, control, accounts, mail, mail-out, bounces, phpmyadmin, adminer, dns1 and dns2. 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.

Why the panel orders wildcards

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.

Renewal takes time after a fix

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:

StatusMeaning
ValidIssued and in its validity period.
IssuedIssued but not yet valid.
ExpiredPast its expiry.
PendingA key with its names, waiting for the CA.
ErrorIssuance failed.
Self-signedThe 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:

SettingEffect
AutomaticThe default. A certificate only for a public address.
OnA certificate whatever the address's range: for a private certificate authority.
OffNone.
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.

CommandWhat it does
certificate:provision:autoThe 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:checkAsks the CAs for the renewal windows of the certificates due to be asked about.
certificate:expiry:announceThe daily expiry notices, now (see below).
certificate:purgeDeletes 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:listThe 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.

A warning on a live site

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).