-
-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Problem Statement
Current sni-cert blocks require mandatory hostnames + individual file paths, making it cumbersome to manage folders containing many dynamically generated domain.crt/domain.key pairs from PKI agents or automation workflows.
HAProxy's ssl crt /path/ has long supported automatic folder scanning, CN/SAN extraction, and most-specific SNI selection - a production-proven approach for DevOps scalability.
Proposed Solution
1. New sni-certs block for folder auto-scan (within additional-certs)
sni-certs {
cert-folder "/etc/zentinel/certs/dynamic/" // Scans *.crt + matching *.key pairs (fullchain .crt)
reload-mode "interval" // "off" | "interval" | "inotify"
reload-interval "30s" // Only if reload-mode="interval"
}2. Make hostnames optional in existing sni-cert (auto CN/SAN fallback)
sni-cert {
cert-file "/premium.crt" // CN=*.premium.com SAN=api.example.com
key-file "/premium.key"
// hostnames auto-extracted from CN/SAN if not specified
}Complete TLS Configuration Example
listener "https" {
address "0.0.0.0:443"
protocol "https"
tls {
// 1. MANUAL DEFAULT (highest priority if present, blocks ACME)
cert-file "/etc/zentinel/certs/manual-default.crt"
key-file "/etc/zentinel/certs/manual-default.key"
// ACME automatic (fallback/domains-specific, used only if no manual)
acme {
email "admin@example.com"
domains "auto.example.com" "newshop.com"
}
additional-certs {
// PRIORITY 3: SNI-CERT WITH explicit hostnames
sni-cert {
hostnames "api.example.com" "direct.api.example.com"
cert-file "/etc/zentinel/certs/api-explicit.crt"
key-file "/etc/zentinel/certs/api-explicit.key"
}
// PRIORITY 4: SNI-CERT WITHOUT hostnames (auto CN/SAN)
sni-cert {
cert-file "/etc/zentinel/certs/premium-auto.crt" // CN=*.premium.com SAN=www.example.com
key-file "/etc/zentinel/certs/premium-auto.key"
}
// PRIORITY 5: SNI-CERTS FOLDER AUTO-SCAN (NEW)
sni-certs {
cert-folder "/etc/zentinel/certs/dynamic/"
reload-mode "interval"
reload-interval "30s"
}
}
}
}/etc/zentinel/certs/dynamic/ folder contents:
api-dynamic.crt (CN=api.example.com)
premium-dynamic.crt (CN=*.premium.com, SAN=beta.example.com)
wildcard-dynamic.crt (CN=*.example.com)
SNI Selection Results
| Requested SNI | Selected Certificate | Priority | Reason |
|---|---|---|---|
api.example.com |
api-explicit.crt |
#3 | Exact hostnames match |
direct.api.example.com |
api-explicit.crt |
#3 | hostnames pattern match |
www.example.com |
premium-auto.crt |
#4 | SNI in SAN of auto sni-cert |
app.premium.com |
premium-auto.crt |
#4 | SNI in CN of auto sni-cert |
beta.example.com |
premium-dynamic.crt |
#5 | SNI in SAN of folder scan |
static.example.com |
wildcard-dynamic.crt |
#5 | *.example.com longest-prefix |
shop.auto.example.com |
ACME cert | #6 | ACME domains match |
newshop.com |
ACME cert | #6 | ACME domains match (no higher) |
unknown.com |
manual-default.crt |
#1 | Default manual cert |
Processing Priority Order
1. manual cert-file/key-file (blocks everything else including ACME)
2. sni-cert { hostnames SNI in patterns } → explicit priority
3. sni-cert {} SNI in CN/SAN → auto cert CN/SAN
4. sni-certs folder SNI in CN/SAN → folder auto-scan
5. ACME (SNI in acme.domains only if no higher match)
6. FALLBACK Default manual cert (possible TLS handshake fails on validation)
Detailed Auto CN/SAN Behavior
sni-certs { cert-folder }: Scans folder for<name>.crt+<name>.keypairs, parses each .crt CN/SAN → builds hostname→cert indexsni-certwithouthostnames: Parses single cert CN/SAN → indexes that cert for those hostnamessni-certWITHhostnames: 1) SNI matches pattern → use cert (priority), 2) OR SNI in CN/SAN → use cert anyway
Benefits: Zero-config PKI folders, full ACME compatibility, HAProxy-like simplicity, production-ready reload modes (kill -HUP + inotify/interval).
Alternatives Considered
No response
Where does this belong?
Configuration option
Manifesto Alignment
- This feature can be bounded (has clear limits)
- This feature can be observed (metrics, logs)
- This feature can fail safely (explicit failure modes)
- This feature does not add implicit behavior
Checklist
- I have searched existing issues for duplicates
- I have read the Manifesto