Certificate Management

This section covers TLS certificate strategy for the global DR hostname and why DNS-01 is typically required.

Certificate Architecture for DR Failover

The external ingress certificate is issued for the global DR FQDN (logscale-dr.oci-dr.humio.net), not for cluster-specific names. This is correct for DR failover.

ComponentPrimary ClusterSecondary Cluster
Ingress Hostlogscale-dr.oci-dr.humio.netlogscale-dr.oci-dr.humio.net
TLS Secret Namelogscale-dr.oci-dr.humio.netlogscale-dr.oci-dr.humio.net
Certificate CNCN=logscale-dr.oci-dr.humio.netCN=logscale-dr.oci-dr.humio.net
IssuerLet's EncryptLet's Encrypt
Two Separate Certificate Systems

1. Internal HumioCluster Certificates (managed by humio-operator)

For internal pod-to-pod TLS communication:

yaml
Certificate name: dr-secondary
DNS names:
- dr-secondary.logging
- dr-secondary-headless.logging
- dr-secondary-internal.logging
Issuer: dr-secondary (self-signed CA created by humio-operator)

2. External Ingress Certificate (managed by cert-manager)

For external HTTPS traffic from users/clients:

yaml
Secret name: logscale-dr.oci-dr.humio.net
DNS names:
- logscale-dr.oci-dr.humio.net
Issuer: letsencrypt-cluster-issuer (Let's Encrypt via DNS-01 or HTTP-01)
Why This Configuration is Correct for DR

  • Same hostname across clusters: Both primary and secondary use logscale-dr.oci-dr.humio.net

  • Each cluster has its own certificate: Independently issued by Let's Encrypt

  • DNS-based failover works seamlessly: When DNS steering policy switches to secondary, the certificate matches

  • No certificate changes during failover: The hostname users access remains constant

Hostname Configuration

The ingress hostname is configured using logscale_public_fqdn:

terraform
# tfvars - set to global hostname for DR failover
logscale_public_fqdn = "logscale-dr.oci-dr.humio.net"

Cluster-specific aliases are configured via primary_logscale_hostname and secondary_logscale_hostname:

terraform
# Global DNS hostnames (when dr != "")
global_logscale_hostname = "logscale-dr" # logscale-dr.oci-dr.humio.net
primary_logscale_hostname = "logscale-primary" # logscale-primary.oci-dr.humio.net
secondary_logscale_hostname = "logscale-secondary" # logscale-secondary.oci-dr.humio.net

With this configuration:

  • Global FQDN (logscale-dr.oci-dr.humio.net): Used by clients, routes to healthy cluster via DNS steering

  • Cluster-specific aliases: Direct access for debugging/validation (bypasses DR steering)

Automatic Hostname Selection for DR Mode

When using DR mode (dr="active" or dr="standby"), the effective LogScale hostname is automatically determined from global_logscale_hostname and dns_zone_name. You do not need to manually set logscale_public_fqdn to the global hostname.

Important

Both primary and secondary clusters must use the same global_logscale_hostname value. If the values differ, the ingress on each cluster will respond to different hostnames, and DR failover will fail with HTTP 404 errors because the ingress won't match the requested hostname.

DR Modetfvars logscale_public_fqdnEffective Hostname UsedWhy
dr="" (non-DR)logscale-single.example.comlogscale-single.example.comDirect cluster access, no failover
dr="active"logscale-single.example.comlogscale-global.example.comAuto-uses ${global_logscale_hostname}.${dns_zone_name}
dr="standby"logscale-single.example.comlogscale-global.example.comSame global hostname for steering policy

Example configuration:

terraform
# Cluster-specific hostname (used when dr="")
logscale_public_fqdn = "logscale-single.oci-dr.humio.net"
# DR hostnames (used when dr="active" or "standby")
global_logscale_hostname = "logscale-oci" # โ†’ logscale-oci.oci-dr.humio.net
primary_logscale_hostname = "logscale-single" # โ†’ A record for direct access
secondary_logscale_hostname = "logscale-secondary" # โ†’ A record for direct access
dns_zone_name = "oci-dr.humio.net"
dr = "active" # Triggers automatic use of global hostname

Result: The HumioCluster hostname, PUBLIC_URL, and ingress rules automatically use logscale-oci.oci-dr.humio.net, allowing the DNS steering policy to route traffic to the healthy cluster.

Note

You do not need to change logscale_public_fqdn when switching between DR modes. The system automatically selects the appropriate hostname based on the dr variable.

Verification Commands
shell
# Check ingress hostname and TLS configuration
kubectl --context oci-secondary get ingress -n logging -o jsonpath='{.items[0].spec.tls[0]}'
# Output: {"hosts":["logscale-dr.oci-dr.humio.net"],"secretName":"logscale-dr.oci-dr.humio.net"}
# Verify certificate CN matches global FQDN
kubectl --context oci-secondary get secret logscale-dr.oci-dr.humio.net -n logging \
-o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -subject
# Output: subject=CN=logscale-dr.oci-dr.humio.net
# Check certificate issuer and validity
kubectl --context oci-secondary get secret logscale-dr.oci-dr.humio.net -n logging \
-o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -issuer -dates
# Confirm ingress annotations include cert-manager
kubectl --context oci-secondary get ingress -n logging \
-o jsonpath='{.items[0].metadata.annotations.cert-manager.io/cluster-issuer}'
# Output: letsencrypt-cluster-issuer
DNS-01 Certificate Issuance

DNS-01 certificate validation is recommended when HTTP-01 validation is blocked by firewall rules (e.g., public_lb_cidrs restricts access to specific IP ranges). DNS-01 validates ownership via _acme-challenge TXT records in OCI DNS, allowing certificate issuance regardless of firewall configuration.

When to use DNS-01:

  • Primary cluster with firewall-restricted load balancer (HTTP-01 blocked)

  • Standby cluster (HTTP-01 may fail during DNS failover)

  • Any cluster where Let's Encrypt cannot reach port 80

Implementation Summary

  • cert-manager is installed by the shared ../logscale-kubernetes module

  • The OCI repo deploys cert-manager-webhook-oci and a DNS-01 ClusterIssuer when DNS-01 is enabled and needed (cert_dns01_provider="oci", cert_dns01_webhook_enabled=true, and cert_dns01_webhook_mode allows deployment)

  • When DNS-01 is enabled, ../logscale-kubernetes skips creating its default HTTP-01 ClusterIssuer (skip_cluster_issuer = true)

For detailed architecture, key components, and step-by-step flow diagrams, see module.cert-manager-oci-webhook In the Architecture Considerations section.

Configuration

Enable DNS-01 on any workspace where HTTP-01 is blocked:

terraform
cert_dns01_provider = "oci"
cert_dns01_webhook_enabled = true
cert_dns01_webhook_mode = "auto" # or "always"

DNS-01 reuses the same OCI API key inputs already required by this repo (tenancy_ocid, user_ocid, user_fingerprint, private_key_path, region).

Files
FileChange
oci/modules/kubernetes/cert-manager-oci-webhook/main.tfWebhook Service + Deployment + APIService + ClusterIssuer
oci/modules/kubernetes/cert-manager-oci-webhook/pki.tfWebhook TLS PKI (Issuer/Certificate)
oci/modules/kubernetes/cert-manager-oci-webhook/rbac.tfWebhook RBAC + ServiceAccount
oci/modules/kubernetes/cert-manager-oci-webhook/variables.tfWebhook + DNS-01 inputs
oci/main.tfInstalls webhook module (when DNS-01 is enabled/needed) and sets skip_cluster_issuer=true
Verification
shell
# Verify on primary cluster (when DNS-01 enabled)
kubectl --context oci-primary get clusterissuer letsencrypt-cluster-issuer -o yaml
kubectl --context oci-primary get secret oci-dns-credentials -n logging-cert
kubectl --context oci-primary get apiservice v1alpha1.acme.d-n.be
kubectl --context oci-primary get certificates -n logging
kubectl --context oci-primary get secret logscale-dr.oci-dr.humio.net -n logging \
-o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -subject -issuer -dates
# Verify on secondary cluster (when DNS-01 enabled)
kubectl --context oci-secondary get clusterissuer letsencrypt-cluster-issuer -o yaml
kubectl --context oci-secondary get secret oci-dns-credentials -n logging-cert
kubectl --context oci-secondary get apiservice v1alpha1.acme.d-n.be
kubectl --context oci-secondary get certificates -n logging
kubectl --context oci-secondary get secret logscale-dr.oci-dr.humio.net -n logging \
-o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -subject -issuer -dates