When implementing DNS-based routing for multi-tenant documentation systems, the SSL/TLS certificate handling becomes critical. The specific scenario involves:
Tenant Domain: docs.tenantcompany.com (CNAME)
→
Hosted Domain: docs.tenant.mycompany.com
The SSL handshake occurs after DNS resolution, meaning the certificate must validate against the client-requested domain (docs.tenantcompany.com). A wildcard certificate for *.tenantcompany.com would technically cover this case, but proper configuration is essential.
Option 1: Tenant-Provided Certificate
If tenants manage their own certificates:
server {
listen 443 ssl;
server_name docs.tenant.mycompany.com docs.tenantcompany.com;
# Tenant's wildcard cert
ssl_certificate /path/to/tenant_wildcard.pem;
ssl_certificate_key /path/to/tenant_wildcard.key;
# SAN must include both domains
ssl_client_certificate /path/to/ca-bundle.crt;
}
Option 2: Automated Certificate Management
For scalable solutions, consider Let's Encrypt with DNS challenges:
# Certbot example for Nginx
certbot --nginx \
-d docs.tenantcompany.com \
-d docs.tenant.mycompany.com \
--preferred-challenges dns \
--manual-auth-hook ./authenticator.sh \
--manual-cleanup-hook ./cleanup.sh
- Certificate Transparency Log requirements for new domains
- TLS SNI (Server Name Indication) support in legacy clients
- CAA record conflicts in tenant DNS zones
For large-scale implementations, a Kubernetes ingress controller with cert-manager handles this elegantly:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tenant-docs
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- docs.tenantcompany.com
- docs.tenant.mycompany.com
secretName: tenant-tls
rules:
- host: docs.tenantcompany.com
http:
paths: [...]
- host: docs.tenant.mycompany.com
http:
paths: [...]
In multi-tenant architectures where documentation is served through tenant-specific subdomains, the DNS configuration typically involves CNAME records pointing tenant domains to your infrastructure. The SSL/TLS handshake occurs before any HTTP redirection, which creates certificate validation requirements.
When a user accesses docs.tenantcompany.com
, the TLS handshake validates the certificate against these criteria:
1. Certificate must cover exact FQDN (docs.tenantcompany.com) or 2. Wildcard certificate covering *.tenantcompany.com 3. Certificate must chain to a trusted root CA 4. Must pass SNI validation if using shared hosting
A tenant's existing wildcard certificate for *.tenantcompany.com
will work for your CNAME setup, provided:
# Example openssl verification
openssl s_client -connect docs.tenantcompany.com:443 \
-servername docs.tenantcompany.com | \
openssl x509 -noout -text | \
grep "DNS:*.tenantcompany.com"
When wildcards aren't available, consider these approaches:
# Option 1: SNI-based certificate loading
server {
listen 443 ssl;
server_name docs.tenantcompany.com;
ssl_certificate /path/to/tenant_cert.pem;
ssl_certificate_key /path/to/tenant_key.pem;
# ... other config
}
For automated certificate management:
# Example using Certbot with DNS challenge
import certbot.main
certbot.main.main([
'certonly',
'--dns-route53',
'--domain', 'docs.tenantcompany.com',
'--non-interactive',
'--agree-tos',
'-m', 'admin@tenantcompany.com'
])
Key considerations for production environments:
- Ensure DNS TTL values are optimized (300-600 seconds)
- Monitor certificate expiration (90-day lifecycle for Let's Encrypt)
- Implement OCSP stapling for performance
Example monitoring check:
#!/bin/bash
expiry_date=$(echo | \
openssl s_client -connect docs.tenantcompany.com:443 2>/dev/null | \
openssl x509 -noout -dates | \
grep 'notAfter' | \
cut -d'=' -f2)
remaining_days=$(( ($(date -d "$expiry_date" +%s) - $(date +%s)) / 86400 ))