EKS collector custom domain - Snowplow-managed DNS, imported certificate

Last updated: September 3, 2026

Snowplow owns the Route53 record. The customer supplies the certificate.

Start at EKS collector custom domains overview if you are not sure this is the right path.

Use this when the zone is delegated to the customer's Snowplow AWS account, but the customer insists on their own certificate — for example a wildcard from their corporate CA, or a Cloudflare Origin certificate.

The certificate is held by a separate k8s_certificate stack deployment, one per certificate. The collector then references that deployment by its environment name.

Consul keys

customer/<client>/aws_rt_pipeline_<env>/input/collector/dns/delegated_imported_cert_map

Both are a JSON object mapping domain to k8s_certificate environment name. Default is {}.

{"collector.acme.com": "cert1"}

Key

Effect

delegated_imported_cert_map

Same, and points the Route53 record at the NLB IPs.

Steps

1. Get the certificate from the customer

Ask for the full certificate chain and the private key, in PEM format. The certificate must cover the collector domain, either exactly or by a wildcard. Take it through an approved secure channel.

2. Deploy a k8s_certificate stack

Pick a short environment name for this certificate, for example cert1. Use a new name for each distinct certificate; reuse the name when the customer sends a renewal.

Store the material in Vault at:

secret/customer/<client>/k8s_certificate_<cert_env>

with fields cert (the full chain) and key (the private key).

Set the Consul inputs under customer/<client>/k8s_certificate_<cert_env>/input/:

Key

Value

_deps/k8s_namespace_env

The aws_eks_namespace environment the pipeline runs in.

certificate_domain

The certificate subject, for identification. For example *.acme.com.

Deploy the k8s_certificate stack with the stacks/deploy handler, using workspace
<client>-<cert_env>. This creates the TLS secret in the namespace.

3. Reference it from the pipeline

Add an entry to collector/dns/delegated_imported_cert_map mapping the domain to <cert_env>, then apply aws_rt_pipeline.

{"t.acme.com": "cer1", "d.example.com": "cert2"}

The apply attaches the secret to the Traefik ingress and writes the Route53 A record pointing at the NLB IPs, with a 60 second TTL.

Renewals

An imported certificate does not renew itself. Track the expiry, which the k8s_certificate stack publishes as cert_expiry. When the customer sends a replacement, create a brand new  k8s_certificate environment. Once created you will update the existing domain in collector/dns/delegated_imported_cert_map

Example is updating "t.acme.com" to use a new certificate

{"t.acme.com": "cer1", "d.example.com": "cert2"}

becomes

{"t.acme.com": "cert20", "d.example.com": "cert2"}

The reason we don't replace the existing k8s_certificate is for rollback purposes. If there's an issue with new certificate we can always repoint back to the previous k8s_certificate ENV for that domain

Verify

dig +short <domain>
curl -sI https://<domain>/health

aws/collector/validate_eks_collector 0.1.0 prints the certificate actually served, including its serial, subject, issuer and validity dates. Use it to confirm the imported certificate is in use and not a stale one.

Common failures

Message contains

Cause

must be a JSON object mapping domain => k8s_certificate env

The value is not valid JSON. It must be an object, not a list or a bare string.

collector_nlb_ips is empty

The aws_eks_namespace stack has not published the NLB IPs. Reapply it, then retry.

appear in BOTH an ack-managed key and an imported-cert key

The domain is also in an ACM key. Pick one certificate source.

appear in BOTH a cert-manager key and an imported-cert key

The domain is also in a cert-manager key. The imported secret wins and the cert-manager entry is ignored, so remove it.

appear in BOTH the delegated and external

The domain is also in external_imported_cert_map. Pick one.