Scrydon
DeploymentReference

TLS Certificates

Choose and install certificates for Scrydon's public edge, private domains, and Traefik-backed Kubernetes routing.

Scrydon exposes browser and API traffic through Kubernetes Gateway API objects — one Gateway and one HTTPRoute per enabled app. The chart defaults to the traefik GatewayClass and stamps cert-manager.io/cluster-issuer: letsencrypt-prod on the Gateway, but certificate ownership depends on where TLS terminates.

Choose your path

Your setupCertificate path
Public hostname reaches Traefik directlyUse cert-manager with Let's Encrypt. The TLS prerequisite shows the default ClusterIssuer.
Publicly delegated domain, but private ingressUse Let's Encrypt DNS-01 with a DNS provider solver.
Private-only hostnameUse an internal ACME CA or a static corporate certificate.
Upstream load balancer terminates TLSInstall the public certificate on the load balancer, then configure TLS Offloading.
Upstream load balancer re-encrypts, or clients reach Traefik directly over HTTPSGive Traefik a certificate for the public hostname.

Certificate responsibilities

LegWhat needs a certificateDefault Scrydon behavior
Client to TraefikThe 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 Gateway's https listener references tls-frontdoor. In subdomain mode the Gateway gets one HTTPS listener per enabled app, referencing tls-auth, tls-platform, tls-cortex, tls-agentic, tls-agentic-realtime, and tls-analytics as needed. Every one of those Secrets is read from the Gateway's own namespace (scrydon-platform), even in a split-namespace install. Marimo stays on the authenticated Analytics origin and needs no separate certificate.
Traefik to workloadsNo public certificate by default. Traefik routes to the app Services over the cluster network.The chart's HTTPRoute backendRefs target each app Service's HTTP port. Service-to-service traffic between Scrydon workloads is protected separately by Dapr mTLS with SPIFFE identity.

Keep gateway.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 shapeLet's Encrypt fit
app.example.com, where example.com is publicly registered and you can create public DNS TXT recordsWorks. 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 DNSDoes 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:
          gatewayHTTPRoute:
            parentRefs:
              - kind: Gateway
                name: gateway-frontdoor
                namespace: scrydon-platform

Then use that issuer in your Scrydon values:

gateway:
  tls:
    enabled: true
    clusterIssuer: internal-acme-issuer
routing:
  host: app.yourcompany.local

cert-manager populates tls-frontdoor in the platform namespace, where the Gateway lives. There is only ever one certificate request per hostname, in both routing modes and whether or not you split namespaces — the chart carries a single cert-manager.io/cluster-issuer annotation on the Gateway, and cert-manager groups listeners by certificate Secret.

This requires cert-manager's Gateway API support (config.enableGatewayAPI=true); see TLS prerequisites.

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 Gateway listeners reference. Set gateway.tls.certManager.enabled: false so cert-manager does not race your certificate with an ACME order, or point every listener at one Secret with gateway.tls.existingSecret.

For default subpath routing:

kubectl create secret tls tls-frontdoor \
  --cert=path/to/corporate-cert.crt \
  --key=path/to/corporate-key.key \
  -n scrydon-platform

Keep that Secret in scrydon-platform even when you override namespaces.agentic, namespaces.analytics, or namespaces.cortex. The Gateway owns every listener, so certificateRefs are resolved from the Gateway's namespace only — there is nothing to copy into the other namespaces, on any implementation.

For subdomain routing, create the per-app secrets in the Gateway's namespace as well — the listeners all live on the one Gateway:

for name in tls-auth tls-platform tls-cortex tls-agentic tls-agentic-realtime tls-analytics; do
  kubectl create secret tls "$name" \
    --cert=path/to/corporate-wildcard-or-host-cert.crt \
    --key=path/to/corporate-key.key \
    -n scrydon-platform
done

If you also want Traefik to have a fallback certificate for hostnames the Gateway's listeners do not cover, configure its default TLSStore:

apiVersion: traefik.io/v1alpha1
kind: TLSStore
metadata:
  name: default
  namespace: traefik
spec:
  defaultCertificate:
    secretName: traefik-public-tls

Create 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 gateway -n scrydon-platform
kubectl describe gateway gateway-frontdoor -n scrydon-platform   # one condition block per listener
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/null

Check that the presented certificate's subject/SAN covers the public hostname and that its issuer chains to a CA trusted by your clients.

On this page

On this page