TLS Certificates
Choose and install certificates for Scrydon's public ingress, private domains, and Traefik-backed Kubernetes routing.
Scrydon exposes browser and API traffic through Kubernetes Ingress objects. The chart defaults to Traefik-compatible Ingresses and cert-manager.io/cluster-issuer: letsencrypt-prod, but certificate ownership depends on where TLS terminates.
Choose your path
| Your setup | Certificate path |
|---|---|
| Public hostname reaches Traefik directly | Use cert-manager with Let's Encrypt. The TLS prerequisite shows the default ClusterIssuer. |
| Publicly delegated domain, but private ingress | Use Let's Encrypt DNS-01 with a DNS provider solver. |
| Private-only hostname | Use an internal ACME CA or a static corporate certificate. |
| Upstream load balancer terminates TLS | Install the public certificate on the load balancer, then configure TLS Offloading. |
| Upstream load balancer re-encrypts, or clients reach Traefik directly over HTTPS | Give Traefik a certificate for the public hostname. |
Certificate responsibilities
| Leg | What needs a certificate | Default Scrydon behavior |
|---|---|---|
| Client to Traefik | The certificate that clients see for routing.host or the per-app subdomains. This can live on Traefik, or on an upstream load balancer if it terminates TLS before Traefik. | In subpath mode the chart references tls-frontdoor. In subdomain mode it references tls-auth, tls-platform, tls-cortex, tls-agentic, tls-agentic-realtime, tls-analytics, and tls-marimo-sidecar as needed. |
| Traefik to workloads | No public certificate by default. Traefik routes to the app Services over the cluster network. | The chart's Ingress backends use the app Services' http ports. Service-to-service traffic between Scrydon workloads is protected separately by Dapr mTLS with SPIFFE identity. |
Keep ingress.tls.enabled: true whenever users reach Scrydon over https://, even if an upstream load balancer terminates TLS and forwards plain HTTP to Traefik. This value controls public URL generation, CORS, and secure cookies; it is not only a Traefik certificate toggle.
If your upstream load balancer terminates TLS and forwards HTTP to Traefik, the public certificate belongs on that load balancer. Traefik still needs trusted forwarded headers; follow TLS Offloading.
If your upstream load balancer re-encrypts to Traefik, or users connect directly to Traefik over HTTPS, Traefik needs a certificate for the public hostname.
Public DNS and Let's Encrypt
Let's Encrypt can issue only for names under publicly delegated DNS. HTTP-01 also requires the hostname to resolve publicly to an ingress that can serve /.well-known/acme-challenge/... on port 80.
DNS-01 does not require the A record to be public, but it still requires a publicly delegated domain where Let's Encrypt can query the authoritative DNS server for _acme-challenge TXT records. For example:
| Domain shape | Let's Encrypt fit |
|---|---|
app.example.com, where example.com is publicly registered and you can create public DNS TXT records | Works. Use HTTP-01 if ingress is public, or DNS-01 if the A record is private. |
app.internal, something.local, or any private-only zone with no public authoritative DNS | Does not work. Use an internal CA or static corporate certificate. |
Option 1: internal ACME with step-ca
For private-only domains where you still want automatic issuance and renewal, run an internal ACME CA such as Smallstep step-ca and point cert-manager at it.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: internal-acme-issuer
spec:
acme:
server: https://step-ca.cert-manager.svc.cluster.local/acme/acme/directory
email: admin@yourcompany.local
privateKeySecretRef:
name: internal-acme-account-key
solvers:
- http01:
ingress:
ingressClassName: traefikThen use that issuer in your Scrydon values:
ingress:
tls:
enabled: true
clusterIssuer: internal-acme-issuer
routing:
host: app.yourcompany.localcert-manager will populate the same TLS Secret names the chart references. In default subpath mode, that is tls-frontdoor in the scrydon-platform namespace.
Option 2: bring your own static certificates
If your IT or security team issues certificates from a corporate PKI, create Kubernetes TLS Secrets with the names Scrydon's Ingresses reference.
For default subpath routing:
kubectl create secret tls tls-frontdoor \
--cert=path/to/corporate-cert.crt \
--key=path/to/corporate-key.key \
-n scrydon-platformFor subdomain routing, create the per-app secrets in the namespace where each Ingress is rendered. With the default single namespace, create them all in scrydon-platform:
for name in tls-auth tls-platform tls-cortex tls-agentic tls-agentic-realtime tls-analytics tls-marimo-sidecar; do
kubectl create secret tls "$name" \
--cert=path/to/corporate-wildcard-or-host-cert.crt \
--key=path/to/corporate-key.key \
-n scrydon-platform
doneIf you also want Traefik to have a fallback certificate for routes that do not specify a TLS secret, configure its default TLSStore:
apiVersion: traefik.io/v1alpha1
kind: TLSStore
metadata:
name: default
namespace: traefik
spec:
defaultCertificate:
secretName: traefik-public-tlsCreate that traefik-public-tls Secret in the traefik namespace if you use this fallback.
Client trust requirement
Private CA certificates are not trusted by browsers or API clients automatically. Every user device, server, and automation that connects to Scrydon's public endpoint must trust the issuing root or intermediate CA.
Distribute the corporate root CA through your normal device management channel, such as MDM, Active Directory Group Policy, Jamf, Intune, or your Linux base image. Without that root installed, clients will see certificate authority errors even when Traefik is configured correctly.
Verify
kubectl get ingress -A
kubectl get certificate -A
kubectl -n scrydon-platform get secret tls-frontdoor
openssl s_client -connect app.example.com:443 -servername app.example.com </dev/nullCheck that the presented certificate's subject/SAN covers the public hostname and that its issuer chains to a CA trusted by your clients.