The cal route had redirect without backend, which the config parser requires. Pingora was in CrashLoopBackOff, taking down all services.
423 lines
14 KiB
YAML
423 lines
14 KiB
YAML
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: pingora-config
|
|
namespace: ingress
|
|
data:
|
|
config.toml: |
|
|
# Sunbeam proxy config.
|
|
#
|
|
# Substitution placeholders (replaced by sed at deploy time):
|
|
# DOMAIN_SUFFIX — e.g. <LIMA_IP>.sslip.io (local) or yourdomain.com (production)
|
|
|
|
[listen]
|
|
http = "0.0.0.0:80"
|
|
https = "0.0.0.0:443"
|
|
|
|
[tls]
|
|
# Cert files are written here by the proxy on startup and on cert renewal
|
|
# via the K8s API. The /etc/tls directory is an emptyDir volume.
|
|
cert_path = "/etc/tls/tls.crt"
|
|
key_path = "/etc/tls/tls.key"
|
|
|
|
[telemetry]
|
|
# OTLP traces → Alloy → Tempo. Requires proxy build with the
|
|
# dedicated Tokio runtime in telemetry::init(). To enable:
|
|
# 1. sunbeam build proxy --push
|
|
# 2. sunbeam k8s exec on server: sudo crictl pull src.sunbeam.pt/studio/proxy:latest
|
|
# (pull the new image WHILE Pingora is still running the old one)
|
|
# 3. Set otlp_endpoint below and sunbeam apply ingress
|
|
# NEVER delete the cached image — Pingora gates the registry.
|
|
otlp_endpoint = ""
|
|
metrics_port = 9090
|
|
|
|
# Kubernetes resource names for cert/config watchers.
|
|
# Override these if your namespace or Secret/ConfigMap names differ.
|
|
[kubernetes]
|
|
namespace = "ingress"
|
|
tls_secret = "pingora-tls"
|
|
config_configmap = "pingora-config"
|
|
|
|
# DDoS detection — decision tree + MLP ensemble (compiled-in weights).
|
|
[ddos]
|
|
enabled = true
|
|
observe_only = true
|
|
threshold = 0.6
|
|
window_secs = 60
|
|
window_capacity = 1000
|
|
min_events = 10
|
|
|
|
# Scanner detection — decision tree + MLP ensemble (compiled-in weights).
|
|
[scanner]
|
|
enabled = true
|
|
observe_only = true
|
|
threshold = 0.5
|
|
bot_cache_ttl_secs = 86400
|
|
|
|
[[scanner.allowlist]]
|
|
ua_prefix = "Googlebot"
|
|
reason = "Google crawler"
|
|
dns_suffixes = ["googlebot.com", "google.com"]
|
|
cidrs = ["66.249.64.0/19"]
|
|
|
|
[[scanner.allowlist]]
|
|
ua_prefix = "Bingbot"
|
|
reason = "Microsoft crawler"
|
|
dns_suffixes = ["search.msn.com"]
|
|
cidrs = ["40.77.167.0/24", "157.55.39.0/24"]
|
|
|
|
[[scanner.allowlist]]
|
|
ua_prefix = "containerd"
|
|
reason = "Container registry client (buildkitd/containerd)"
|
|
|
|
# Rate limiting — leaky bucket per-identity throttling.
|
|
[rate_limit]
|
|
enabled = true
|
|
eviction_interval_secs = 300
|
|
stale_after_secs = 600
|
|
bypass_cidrs = ["10.0.0.0/8", "127.0.0.0/8", "::1/128"]
|
|
|
|
[rate_limit.authenticated]
|
|
burst = 200
|
|
rate = 50.0
|
|
|
|
[rate_limit.unauthenticated]
|
|
burst = 50
|
|
rate = 10.0
|
|
|
|
# Host-prefix → backend routing table.
|
|
# The prefix is the subdomain before the first dot, so these routes work
|
|
# identically for yourdomain.com and *.sslip.io.
|
|
# Edit to match your own service names and namespaces.
|
|
#
|
|
# Per-route options:
|
|
# host_prefix — subdomain to match (required)
|
|
# backend — upstream URL, e.g. "http://svc.ns.svc.cluster.local:8000" (required)
|
|
# websocket — proxy WebSocket upgrades (default: false)
|
|
# disable_secure_redirection — when true, plain-HTTP requests are forwarded
|
|
# as-is instead of being 301-redirected to HTTPS.
|
|
# Default: false (all HTTP → HTTPS redirect enforced).
|
|
|
|
[[routes]]
|
|
host_prefix = "docs"
|
|
backend = "http://collabora.lasuite.svc.cluster.local:9980"
|
|
websocket = true
|
|
|
|
[[routes]]
|
|
host_prefix = "meet"
|
|
backend = "http://meet-frontend.lasuite.svc.cluster.local:80"
|
|
websocket = true
|
|
|
|
[[routes.paths]]
|
|
prefix = "/api/"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/admin/"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/oidc/"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/external-api/"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/static/"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/__"
|
|
backend = "http://meet-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes]]
|
|
host_prefix = "drive"
|
|
backend = "http://drive-frontend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/api/"
|
|
backend = "http://drive-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/admin/"
|
|
backend = "http://drive-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/static/"
|
|
backend = "http://drive-backend.lasuite.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/external_api/"
|
|
backend = "http://drive-backend.lasuite.svc.cluster.local:80"
|
|
# /media/ falls through to frontend nginx which handles auth_request internally
|
|
|
|
[[routes]]
|
|
host_prefix = "mail"
|
|
backend = "http://bulwark.stalwart.svc.cluster.local:80"
|
|
|
|
# JMAP protocol (Bulwark ↔ Stalwart)
|
|
[[routes.paths]]
|
|
prefix = "/jmap"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
# Well-known service discovery (autoconfig, caldav, carddav, etc.)
|
|
[[routes.paths]]
|
|
prefix = "/.well-known/"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
# Stalwart OAuth2 endpoints (/authorize/code, /auth/token, /auth/device)
|
|
[[routes.paths]]
|
|
prefix = "/authorize"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/auth/"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
# Stalwart login page (used during OAuth flow)
|
|
[[routes.paths]]
|
|
prefix = "/login"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
[[routes]]
|
|
host_prefix = "messages"
|
|
backend = "http://tuwunel.matrix.svc.cluster.local:6167"
|
|
websocket = true
|
|
|
|
# Serve .well-known from tuwunel directly
|
|
[[routes.paths]]
|
|
prefix = "/.well-known/matrix"
|
|
backend = "http://tuwunel.matrix.svc.cluster.local:6167"
|
|
|
|
[[routes]]
|
|
host_prefix = "find"
|
|
backend = "http://find-backend.lasuite.svc.cluster.local:8000"
|
|
|
|
[[routes]]
|
|
host_prefix = "design"
|
|
backend = "http://beam-design.devtools.svc.cluster.local:80"
|
|
|
|
[[routes]]
|
|
host_prefix = "designer"
|
|
backend = "http://penpot-frontend.devtools.svc.cluster.local:8080"
|
|
websocket = true
|
|
|
|
[[routes]]
|
|
host_prefix = "mcp-designer"
|
|
backend = "http://penpot-mcp.devtools.svc.cluster.local:4400"
|
|
websocket = true
|
|
timeout_secs = 86400
|
|
|
|
[[routes.paths]]
|
|
prefix = "/mcp"
|
|
backend = "http://penpot-mcp.devtools.svc.cluster.local:4401"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/sse"
|
|
backend = "http://penpot-mcp.devtools.svc.cluster.local:4401"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/ws"
|
|
backend = "http://penpot-mcp.devtools.svc.cluster.local:4402"
|
|
timeout_secs = 86400
|
|
|
|
[[routes]]
|
|
host_prefix = "src"
|
|
backend = "http://gitea-http.devtools.svc.cluster.local:3000"
|
|
websocket = true
|
|
|
|
# auth: unified IAM dashboard; Hydra handles OAuth2/OIDC; Kratos handles self-service flows.
|
|
[[routes]]
|
|
host_prefix = "auth"
|
|
backend = "http://kratos-admin-ui.ory.svc.cluster.local:3000"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/oauth2"
|
|
backend = "http://hydra-public.ory.svc.cluster.local:4444"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/.well-known"
|
|
backend = "http://hydra-public.ory.svc.cluster.local:4444"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/userinfo"
|
|
backend = "http://hydra-public.ory.svc.cluster.local:4444"
|
|
|
|
# /kratos prefix is stripped before forwarding so Kratos sees its native paths.
|
|
[[routes.paths]]
|
|
prefix = "/kratos"
|
|
backend = "http://kratos-public.ory.svc.cluster.local:80"
|
|
strip_prefix = true
|
|
|
|
[[routes]]
|
|
host_prefix = "integration"
|
|
backend = "http://integration.lasuite.svc.cluster.local:80"
|
|
|
|
|
|
[[routes]]
|
|
host_prefix = "metrics"
|
|
backend = "http://kube-prometheus-stack-grafana.monitoring.svc.cluster.local:80"
|
|
|
|
# Observability APIs — gated behind OIDC auth_request.
|
|
[[routes]]
|
|
host_prefix = "systemmetrics"
|
|
backend = "http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090"
|
|
auth_request = "http://kratos-public.ory.svc.cluster.local/sessions/whoami"
|
|
|
|
[[routes]]
|
|
host_prefix = "systemlogs"
|
|
backend = "http://loki-gateway.monitoring.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://loki-gateway.monitoring.svc.cluster.local:80"
|
|
auth_request = "http://kratos-public.ory.svc.cluster.local/sessions/whoami"
|
|
|
|
[[routes]]
|
|
host_prefix = "systemtracing"
|
|
backend = "http://tempo.monitoring.svc.cluster.local:3200"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://tempo.monitoring.svc.cluster.local:3200"
|
|
auth_request = "http://kratos-public.ory.svc.cluster.local/sessions/whoami"
|
|
|
|
[[routes]]
|
|
host_prefix = "livekit"
|
|
backend = "http://livekit-server.media.svc.cluster.local:80"
|
|
websocket = true
|
|
|
|
# lk-jwt-service: Element Call token exchange (MSC4143)
|
|
[[routes.paths]]
|
|
prefix = "/sfu/get"
|
|
backend = "http://lk-jwt-service.media.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/healthz"
|
|
backend = "http://lk-jwt-service.media.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/get_token"
|
|
backend = "http://lk-jwt-service.media.svc.cluster.local:80"
|
|
|
|
[[routes]]
|
|
host_prefix = "cal"
|
|
# Default: redirect to unified Bulwark calendar UI.
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
redirect = "https://mail.DOMAIN_SUFFIX/calendar"
|
|
|
|
# CalDAV protocol — external calendar clients connect here.
|
|
[[routes.paths]]
|
|
prefix = "/caldav"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/.well-known/caldav"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/.well-known/carddav"
|
|
backend = "http://stalwart.stalwart.svc.cluster.local:8080"
|
|
|
|
[[routes]]
|
|
host_prefix = "projects"
|
|
backend = "http://projects.lasuite.svc.cluster.local:80"
|
|
websocket = true
|
|
|
|
[[routes]]
|
|
host_prefix = "s3"
|
|
backend = "http://seaweedfs-filer.storage.svc.cluster.local:8333"
|
|
|
|
# Admin APIs — gated behind OIDC auth_request (Hydra userinfo validates the SSO bearer token).
|
|
# CLI passes the token from `sunbeam auth sso` as Authorization: Bearer.
|
|
|
|
# Kratos admin API (identity, session, recovery, schema, courier management).
|
|
[[routes]]
|
|
host_prefix = "id"
|
|
backend = "http://kratos-admin.ory.svc.cluster.local:80"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://kratos-admin.ory.svc.cluster.local:80"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
# Hydra admin API (OAuth2 client, JWK, issuer, token management).
|
|
# Exposed as a path under auth.{domain} alongside the existing public endpoints.
|
|
[[routes]]
|
|
host_prefix = "hydra"
|
|
backend = "http://hydra-admin.ory.svc.cluster.local:4445"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://hydra-admin.ory.svc.cluster.local:4445"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
# OpenSearch admin API (document, index, cluster management).
|
|
[[routes]]
|
|
host_prefix = "search"
|
|
backend = "http://opensearch.data.svc.cluster.local:9200"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://opensearch.data.svc.cluster.local:9200"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
# OpenBao/Vault API (secrets, policies, auth management).
|
|
[[routes]]
|
|
host_prefix = "vault"
|
|
backend = "http://openbao.data.svc.cluster.local:8200"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/"
|
|
backend = "http://openbao.data.svc.cluster.local:8200"
|
|
auth_request = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
|
|
|
|
[[routes]]
|
|
host_prefix = "call"
|
|
backend = "http://element-call.media.svc.cluster.local:80"
|
|
|
|
# Bare domain (sunbeam.pt) — serves .well-known/matrix delegation only.
|
|
# The proxy splits on '.', so sunbeam.pt yields prefix "sunbeam".
|
|
[[routes]]
|
|
host_prefix = "sunbeam"
|
|
backend = "http://tuwunel.matrix.svc.cluster.local:6167"
|
|
|
|
[[routes.paths]]
|
|
prefix = "/.well-known/matrix"
|
|
backend = "http://tuwunel.matrix.svc.cluster.local:6167"
|
|
|
|
# TLS passthrough: SNI-routed connections relayed without TLS termination.
|
|
# BuildKit uses mTLS (client certs) so Pingora can't terminate — it peeks
|
|
# the ClientHello SNI and relays the raw TCP stream to the backend.
|
|
[[tls_passthrough]]
|
|
host_prefix = "build"
|
|
backend = "buildkitd.build.svc.cluster.local:1234"
|
|
|
|
# SMTP inbound: port 25 → Stalwart for mail delivery.
|
|
[smtp]
|
|
listen = "0.0.0.0:25"
|
|
backend = "stalwart.stalwart.svc.cluster.local:25"
|
|
|
|
# SMTP submission: port 587 → Stalwart for authenticated sending.
|
|
[smtp-submission]
|
|
listen = "0.0.0.0:587"
|
|
backend = "stalwart.stalwart.svc.cluster.local:587"
|
|
|
|
# IMAPS: port 993 → Stalwart for desktop/mobile email clients.
|
|
[imaps]
|
|
listen = "0.0.0.0:993"
|
|
backend = "stalwart.stalwart.svc.cluster.local:993"
|
|
|
|
# SSH TCP passthrough: port 22 → Gitea SSH pod (headless service → pod:2222).
|
|
[ssh]
|
|
listen = "0.0.0.0:22"
|
|
backend = "gitea-ssh.devtools.svc.cluster.local:2222"
|