# Traefik Ingress — canonical path-based routing for researchstack.info # # This is the single source of truth for URL → service mapping inside k3s. # The public edge Caddy terminates TLS and forwards to Traefik's entrypoint. # Traefik handles path routing, prefix stripping, and forward-auth. # # Middleware annotation format: -@kubernetescrd # # Split into per-route Ingresses so each gets its own middleware chain: # - /apps/*, /server/* → forward_auth (Authentik) + strip-prefix # - /api/* → strip-prefix only (token-auth, no SSO) # - / → forward_auth (Authentik), no strip # - auth.* → no middleware (Authentik itself) # ═══════════════════════════════════════════════════════════════════════════ # /apps/chat/* → Hermes (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-apps-chat namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-apps-chat@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /apps/chat pathType: Prefix backend: service: name: hermes port: number: 80 # ═══════════════════════════════════════════════════════════════════════════ # /apps/budget/* → Actual Budget (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-apps-budget namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-apps-budget@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /apps/budget pathType: Prefix backend: service: name: actual-budget port: number: 5006 # ═══════════════════════════════════════════════════════════════════════════ # /apps/books/* → Audiobookshelf (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-apps-books namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-apps-books@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /apps/books pathType: Prefix backend: service: name: audiobookshelf port: number: 80 --- # ═══════════════════════════════════════════════════════════════════════════ # /server/status/* → Uptime Kuma (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-server-status namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-server-status@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /server/status pathType: Prefix backend: service: name: uptime-kuma port: number: 3001 # ═══════════════════════════════════════════════════════════════════════════ # /server/dash/* → Homarr (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-server-dash namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-server-dash@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /server/dash pathType: Prefix backend: service: name: homarr port: number: 7575 # ═══════════════════════════════════════════════════════════════════════════ # /server/vault/* → Vaultwarden (SSO-gated) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-server-vault namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd,services-strip-server-vault@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /server/vault pathType: Prefix backend: service: name: vaultwarden port: number: 80 # ═══════════════════════════════════════════════════════════════════════════ # /api/cred/* → Credential Server (token-auth, no SSO) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-api-cred namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-strip-api-cred@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /api/cred pathType: Prefix backend: service: name: credential-server port: number: 8444 # ═══════════════════════════════════════════════════════════════════════════ # /api/registry/* → Registry API (token-auth, no SSO) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-api-registry namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-strip-api-registry@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /api/registry pathType: Prefix backend: service: name: registry-api port: number: 8080 # ═══════════════════════════════════════════════════════════════════════════ # /api/jobs/* → Job Router (token-auth, no SSO) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-api-jobs namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-strip-api-jobs@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /api/jobs pathType: Prefix backend: service: name: jobs-api port: number: 8080 # ═══════════════════════════════════════════════════════════════════════════ # /api/blobs/* → Blob Plane (token-auth, no SSO) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-api-blobs namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-strip-api-blobs@kubernetescrd spec: rules: - host: researchstack.info http: paths: - path: /api/blobs pathType: Prefix backend: service: name: blobs-api port: number: 8080 # ═══════════════════════════════════════════════════════════════════════════ # / → Homer landing page (SSO-gated, no strip) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-landing namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: services-authentik-forward-auth@kubernetescrd traefik.ingress.kubernetes.io/router.priority: "1" spec: rules: - host: researchstack.info http: paths: - path: / pathType: Prefix backend: service: name: homer port: number: 8080 # ═══════════════════════════════════════════════════════════════════════════ # auth.researchstack.info → Authentik (stable OIDC issuer, no middleware) # ═══════════════════════════════════════════════════════════════════════════ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rs-auth namespace: services annotations: traefik.ingress.kubernetes.io/router.entrypoints: web spec: rules: - host: auth.researchstack.info http: paths: - path: / pathType: Prefix backend: service: name: authentik-server port: number: 80