SSL Certificates¶
enconf manages SSL certificates automatically via Let's Encrypt and additionally supports uploading custom certificates.
Overview¶
The SSL management shows all configured SSL certificates with their status.
| Column | Description |
|---|---|
| Domain | Certificate domain |
| Type | Let's Encrypt or Custom |
| Valid Until | Expiration date |
| Status | Valid, Expiring Soon, Expired |
Let's Encrypt (Automatic)¶
Request Certificate¶
Let's Encrypt certificates are automatically issued in most cases when creating a website or domain.
Manual request:
- Navigate to domain management
- Select the desired domain
- Click Enable SSL
Prerequisites:
- The domain must point to the server via A or AAAA record
- Port 80 must be reachable for the ACME HTTP challenge
- The domain must be publicly resolvable
Automatic DNS Check
Before activating SSL, the panel automatically checks via an external DNS resolver (Cloudflare 1.1.1.1) whether the domain's A record points to the server's IP. If the IP doesn't match, activation is rejected with a clear error message. This prevents failed Let's Encrypt challenges.
Secure all domains at once¶
After a migration (the importer intentionally transfers no certificates) every website starts without SSL. The "Secure all" button on the SSL page issues a Let's Encrypt certificate for every active website domain that has none yet:
- Runs in the background with progress and a per-domain outcome
- Per-domain result: issued · skipped (DNS doesn't point to this server yet — retry later) · failed
- Uses the same DNS pre-check as single activation, so no Let's Encrypt limits are burned on domains that don't point here yet
This brings all domains to HTTPS in one click after an import, without enabling each one individually.
Automatic Renewal¶
- The Certbot timer regularly checks all certificates
- Certificates are automatically renewed 30 days before expiration
- After renewal, Nginx is automatically reloaded
Let's Encrypt Limits
Let's Encrypt allows a maximum of 50 certificates per registered domain per week. For many subdomains, a wildcard certificate is recommended.
Troubleshooting¶
| Problem | Solution |
|---|---|
| DNS does not point to server | Correct the A/AAAA record |
| Port 80 blocked | Check firewall rule |
| Rate limit reached | Wait 1 hour, then try again |
| Domain not resolvable | Check DNS configuration |
| DNS points to wrong IP | Point the A record at one of this server's public IPs — on a server with several IPs, any of them is accepted (verified via external DNS 1.1.1.1) |
SSL Repair¶
Under Settings → Repair → RepairSSL the panel reconciles the TLS intent stored in the database against the certificates that actually exist on the server, and heals any drift.
What RepairSSL detects and fixes:
- Missing certificate — a domain is marked SSL-enabled in the panel but no certificate is (any longer) on disk (e.g. after an accidental revoke) → re-issued.
- Expired certificate → re-issued.
- SAN drift — the certificate doesn't cover every domain/alias of the site (e.g. a
www.domain added later) → expanded. - Redundant alias certificates — an alias owns its own certificate even though the site's primary certificate already covers it → surfaced as a one-click Remove (never deleted automatically).
- Marker and recorded choice — a custom certificate is served via a marker next to its files, and the choice is also stored in the database. RepairSSL reconciles the two: if the database says "custom" and the marker is missing, it is set (after the same checks as an installation); if the database says "Let's Encrypt" and the marker is still there, it is removed — but only when a Let's Encrypt lineage exists to hand back to. Otherwise it is only reported.
- Decision needed — a Let's Encrypt lineage and a custom certificate exist with no recorded choice → only reported, never changed (see above).
Preview first: the dry run shows, per domain, what would happen without issuing anything. On apply, RepairSSL first re-renders the vhost (so every name is in server_name), then re-issues the affected certificates — overriding any earlier ACME backoff so a domain whose root cause was just fixed can be issued again immediately.
Reachable names only
Names that no longer resolve to the server via DNS are left out of the re-issue — so a single missing DNS record can't fail the whole certificate request.
Self-heal on startup¶
If a certificate an Nginx vhost still references is missing (e.g. after a revoke), nginx -t would fail server-wide and Nginx would not start after a reboot. The agent heals this automatically on startup: the affected server block is reset to the always-present snakeoil certificate so Nginx comes up safely — the real certificate is then restored via RepairSSL or the normal SSL flow.
Unserved names (HTTPS catch-all)¶
If a visitor requests a name no vhost on the server serves (for example a domain that was never created or has been deleted but still points here via DNS), an HTTPS catch-all answers with the operating system's neutral, self-signed certificate and a 404 — never with a customer's certificate, which would otherwise reveal that customer's name and existence. Since 2.10.5 the catch-all also covers HTTP/3 (QUIC, UDP 443): there the default applied to TCP only, so nginx fell back on UDP to the first QUIC vhost in the configuration and handed out its (foreign) certificate. The agent writes the QUIC variant first and lets nginx -t decide; an nginx without the HTTP/3 module keeps the TCP-only catch-all.
Domain Aliases and Subdomains¶
When a domain alias or subdomain is created, the following happens automatically:
- DNS zone is created with A records pointing to the server IP
- Domain record is created in the panel (visible in the domain and SSL management)
- Nginx vhost is updated — the alias is added to the
server_namedirective
Enabling SSL for Aliases¶
When enabling SSL for a domain, all domain aliases of the associated site are automatically included as SANs (Subject Alternative Names) in the certificate. This means:
- One certificate covers the primary domain + all aliases
- All domains share the same Nginx
serverblock and the same certificate - When new aliases are added, the certificate is automatically expanded (
certbot --expand)
You only need to enable SSL for the primary domain — aliases are covered automatically.
Wildcard certificates count as coverage
Whether a certificate covers a name is decided uniformly by the TLS rules: a wildcard (*.example.com) covers exactly one label (www.example.com, shop.example.com), not the apex example.com and not two labels (a.b.example.com). An existing wildcard certificate is therefore found for an alias or name beneath it (instead of that name getting the placeholder certificate), and a re-issue is skipped when the wildcard already covers all names. The renewal's 30-day margin still decides on its own.
DNS Must Be Correct
All domains in the certificate (primary + aliases) must have their A record pointing to the server IP. Otherwise the Let's Encrypt challenge will fail.
Wildcard Certificates (*.domain.com)¶
Wildcard certificates cover all subdomains of a domain (e.g. *.example.com). They are issued via the DNS-01 challenge from Let's Encrypt.
Prerequisites¶
- The domain must use the panel's nameservers so the
_acme-challengeTXT record can be set automatically - Customers with external DNS can use Let's Encrypt (HTTP-01) or upload a custom certificate instead
Request a Wildcard Certificate¶
- Navigate to SSL Certificates
- Click Enable SSL for the desired domain
- Select Wildcard (*.domain)
- Click Enable
The process takes 1–3 minutes as DNS propagation needs to complete.
ACME DNS Configuration¶
| Mode | Description |
|---|---|
| Automatic | Uses the PowerDNS server that manages the DNS zone in the panel |
| External PowerDNS | Uses an external PowerDNS instance (API URL + API Key required) |
Configuration under Settings → Panel Settings → ACME DNS:
| Setting | Description |
|---|---|
| DNS Mode | Automatic or External PowerDNS |
| PowerDNS API URL | URL of the external PowerDNS API (e.g. http://ns1.example.com:8081) |
| PowerDNS API Key | API key for authentication |
Automatic Renewal¶
Wildcard certificates are automatically renewed 30 days before expiry — also via DNS-01 challenge.
External PowerDNS Instances
When using an external PowerDNS server, ensure the API URL is reachable from the panel server and the API key has permission to create and delete TXT records in the zone.
Custom Certificates (Custom SSL)¶
For domains that cannot or should not use Let's Encrypt:
Install a Certificate¶
- Open Enable SSL for the domain and choose the certificate type Custom certificate
- Paste the contents in PEM format into the fields:
| Field | Required | Description |
|---|---|---|
| Certificate (PEM) | Yes | The SSL certificate |
| Private Key (PEM) | Yes | The associated private key |
| Intermediate Chain (optional) | No | Intermediate certificates, appended to the certificate |
- Click Enable
A custom certificate can only be installed for a website's primary domain (or a domain without a website), not for a single alias or subdomain.
What is checked before installation¶
Before anything is written to the server the agent checks:
- Certificate and key are valid PEM (at most 64 KB per field) and belong together
- The key is strong enough: RSA 2048 bit or more, EC 256 bit or more (Ed25519 is accepted too)
- The certificate is valid for the domain — wildcards are handled correctly (
*.example.comcoverswww.example.com, notexample.com) - The certificate is valid right now (not expired, not yet valid in the future)
A violation aborts the installation with a specific message. A password-protected key is not accepted — remove the passphrase first.
All or nothing
The files are written atomically (the key readable by root only), then the web server configuration is re-rendered. If Nginx rejects the configuration, the agent rolls the installation back and restores the previous certificate — you see the error but never a half-installed state. The private key is never logged, never stored in the database and never returned in a response.
Replace a Certificate¶
Simply install a new certificate for the same domain — the previous one is only removed once the new one has been rendered successfully.
Your own certificate stays¶
An installed custom certificate is never silently swapped for Let's Encrypt. The agent remembers your choice and serves the custom certificate while it is valid. Specifically, these flows leave it alone:
- Re-issue (triggered by every new alias and subdomain), the automatic renewal, RepairSSL and the Site Doctor skip the domain with the reason "custom certificate". For an expiring custom certificate the Doctor offers no "re-issue" fix — only installing a new certificate helps.
- Enabling Let's Encrypt replaces the custom certificate only after explicit confirmation in the dialog (the call requires
replace_custom=true; without confirmation the panel answers with a conflict and changes nothing). - FTP does not use a custom certificate — a customer's certificate is never chosen for FTP TLS.
If the custom certificate fails (expired, key pair broken, file swapped, not yet valid), the server serves the Let's Encrypt certificate again if one exists, instead of showing visitors a dead certificate. Without a Let's Encrypt certificate the custom one stays.
Aliases and subdomains
A custom certificate is not extended. If you create an alias or subdomain whose name the certificate does not cover, the panel warns you: visitors see a certificate warning until you upload a certificate that includes the name.
Display and "decision needed"¶
The certificate list shows exactly the certificate that is served per name — when a custom certificate is active it is listed instead of the Let's Encrypt lineage behind it.
On existing domains both a Let's Encrypt lineage and a custom certificate can sit on disk without a choice ever having been recorded. The panel does not guess: it changes nothing, reports the domain with both expiry dates as "decision needed" in the RepairSSL report, and shows a "decision needed" counter on the admin dashboard. Decide by activating the certificate you want (install the custom one or enable Let's Encrypt).
Panel SSL¶
The SSL certificate for the panel itself is configured under Settings > Server:
Options¶
| Mode | Description |
|---|---|
| Let's Encrypt | Automatic certificate for the panel URL |
| Custom | Upload a custom certificate |
| Self-Signed | Self-signed certificate (for testing only) |
Configure Panel SSL¶
- Navigate to Settings > Server
- Select the Panel SSL Mode
- For Custom: Upload certificate and key
- Click Save
SSL validation method (for servers not reachable from the internet)¶
By default the panel certificate is validated via HTTP-01 — Let's Encrypt must reach the server on port 80 from the internet. For internal or firewalled servers that aren't reachable from outside, HTTP-01 can never complete (the "Issue certificate" button then appears to do nothing). For those cases enconf offers DNS-01 validation via a DNS provider — the certificate is validated through a DNS record instead of over HTTP.
Configure under Settings → Panel → Panel SSL validation:
| Method | Description |
|---|---|
| HTTP (default) | HTTP-01 over port 80 — the server must be reachable from the internet |
| DNS (Cloudflare) | DNS-01 via the Cloudflare API — automatically reuses the Cloudflare API token from Settings → DNS |
| DNS (Hetzner) | DNS-01 via the Hetzner DNS API — enter a Hetzner DNS API token |
| DNS (RFC2136 / dynamic) | DNS-01 via dynamic DNS updates (TSIG) — works with enconf's own PowerDNS and any BIND/PowerDNS/Knot server that allows dynamic updates |
RFC2136 additionally needs the TSIG credentials:
| Field | Description |
|---|---|
| DNS server | Hostname or IP of the DNS server that accepts dynamic updates |
| Port | Default 53 |
| TSIG key name | Name of the TSIG key (with trailing dot, e.g. acme-key.) |
| TSIG secret | Base64-encoded TSIG secret |
| TSIG algorithm | e.g. HMAC-SHA256 (also SHA512/384/224/SHA1/MD5) |
Issue the certificate:
- Settings → Panel → Panel SSL validation — pick a provider and enter the credentials
- Save
- Click Issue panel certificate now
Only the issue button performs the first issuance
On an internal server whose first HTTP attempt failed there is no renewal configuration yet — so the regular "renew" action cannot create an initial certificate. The Issue panel certificate now button triggers a fresh issuance using the selected validation method.
Automatic renewal & security
Credentials are stored in a root-only file so certbot renew later renews the certificate automatically via the same DNS method — no further manual step. The DNS plugin needed for validation (Cloudflare/Hetzner/RFC2136) is installed on demand. HTTP validation remains the unchanged default for publicly reachable servers.
Mail SSL¶
For encrypted email communication (IMAP/SMTP):
- Navigate to Settings > Server
- Configure the Mail SSL Mode
- Options are the same as for Panel SSL
Separate Certificates
It is recommended to use separate certificates for the panel and mail server so that the mail hostname (e.g. mail.example.com) is correctly included in the certificate.
Dedicated mail server
A dedicated mail server (mail gateway or mail storage role, without Nginx) now also gets a Let's Encrypt certificate for its hostname. Certbot is part of both mail roles; without Nginx issuance runs via --standalone. On servers with Nginx the challenge still goes through the web server. Previously the mail hostname there stayed on the self-signed certificate — exactly the one mail clients were shown.
Mail SNI (Per-Domain TLS Certificates)¶
enconf supports Server Name Indication (SNI) for mail services. This allows each domain to use its own TLS certificate for Postfix (SMTP) and Dovecot (IMAP/POP3) connections.
When SSL is enabled for a domain, the certificate is automatically pushed to both Postfix and Dovecot SNI maps. This means that mail clients connecting to mail.customer-domain.com receive the correct certificate for that domain, rather than the server's default mail certificate.
How it works:
- When a Let's Encrypt or custom certificate is issued for a domain, the panel automatically updates the Postfix and Dovecot SNI configuration
- No manual configuration is required
- Each domain presents its own certificate during the TLS handshake
- Falls back to the default mail certificate if no domain-specific certificate is available
Automatic Configuration
Mail SNI is configured automatically whenever SSL is enabled for a domain. There are no additional settings to configure.
How it works¶
When SSL is enabled for a domain, the certificates are configured for the mail services as well:
- Enable SSL — enabling SSL for a domain hands the certificate to Postfix and Dovecot automatically
- SNI mapping — Postfix and Dovecot pick the matching certificate from the hostname the client asked for
- Automatic refresh — when the certificate is renewed through Let's Encrypt, the mail services are updated automatically
Compatibility¶
Mail SNI works with both mail architectures:
| Architecture | Description |
|---|---|
| Central | The mail gateway server manages all certificates |
| Decentral | Each server manages its own mail certificates |
No manual step required
SNI configuration happens entirely automatically when SSL is enabled for a domain. There is nothing else to do.
Certificate Monitoring¶
The system automatically monitors all SSL certificates:
- 30 days before expiration: Automatic renewal for Let's Encrypt
- 14 days before expiration: Notification to the customer. Custom certificates have their own event (Own SSL certificate expiring,
ssl_expiring_custom) whose text asks for a new certificate to be uploaded — it is not renewed automatically. Let's Encrypt keeps the "SSL certificate expiring" event. Both can be customized under Notifications. - Expired: Warning on the dashboard and system page
TLS health judges the served certificate¶
The TLS health report connects to the services (HTTPS, SMTPS, IMAPS, panel) and judges the certificate that is actually served — not only the certificate registry entry. This matters because, for example, Postfix can keep serving the old certificate after a renewal while the registry already shows the new one. An expired served certificate now also shows as expired for SMTPS and IMAPS; the expiry is checked before the name. The name comparison understands wildcard certificates, so a wildcard serving www.example.com is no longer a false alarm.