Scrydon
DeploymentReference

Routing Modes — Subpath vs Subdomain

Choose whether Scrydon's browser-facing apps share one hostname or use one hostname per app.

Scrydon's browser-facing apps support two deployment-time routing modes. The same application images serve both modes; routing.mode selects the public URLs, base paths, Ingress objects, cookies, and CORS configuration.

Subpath (subpath, default)Subdomain (subdomain)
Example URLsapp.example.com/cortex
app.example.com/analytics
cortex.example.com
analytics.example.com
DNSOne A recordOne wildcard or one A record per app
TLSOne host certificateOne wildcard or one certificate per app
IngressOne per distinct workload namespace (ingress-frontdoor when collapsed)One Ingress per enabled browser/realtime app
CookiesHost-scopedShared registrable domain
CORSOne public originOne public origin per app
Best fitCustomer and on-premises installsSaaS or independent app domains

Use the default subpath mode unless you need separate DNS, TLS, or SSO policy per app.

How base paths work

The chart resolves each application's prefix and injects BASE_PATH. The app mounts routes and assets below that prefix, injects the value into client code, and configures TanStack Router with the same base path. API services follow the same rule.

Ingress-only strip-prefix rewriting is insufficient because server-rendered pages and hashed assets need an application-aware public base path. No rebuild is required when changing modes.

Subpath quick start

routing:
  mode: subpath
  host: app.example.com
  # paths:
  #   cortex: /cortex
  #   agentic: /agentic
  #   analytics: /analytics
  #   platform: /platform
  #   apiAuth: /api/auth
  #   apiOntology: /api/ontology
  #   apiTable: /api/table
  #   agenticRealtime: /agentic/realtime

Create one A record for app.example.com. With TLS enabled, the chart references tls-frontdoor and renders one ingress-frontdoor containing the enabled app and API paths.

Subdomain quick start

routing:
  mode: subdomain

auth:
  publicUrl: https://auth.example.com
  ingress: { hostname: auth.example.com }
  corsOrigins:
    - https://app.example.com
    - https://cortex.example.com
    - https://agentic.example.com
    - https://ws-agentic.example.com
    - https://analytics.example.com

platform:
  publicUrl: https://app.example.com
  ingress: { hostname: app.example.com }

cortex:
  publicUrl: https://cortex.example.com
  ingress: { hostname: cortex.example.com }

agentic:
  publicUrl: https://agentic.example.com
  publicSocketUrl: https://ws-agentic.example.com
  app:
    ingress: { hostname: agentic.example.com }
  realtime:
    ingress:
      hostname: ws-agentic.example.com
      annotations:
        traefik.ingress.kubernetes.io/service.sticky.cookie: "true"
        traefik.ingress.kubernetes.io/service.sticky.cookie.name: scrydon_realtime_affinity
        traefik.ingress.kubernetes.io/service.sticky.cookie.secure: "true"
        traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: "true"

analytics:
  publicUrl: https://analytics.example.com
  ingress: { hostname: analytics.example.com }

Create an A record per host, or use a wildcard. Each enabled app Ingress references its corresponding TLS secret. Cross-subdomain sessions require every public URL to share the same registrable domain.

Marimo notebooks

Marimo does not have a public host, path, Ingress, or TLS secret. The notebook document, Connect request, cell Run request, HTTP proxying, and WebSocket proxying all stay on the authenticated Analytics origin:

  • subpath: https://app.example.com/analytics/notebooks/...
  • subdomain: https://analytics.example.com/notebooks/...

The stateless document renderer and isolated runtimes are private cluster services. Do not create a marimo.example.com DNS record or expose runtime ports directly.

DNS and TLS

For issuer choices, private domains, and corporate certificates, see TLS Certificates.

Subpath requires only:

app.example.com  A  <ingress load-balancer IP>

Subdomain commonly requires:

app.example.com         A  <ingress load-balancer IP>
cortex.example.com      A  <ingress load-balancer IP>
agentic.example.com     A  <ingress load-balancer IP>
ws-agentic.example.com  A  <ingress load-balancer IP>
analytics.example.com   A  <ingress load-balancer IP>
auth.example.com        A  <ingress load-balancer IP>

Switching a live deployment

  1. Provision the target DNS records and certificates.
  2. Change routing.mode and the matching host/public URL values.
  3. Upgrade the same chart version with your values file.
  4. Verify Ingresses, certificates, app health, sign-in, and WebSocket routes.
  5. Cut over DNS. Users may need to sign in again because cookie scope changed.
helm upgrade scrydon oci://scrydonops.azurecr.io/scrydon/charts/scrydon \
  --version "${CURRENT_VERSION}" \
  --namespace scrydon-platform \
  -f values.customer.yaml \
  --wait

# Subpath: one shared-host Ingress per distinct workload namespace
kubectl get ingress -A

# Subdomain: one Ingress per enabled public app
kubectl get ingress -A

Changing the mode back and upgrading performs the routing rollback. It does not affect notebook runtime isolation because Marimo remains behind Analytics in both modes.

Multiple namespaces

An Ingress can reference only Services in its own namespace. In subpath mode the chart therefore renders one front-door Ingress per distinct application namespace. Every resource uses the same routing.host, and each contains only the paths whose Services are local to that namespace. A collapsed install still renders only ingress-frontdoor in scrydon-platform.

When TLS is enabled, tls-frontdoor (or ingress.tls.existingSecret) must exist in every namespace that receives a front-door Ingress. cert-manager creates those namespace-local copies when enabled; static-certificate operators must copy the Secret themselves.

On this page

On this page