diff --git a/.idea/runConfigurations/pytest_all.xml b/.idea/runConfigurations/pytest_all.xml
index 6bf0f13..f2829fa 100644
--- a/.idea/runConfigurations/pytest_all.xml
+++ b/.idea/runConfigurations/pytest_all.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/.idea/runConfigurations/pytest_gke.xml b/.idea/runConfigurations/pytest_gke.xml
index 858be99..491ca9c 100644
--- a/.idea/runConfigurations/pytest_gke.xml
+++ b/.idea/runConfigurations/pytest_gke.xml
@@ -1,17 +1,22 @@
+
+
+
+
+
@@ -21,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/pytest_k3d.xml b/.idea/runConfigurations/pytest_k3d.xml
index d94d551..4034f14 100644
--- a/.idea/runConfigurations/pytest_k3d.xml
+++ b/.idea/runConfigurations/pytest_k3d.xml
@@ -1,17 +1,22 @@
+
+
+
+
+
@@ -21,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/pytest_min.xml b/.idea/runConfigurations/pytest_min.xml
index 12e00f6..8383115 100644
--- a/.idea/runConfigurations/pytest_min.xml
+++ b/.idea/runConfigurations/pytest_min.xml
@@ -1,17 +1,22 @@
+
+
+
+
+
@@ -21,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/pytest_unit.xml b/.idea/runConfigurations/pytest_unit.xml
index c0f7d1f..56f12e8 100644
--- a/.idea/runConfigurations/pytest_unit.xml
+++ b/.idea/runConfigurations/pytest_unit.xml
@@ -1,16 +1,21 @@
+
+
+
+
+
@@ -20,4 +25,4 @@
-
+
\ No newline at end of file
diff --git a/conf/k3d.cfg b/conf/k3d.cfg
index 7626709..c41c86a 100644
--- a/conf/k3d.cfg
+++ b/conf/k3d.cfg
@@ -1,5 +1,5 @@
; Knoe Master Configuration File
-; Generated by install.py on 2026-05-03 19:40:53
+; Generated by install.py on 2026-05-04 02:15:57
; This file is used as input for Ansible deployment and k8s cluster creation.
[User]
@@ -53,7 +53,7 @@ env_setup.PROLE_DATA = /Users/chrisfu/dev/prole/data
env_setup.PROLE_LOGS = /Users/chrisfu/dev/prole/logs
gitops.git_provider = Gitea
gitops.node_selector =
-init_cluster.argocd_enabled = false
+init_cluster.argocd_enabled = true
init_cluster.at_rest_encryption_enabled = true
init_cluster.cluster_env = dev
init_cluster.deployment_target = knoe-dev-cluster
@@ -70,26 +70,27 @@ init_db_build.run_build = true
init_password.cluster_name = ${CLUSTER_NAME}
init_password.db_host_port = 5432
init_password.db_namespace = ${DATABASE_NAMESPACE}
-init_password.db_password = ${KNOE_SECRET:v1:dZtt1snkOcvvfKLT:InElcG1YzL86l6ZPP03cf9Zx07Tq5-qt}
-init_password.db_password_confirm = ${KNOE_SECRET:v1:dZtt1snkOcvvfKLT:InElcG1YzL86l6ZPP03cf9Zx07Tq5-qt}
-init_password.db_username = chrisfu
+init_password.db_password = ${KNOE_SECRET:v1:v00gnU0lZjZUF__L:3tlFaJnbjpK1_Ufggmfp8T91VSuq1uMO}
+init_password.db_password_confirm = ${KNOE_SECRET:v1:v00gnU0lZjZUF__L:3tlFaJnbjpK1_Ufggmfp8T91VSuq1uMO}
+init_password.db_username = root
init_password.generate_ssh_key = true
init_scripts.run_scripts = true
kerberos_config.enabled = true
kerberos_config.kdc = 10.0.0.3
-kerberos_config.password = ${KNOE_SECRET:v1:FIPsTmrzljDXRhwf:Hfp05VmT2yAOJIUFoSG1utMJHMvNP7reGAkoXyvmIp_lAftCI6NyHSj0AqrHPI0Q}
+kerberos_config.password = ${KNOE_SECRET:v1:b3l7OBzEaKrOf04_:HQL8wPSazmkCgAjevoW0eNjsoOUkPi11OxZSQyOqvcD347WCoUKcztiyqubQwMj5}
kerberos_config.realm = PROLE.ORG
kerberos_config.test_connection = true
kerberos_config.user = administrator
network_scan.run = true
ollama_config.model =
-ollama_config.server_host = fairyland.prole.org
+ollama_config.server_host =
ollama_config.server_port = 11434
supabase_config.pv_base_dir = /synology/d005
supabase_config.pv_node =
[Global]
; Variables used by name in more than one place or assumed global scope
+ARGOCD_NAMESPACE = argocd
CLUSTER_ENV = dev
CLUSTER_NAME = knoe-db
CNPG_PLACEMENT_PLAN_FILE = /Users/chrisfu/dev/prole/conf/cnpg-placement/knoe-system-knoe-db.json
@@ -97,16 +98,21 @@ CNPG_PLACEMENT_PLAN_HASH = 965d2fde4035059f
CNPG_PLACEMENT_PLAN_ID = cnpg-placement-965d2fde4035059f
DATABASE_NAMESPACE = knoe-db
DB_HOST_PORT = 5432
-DB_PASSWORD = ${KNOE_SECRET:v1:LJJ4Y6WIqRMV5Pp6:UD3iURPdk8_3xDqlakAg0eY_81kppn4g}
+DB_PASSWORD = ${KNOE_SECRET:v1:UHU7cGaV3F206SiN:iWT-KbxciZyijyU2W3d_toKCoTRyCKfp}
DEPLOYMENT_MODE = k3d
DEPLOYMENT_TARGET = knoe-dev-cluster
DOCKER_PRELOAD = false
-KNOE_DB_USER = chrisfu
+K3S_SERVER = https://myrddin.prole.org:6443
+K3S_TOKEN = ${KNOE_SECRET:v1:-cslrAhG8WhxxJLY:vAx5MGOBcU1NBMjf4U-3y1djMDmwwOjiWkrutxPa4Li5P8RBjCBhEOCEdGP2CiPJJ6UQK-ietX-mu_5nO3yNNjpwDququT4U6lWHPEInSvUNH6ImU-HzPvm_diL2FwJtZm3sY5HgecIy2dwXB_vLnYaA_7VXt9zf0T70rw==}
+KNOE_DB_USER = root
KNOE_HOME = /Users/chrisfu/dev/prole
+KUBECONTEXT = k3d-knoe-dev-cluster
+OPENTOFU_URL = http://127.0.0.1:8080
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
PROLE_K3S_TOKEN = ${KNOE_SECRET:v1:-cslrAhG8WhxxJLY:vAx5MGOBcU1NBMjf4U-3y1djMDmwwOjiWkrutxPa4Li5P8RBjCBhEOCEdGP2CiPJJ6UQK-ietX-mu_5nO3yNNjpwDququT4U6lWHPEInSvUNH6ImU-HzPvm_diL2FwJtZm3sY5HgecIy2dwXB_vLnYaA_7VXt9zf0T70rw==}
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
+REGISTRY_NAMESPACE = knoe-system
SERVICE_NAMESPACE = knoe-system
SUPABASE_PV_BASE = /synology/d005
SUPABASE_PV_BASE_DIR = /synology/d005
@@ -115,7 +121,7 @@ SUPABASE_PV_BASE_DIR = /synology/d005
; No configuration values captured yet for this section.
[Dependencies]
-; No configuration values captured yet for this section.
+STATUS = All installed
[Network]
AD_DC_HOST = myrddin.prole.org
@@ -138,7 +144,7 @@ PROLE_DATA = $HOME/dev/prole/data
PROLE_LOGS = $HOME/dev/prole/logs
[Monitoring]
-GRAFANA_ADMIN_PASSWORD = ${KNOE_SECRET:v1:T80z8G4SXuY96xLZ:HFX0qAPJIOz7Fevc5m2Ml2YL8qmpbES3}
+GRAFANA_ADMIN_PASSWORD = ${KNOE_SECRET:v1:KjciJR7E96MaNboA:dLAYw8xx0bQt9qoh7CYqnbOUUCwFU4bY}
[Kerberos Authentication]
AD_PORT_FORWARD = 1
@@ -149,18 +155,17 @@ AD_TCP_PORTS = 88 389 445 464 636
AD_UDP_PORTS = 88 464
ENABLED = True
KDC = 10.0.0.3
-PASSWORD = ${KNOE_SECRET:v1:SwR1_S3KrYbGj7k8:Qi4fnGhMAaMetBAhql2FhskJgVVIvj3mcN3Po5TCk7JyZaVzDZuYEjwpPjevODjC}
+PASSWORD = ${KNOE_SECRET:v1:LRsb2eBOIlB3CksO:73aNgprchcwifxIEiaGBLLj-kZCpry1v34DADJIfUaA4ltfVQc2V6kvoBmznYBmH}
REALM = PROLE.ORG
SERVER = 10.0.0.3
+STATUS = Attempted
USER = administrator
[Ollama]
-OLLAMA_HOST = http://fairyland.prole.org:11434
OLLAMA_SERVERS = fairyland.prole.org:11434,k3d.localhost:11434,morgoth.prole.org:11434
-OLLAMA_SERVER_HOST = fairyland.prole.org
-OLLAMA_SERVER_PORT = 11434
[Optional Features]
+ARGOCD_ENABLED = True
AT_REST_ENCRYPTION_ENABLED = True
GITOPS_ENABLED = False
KERBEROS_ENABLED = True
@@ -170,7 +175,9 @@ SUPABASE_ENABLED = False
; No configuration values captured yet for this section.
[Database Creation]
-; No configuration values captured yet for this section.
+APP_CLUSTER_NAME = knoe-dev-0
+DB_CLUSTER_NAME = knoe-dev-cnpg-0
+DB_USER = root
[Initialize Cluster]
ENVIRONMENT = dev
@@ -180,6 +187,7 @@ K3S_TOKEN = ${KNOE_SECRET:v1:-cslrAhG8WhxxJLY:vAx5MGOBcU1NBMjf4U-3y1djMDmwwOjiWk
[Dev Cluster (k3d)]
CLUSTER_ENV = dev
DISPLAY_NAME = knoe-dev-cluster
+KUBECTL_CONTEXT = k3d-knoe-dev-cluster
MODE = k3d
[Service Cluster (k3s)]
@@ -191,7 +199,10 @@ MODE = k3s
PIPELINE_URL = http://127.0.0.1:8080
[GCP]
-; No configuration values captured yet for this section.
+BILLING_ACCOUNT = 01193C-25783B-3211AD
+BILLING_PROJECT = plenary-truck-485623-p7
+ORG_ID = 584001916389
+PROJECT_ID = plenary-truck-485623-p7
[Prod Cluster (k8s)]
ARTIFACTS_DIR = $HOME/dev/prole/data/staging
@@ -212,4 +223,4 @@ MODE = k3d
TARGET = knoe-dev-cluster
[Install]
-; No configuration values captured yet for this section.
+STATUS = Failed
diff --git a/conf/k3s.cfg b/conf/k3s.cfg
index ba0507f..0ac5438 100644
--- a/conf/k3s.cfg
+++ b/conf/k3s.cfg
@@ -143,18 +143,14 @@ DEPLOYMENT_MODE = k3s
DEPLOYMENT_TARGET = knoe-service-cluster
DOCKER_IMPORT_DIR =
DOCKER_PRELOAD = false
-GITEA_HOSTNAME = git-internal.prole.org
+GITEA_HOSTNAME = git.prole.org
GITEA_PV_NODE = gandalf.prole.org
-GITLAB_GITALY_STORAGE_CLASS = synology-iscsi
-GITLAB_PUBLIC_HOSTS = git.prole.org
-GITLAB_REPAIR_BLOCKED_AUTOCLEAN = 1
-GITLAB_STORAGE_NODE = merlin.prole.org
K3S_SERVER = https://myrddin.prole.org:6443
K3S_TOKEN = ${KNOE_SECRET:v1:-cslrAhG8WhxxJLY:vAx5MGOBcU1NBMjf4U-3y1djMDmwwOjiWkrutxPa4Li5P8RBjCBhEOCEdGP2CiPJJ6UQK-ietX-mu_5nO3yNNjpwDququT4U6lWHPEInSvUNH6ImU-HzPvm_diL2FwJtZm3sY5HgecIy2dwXB_vLnYaA_7VXt9zf0T70rw==}
KNOE_DB_USER = root
KNOE_HOME = $HOME/dev/knoe
KNOE_IMAGE_REGISTRY = registry.prole.org
-MONITORING_STORAGE_CLASS = local-path
+MONITORING_STORAGE_CLASS = merlin-local-iscsi-prometheus
OPENTOFU_URL = http://127.0.0.1:8080
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
@@ -208,7 +204,7 @@ PROLE_DATA = $HOME/dev/knoe/data
PROLE_LOGS = $HOME/dev/knoe/logs
[Monitoring]
-MONITORING_STORAGE_CLASS = local-path
+MONITORING_STORAGE_CLASS = merlin-local-iscsi-prometheus
[Kerberos Authentication]
STATUS = Initialized
diff --git a/conf/port-mapping.cfg b/conf/port-mapping.cfg
index 561f824..f879a37 100644
--- a/conf/port-mapping.cfg
+++ b/conf/port-mapping.cfg
@@ -1,9 +1,11 @@
# Port mappings for Knoe Tools (generated).
# Format: key: local=... remote=... ns=... svc=... address=...
+gitea-ssh: local=22 remote=22 ns=gitea svc=gitea-ssh address=0.0.0.0
garage: local=3900 remote=3900 ns=knoe-system svc=garage address=0.0.0.0
-openbao: local=8200 remote=8200 ns=knoe-system svc=openbao address=127.0.0.1
+openbao: local=8200 remote=8200 ns=knoe-system svc=openbao address=0.0.0.0
opentofu: local=8080 remote=8080 ns=knoe-system svc=opentofu address=0.0.0.0
postgres: local=5432 remote=5432 ns=knoe-db svc=knoe-db-rw address=0.0.0.0
prometheus: local=9090 remote=9090 ns=monitoring svc=prometheus-kube-prometheus-stack-prometheus address=127.0.0.1
grafana: local=3000 remote=80 ns=monitoring svc=prometheus-grafana address=0.0.0.0
+gitea-http: local=13000 remote=3000 ns=gitea svc=gitea-http address=0.0.0.0
diff --git a/deploy/opentofu/k3s/manifests/knoe/kong-configmap.yaml b/deploy/opentofu/k3s/manifests/knoe/kong-configmap.yaml
index db89b16..9d66df8 100644
--- a/deploy/opentofu/k3s/manifests/knoe/kong-configmap.yaml
+++ b/deploy/opentofu/k3s/manifests/knoe/kong-configmap.yaml
@@ -82,7 +82,7 @@ data:
routes:
- name: gitea-root
hosts:
- - git-internal.prole.org
+ - git.prole.org
paths:
- /
strip_path: false
diff --git a/deploy/opentofu/k3s/manifests/knoe/svc-knoe-ingress.yaml b/deploy/opentofu/k3s/manifests/knoe/svc-knoe-ingress.yaml
new file mode 100644
index 0000000..71bfb86
--- /dev/null
+++ b/deploy/opentofu/k3s/manifests/knoe/svc-knoe-ingress.yaml
@@ -0,0 +1,69 @@
+# svc-knoe-ingress.yaml
+# Traefik ingress for *.prole.org — routes all public domains through
+# knoe-svc-kong (declarative Kong in knoe-system). cert-manager issues a
+# Let's Encrypt cert (svc-prole-org-tls) for all hosts via HTTP-01.
+#
+# Kong routing (kong-configmap.yaml):
+# api.prole.org → knoe-auth.knoe-system:8080
+# db.prole.org → oauth2-proxy.supabase:4180 (Supabase Studio + Google gate)
+# svc.prole.org → knoe-grafana-proxy.monitoring:80 (Grafana)
+# git.prole.org → gitea-http.gitea:3000 (Gitea)
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: svc-knoe-ingress
+ namespace: knoe-system
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ kubernetes.io/ingress.class: traefik
+ traefik.ingress.kubernetes.io/router.priority: "10"
+spec:
+ rules:
+ - host: svc.prole.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: knoe-svc-kong
+ port:
+ number: 8000
+ - host: api.prole.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: knoe-svc-kong
+ port:
+ number: 8000
+ - host: db.prole.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: oauth2-proxy
+ port:
+ number: 80
+ - host: git.prole.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: knoe-svc-kong
+ port:
+ number: 8000
+ tls:
+ - hosts:
+ - svc.prole.org
+ - api.prole.org
+ - db.prole.org
+ - git.prole.org
+ secretName: svc-prole-org-tls
diff --git a/env.sh b/env.sh
index cc498c1..c31ea6a 100755
--- a/env.sh
+++ b/env.sh
@@ -4,10 +4,10 @@
# "$KNOE_HOME/env.sh" [args…]
# shellcheck shell=bash
export KNOE_HOME="$HOME/dev/prole"
-export KNOE_CONF="$HOME/dev/prole/conf"
-export PROLE_DATA="$HOME/dev/prole/data"
-export PROLE_LOGS="$HOME/dev/prole/logs"
-export KNOE_SERVICE="$HOME/dev/prole/etc"
+export KNOE_CONF="$KNOE_HOME/conf"
+export PROLE_DATA="$KNOE_HOME/data"
+export PROLE_LOGS="$KNOE_HOME/logs"
+export KNOE_SERVICE="$KNOE_HOME/etc"
# Ensure PATH works for GUI-launched shells (Docker, etc.)
_knoe_add_path() { case ":${PATH}:" in *":$1:"*) ;; *) PATH="$1:${PATH:-}" ;; esac; }
diff --git a/etc/init_grafana_oauth_prole.sh b/etc/init_grafana_oauth_prole.sh
old mode 100755
new mode 100644
diff --git a/etc/init_oauth2_proxy_prole.sh b/etc/init_oauth2_proxy_prole.sh
old mode 100755
new mode 100644
diff --git a/infrastructure/inventory/group_vars/all/dns.yml b/infrastructure/inventory/group_vars/all/dns.yml
index 6c467f5..9b1e453 100644
--- a/infrastructure/inventory/group_vars/all/dns.yml
+++ b/infrastructure/inventory/group_vars/all/dns.yml
@@ -111,6 +111,11 @@ prole_dns_records:
value: 10.0.0.207
ttl: 300
+ - name: git
+ type: A
+ value: 73.15.20.166
+ ttl: 300
+
- name: svc
type: A
value: 73.15.20.166
diff --git a/modes/k3d/knoe-db/.version b/modes/k3d/knoe-db/.version
index dec2bf5..410b14d 100644
--- a/modes/k3d/knoe-db/.version
+++ b/modes/k3d/knoe-db/.version
@@ -1 +1 @@
-19
\ No newline at end of file
+25
\ No newline at end of file
diff --git a/supabase/helm/generated/manifest-summary.json b/supabase/helm/generated/manifest-summary.json
index 4fac2ad..0818283 100644
--- a/supabase/helm/generated/manifest-summary.json
+++ b/supabase/helm/generated/manifest-summary.json
@@ -1,10 +1,10 @@
{
- "values": "/Users/chrisfu/dev/knoe/supabase/helm/generated/values.generated.json",
- "manifests": "/Users/chrisfu/dev/knoe/supabase/k8s/supabase-helm.yaml",
- "manifests_app": "/Users/chrisfu/dev/knoe/supabase/helm/generated/supabase-helm.app.yaml",
- "manifests_frontdoor_db": "/Users/chrisfu/dev/knoe/supabase/helm/generated/supabase-helm.frontdoor-db.yaml",
- "manifests_public_ingress_tls": "/Users/chrisfu/dev/knoe/supabase/k8s/public-ingress-tls.yaml",
- "manifests_public_ingress_kong": "/Users/chrisfu/dev/knoe/supabase/k8s/public-ingress-kong.yaml",
- "db_host": "10.180.15.236",
+ "values": "/Users/chrisfu/dev/prole/supabase/helm/generated/values.generated.json",
+ "manifests": "/Users/chrisfu/dev/prole/supabase/k8s/supabase-helm.yaml",
+ "manifests_app": "/Users/chrisfu/dev/prole/supabase/helm/generated/supabase-helm.app.yaml",
+ "manifests_frontdoor_db": "/Users/chrisfu/dev/prole/supabase/helm/generated/supabase-helm.frontdoor-db.yaml",
+ "manifests_public_ingress_tls": "/Users/chrisfu/dev/prole/supabase/k8s/public-ingress-tls.yaml",
+ "manifests_public_ingress_kong": "/Users/chrisfu/dev/prole/supabase/k8s/public-ingress-kong.yaml",
+ "db_host": "knoe-db-rw.knoe-db.svc.cluster.local",
"supabase_namespace": "supabase"
}
\ No newline at end of file
diff --git a/supabase/helm/generated/supabase-helm.app.yaml b/supabase/helm/generated/supabase-helm.app.yaml
index d352d24..c874175 100644
--- a/supabase/helm/generated/supabase-helm.app.yaml
+++ b/supabase/helm/generated/supabase-helm.app.yaml
@@ -10,8 +10,6 @@
---
{"apiVersion": "v1", "kind": "ServiceAccount", "metadata": {"name": "supabase-meta", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}}
---
-{"apiVersion": "v1", "kind": "ServiceAccount", "metadata": {"name": "supabase-minio", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}}
----
{"apiVersion": "v1", "kind": "ServiceAccount", "metadata": {"name": "supabase-realtime", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}}
---
{"apiVersion": "v1", "kind": "ServiceAccount", "metadata": {"name": "supabase-rest", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}}
@@ -24,11 +22,11 @@
---
{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-analytics", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"privateAccessToken": "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXByaXZhdGU=", "publicAccessToken": "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXB1YmxpYw=="}}
---
-{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-dashboard", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"openAiApiKey": "a2V5X3N1cGVyX3NlY3JldA==", "password": "dGhpc19wYXNzd29yZF9pc19pbnNlY3VyZV9hbmRfc2hvdWxkX2JlX3VwZGF0ZWQ=", "username": "c3VwYWJhc2U="}}
+{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-openai", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"apiKey": "a2V5X3N1cGVyX3NlY3JldA=="}}
---
{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-db", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"database": "cG9zdGdyZXM=", "password": "dnp4LndDNEFrZDR4LURqNldndWg=", "password_encoded": "dnp4LndDNEFrZDR4LURqNldndWg="}}
---
-{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-jwt", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"anonKey": "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaVlXNXZiaUlzSW1semN5STZJbXR1YjJVdGMzVndZV0poYzJVaUxDSnBZWFFpT2pFM056WTRNamN3T0Rjc0ltVjRjQ0k2TWpBNU1qRTROekE0TjMwLkJFbHZWemJkZ05tbHRZV3VtcnhwaWg3RU9LeU5NeXdveWtPLVo2UUZUdHc=", "secret": "NGU1M2UxZWNiOThlYjMyZWU4M2I4OTBiZWE3OWU2NzhlOTUyYzZhZTIzN2VkZjNmNjVmMzdiZjZkZDIyNjJlYg==", "serviceKey": "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaWMyVnlkbWxqWlY5eWIyeGxJaXdpYVhOeklqb2lhMjV2WlMxemRYQmhZbUZ6WlNJc0ltbGhkQ0k2TVRjM05qZ3lOekE0Tnl3aVpYaHdJam95TURreU1UZzNNRGczZlEuakVzTUZQdDFnYjhxQWkzb1VPTnNoNVROY2dYeV8zZW8wMC1TVzVjU2dLWQ=="}}
+{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-jwt", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"anonKey": "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaVlXNXZiaUlzSW1semN5STZJbXR1YjJVdGMzVndZV0poYzJVaUxDSnBZWFFpT2pFM056YzROekExTlRRc0ltVjRjQ0k2TWpBNU16SXpNRFUxTkgwLmdIUDdTcWE2TW1JOHBzbE1OZkt4WmhGVXpPS0FNWDUteGs3WFQwblFZcWc=", "secret": "NGU1M2UxZWNiOThlYjMyZWU4M2I4OTBiZWE3OWU2NzhlOTUyYzZhZTIzN2VkZjNmNjVmMzdiZjZkZDIyNjJlYg==", "serviceKey": "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaWMyVnlkbWxqWlY5eWIyeGxJaXdpYVhOeklqb2lhMjV2WlMxemRYQmhZbUZ6WlNJc0ltbGhkQ0k2TVRjM056ZzNNRFUxTkN3aVpYaHdJam95TURrek1qTXdOVFUwZlEuQjBNMFY4VExaQzBoUzQ2OU8tbGVpY0R0OHVRRXFPY21EYWpsV1ppR1Zzdw=="}}
---
{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-meta", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"cryptoKey": "eW91ci1lbmNyeXB0aW9uLWtleS0zMi1jaGFycy1taW4="}}
---
@@ -36,29 +34,25 @@
---
{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-realtime", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"secretKeyBase": "VXBOVm50bjNjRHhISnBxOTlZTWMxVDFBUWdRcGM4a2ZZVHVSZ0JpWWExNUJMcng4ZXRRb1h6M2dadjEvdTJvcQ=="}}
---
-{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-s3", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"accessKey": "OWQzNmQ0MzRkMjZkZGRiOTcyZGNmZjJkOTI2NjYxMmI4ZTYxOGQ2YTYzYmIwOGM2ZTEyZTdlOTYzOGQ4MDQyMQ==", "keyId": "R0s5NmQ1ZmZlOGIxMWYzYTNkYzdhMDlhNzY="}}
+{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-s3", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"accessKey": "NWZmNDBmMDY3NzI4YTc5ZGViMTNiMTc5Y2NkZmQxMTVkN2MwOTY2YmQxOGZhMzhkMjc5OGNmMzg5YTEzN2JmZA==", "keyId": "R0tmZTQ4NmE4NmVhMDg5MWY4ZTUzMzQ1NmE="}}
---
{"apiVersion": "v1", "kind": "Secret", "metadata": {"name": "supabase-smtp", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "type": "Opaque", "data": {"password": "ZmFrZV9tYWlsX3Bhc3N3b3Jk", "username": "ZmFrZV9tYWlsX3VzZXI="}}
---
{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "supabase-functions-main", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "data": {"index.ts": "import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts'\n\nconsole.log('main function started')\n\nconst JWT_SECRET = Deno.env.get('JWT_SECRET')\nconst VERIFY_JWT = Deno.env.get('VERIFY_JWT') === 'true'\n\nfunction getAuthToken(req: Request) {\nconst authHeader = req.headers.get('authorization')\nif (!authHeader) {\n throw new Error('Missing authorization header')\n}\nconst [bearer, token] = authHeader.split(' ')\nif (bearer !== 'Bearer') {\n throw new Error(`Auth header is not 'Bearer {token}'`)\n}\nreturn token\n}\n\nasync function verifyJWT(jwt: string): Promise {\nconst encoder = new TextEncoder()\nconst secretKey = encoder.encode(JWT_SECRET)\ntry {\n await jose.jwtVerify(jwt, secretKey)\n} catch (err) {\n console.error(err)\n return false\n}\nreturn true\n}\n\nDeno.serve(async (req: Request) => {\nif (req.method !== 'OPTIONS' && VERIFY_JWT) {\n try {\n const token = getAuthToken(req)\n const isValidJWT = await verifyJWT(token)\n\n if (!isValidJWT) {\n return new Response(JSON.stringify({ msg: 'Invalid JWT' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n } catch (e) {\n console.error(e)\n return new Response(JSON.stringify({ msg: e.toString() }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n}\n\nconst url = new URL(req.url)\nconst { pathname } = url\nconst path_parts = pathname.split('/')\nconst service_name = path_parts[1]\n\nif (!service_name || service_name === '') {\n const error = { msg: 'missing function name in request' }\n return new Response(JSON.stringify(error), {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\nconst servicePath = `/home/deno/functions/${service_name}`\nconsole.error(`serving the request with ${servicePath}`)\n\nconst memoryLimitMb = 150\nconst workerTimeoutMs = 1 * 60 * 1000\nconst noModuleCache = false\nconst importMapPath = null\nconst envVarsObj = Deno.env.toObject()\nconst envVars = Object.keys(envVarsObj).map((k) => [k, envVarsObj[k]])\n\ntry {\n const worker = await EdgeRuntime.userWorkers.create({\n servicePath,\n memoryLimitMb,\n workerTimeoutMs,\n noModuleCache,\n importMapPath,\n envVars,\n })\n return await worker.fetch(req)\n} catch (e) {\n const error = { msg: e.toString() }\n return new Response(JSON.stringify(error), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n})\n"}}
---
-{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "supabase-kong", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "data": {"wrapper.sh": "#!/bin/bash\n\nset -euo pipefail\n\necho \"Replacing env placeholders of /usr/local/kong/kong.yml\"\n\nsed \\\n-e \"s|\\${SUPABASE_ANON_KEY}|${SUPABASE_ANON_KEY}|\" \\\n-e \"s|\\${SUPABASE_SERVICE_KEY}|${SUPABASE_SERVICE_KEY}|\" \\\n-e \"s|\\${DASHBOARD_USERNAME}|${DASHBOARD_USERNAME}|\" \\\n-e \"s|\\${DASHBOARD_PASSWORD}|${DASHBOARD_PASSWORD}|\" \\\n/usr/local/kong/template.yml \\\n> /usr/local/kong/kong.yml\n\nexec /docker-entrypoint.sh kong docker-start\n", "template.yml": "_format_version: '2.1'\n_transform: true\n\nconsumers:\n - username: DASHBOARD\n - username: anon\n keyauth_credentials:\n - key: ${SUPABASE_ANON_KEY}\n - username: service_role\n keyauth_credentials:\n - key: ${SUPABASE_SERVICE_KEY}\nacls:\n - consumer: anon\n group: anon\n - consumer: service_role\n group: admin\nbasicauth_credentials:\n - consumer: DASHBOARD\n username: ${DASHBOARD_USERNAME}\n password: ${DASHBOARD_PASSWORD}\nservices:\n # Dedicated health endpoint used by the GCE LB BackendConfig.\n # request-termination returns 200 synchronously without hitting any\n # upstream, so the probe passes as long as the Kong proxy itself is\n # accepting requests -- same liveness semantics as the TCP check we\n # originally wanted, but using the HTTP protocol that GCE's L7\n # BackendConfig CRD actually accepts (TCP is rejected with\n # `Protocol \"TCP\" is not valid, must be one of [HTTP,HTTPS,HTTP2]`).\n #\n # URL is a RFC-2606 reserved `.invalid` hostname that never resolves.\n # We originally tried `http://127.0.0.1:8000/` here, which is Kong's\n # own proxy port -- this crashlooped the pod on startup (rollout timed\n # out waiting for new pod to become Ready). Suspected cause: Kong's\n # declarative-config parser rejects the self-reference. Since the\n # request-termination plugin short-circuits before any DNS lookup or\n # upstream connection, using a non-resolvable placeholder URL is\n # equivalent in behavior but avoids the loop detection.\n - name: healthz\n url: http://knoe.healthz.invalid/\n routes:\n - name: healthz\n strip_path: true\n paths:\n - /healthz\n plugins:\n - name: request-termination\n config:\n status_code: 200\n message: ok\n - name: auth-v1-open\n url: http://supabase-auth:9999/verify\n routes:\n - name: auth-v1-open\n strip_path: true\n paths:\n - /auth/v1/verify\n plugins:\n - name: cors\n - name: auth-v1-open-callback\n url: http://supabase-auth:9999/callback\n routes:\n - name: auth-v1-open-callback\n strip_path: true\n paths:\n - /auth/v1/callback\n plugins:\n - name: cors\n - name: auth-v1-open-authorize\n url: http://supabase-auth:9999/authorize\n routes:\n - name: auth-v1-open-authorize\n strip_path: true\n paths:\n - /auth/v1/authorize\n plugins:\n - name: cors\n - name: auth-v1\n _comment: \"GoTrue: /auth/v1/* -> http://supabase-auth:9999/*\"\n url: http://supabase-auth:9999\n routes:\n - name: auth-v1-all\n strip_path: true\n paths:\n - /auth/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: rest-v1\n _comment: \"PostgREST: /rest/v1/* -> http://supabase-rest:3000/*\"\n url: http://supabase-rest:3000/\n routes:\n - name: rest-v1-all\n strip_path: true\n paths:\n - /rest/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: true\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: graphql-v1\n _comment: 'PostgREST: /graphql/v1/* -> http://supabase-rest:3000/rpc/graphql'\n url: http://supabase-rest:3000/rpc/graphql\n routes:\n - name: graphql-v1-all\n strip_path: true\n paths:\n - /graphql/v1\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: true\n - name: request-transformer\n config:\n add:\n headers:\n - Content-Profile:graphql_public\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: realtime-v1-ws\n _comment: \"Realtime: /realtime/v1/* -> ws://supabase-realtime:4000/socket/*\"\n url: http://supabase-realtime:4000/socket\n protocol: ws\n routes:\n - name: realtime-v1-ws\n strip_path: true\n paths:\n - /realtime/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: realtime-v1-rest\n _comment: 'Realtime: /realtime/v1/* -> http://supabase-realtime:4000/api/*'\n url: http://supabase-realtime:4000/api\n protocol: http\n routes:\n - name: realtime-v1-rest\n strip_path: true\n paths:\n - /realtime/v1/api\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: storage-v1\n _comment: \"Storage: /storage/v1/* -> http://supabase-storage:5000/*\"\n url: http://supabase-storage:5000/\n routes:\n - name: storage-v1-all\n strip_path: true\n paths:\n - /storage/v1/\n plugins:\n - name: cors\n - name: functions-v1\n _comment: 'Edge Functions: /functions/v1/* -> http://supabase-functions:9000/*'\n url: http://supabase-functions:9000/\n routes:\n - name: functions-v1-all\n strip_path: true\n paths:\n - /functions/v1/\n plugins:\n - name: cors\n\n\n\n\n - name: meta\n _comment: \"pg-meta: /pg/* -> http://supabase-meta:8080/*\"\n url: http://supabase-meta:8080/\n routes:\n - name: meta-all\n strip_path: true\n paths:\n - /pg/\n plugins:\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - name: dashboard\n _comment: 'Studio: /* -> http://supabase-studio:3000/*'\n url: http://supabase-studio:3000/\n routes:\n - name: dashboard-all\n strip_path: true\n paths:\n - /\n plugins:\n - name: cors\n - name: basic-auth\n config:\n hide_credentials: true\n"}}
+{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "supabase-kong", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "data": {"wrapper.sh": "#!/bin/bash\n\nset -euo pipefail\n\necho \"Replacing env placeholders of /usr/local/kong/kong.yml\"\n\nsed \\\n-e \"s|\\${SUPABASE_ANON_KEY}|${SUPABASE_ANON_KEY}|\" \\\n-e \"s|\\${SUPABASE_SERVICE_KEY}|${SUPABASE_SERVICE_KEY}|\" \\\n/usr/local/kong/template.yml \\\n> /usr/local/kong/kong.yml\n\nexec /docker-entrypoint.sh kong docker-start\n", "template.yml": "_format_version: '2.1'\n_transform: true\n\nconsumers:\n - username: anon\n keyauth_credentials:\n - key: ${SUPABASE_ANON_KEY}\n - username: service_role\n keyauth_credentials:\n - key: ${SUPABASE_SERVICE_KEY}\nacls:\n - consumer: anon\n group: anon\n - consumer: service_role\n group: admin\nservices:\n # Dedicated health endpoint used by the GCE LB BackendConfig.\n # request-termination returns 200 synchronously without hitting any\n # upstream, so the probe passes as long as the Kong proxy itself is\n # accepting requests -- same liveness semantics as the TCP check we\n # originally wanted, but using the HTTP protocol that GCE's L7\n # BackendConfig CRD actually accepts (TCP is rejected with\n # `Protocol \"TCP\" is not valid, must be one of [HTTP,HTTPS,HTTP2]`).\n #\n # URL is a RFC-2606 reserved `.invalid` hostname that never resolves.\n # We originally tried `http://127.0.0.1:8000/` here, which is Kong's\n # own proxy port -- this crashlooped the pod on startup (rollout timed\n # out waiting for new pod to become Ready). Suspected cause: Kong's\n # declarative-config parser rejects the self-reference. Since the\n # request-termination plugin short-circuits before any DNS lookup or\n # upstream connection, using a non-resolvable placeholder URL is\n # equivalent in behavior but avoids the loop detection.\n - name: healthz\n url: http://knoe.healthz.invalid/\n routes:\n - name: healthz\n strip_path: true\n paths:\n - /healthz\n plugins:\n - name: request-termination\n config:\n status_code: 200\n message: ok\n # Stop-gap support endpoint -- 302s to mailto:support@knoe.dev so any user\n # who lands at https://db.0.knoe.dev/support gets a working escape hatch.\n # The in-Studio \"Report a problem\" / \"Send feedback\" buttons in upstream\n # Studio are hardcoded to supabase.com endpoints and are not yet rewired\n # (would require forking the Studio image -- tracked in docs/TODO.md).\n # In the meantime we tell users: \"for help, go to db.0.knoe.dev/support\".\n # request-termination synthesizes a 302 status; response-transformer\n # injects the Location header (request-termination alone can't set it).\n - name: support\n url: http://knoe.support.invalid/\n routes:\n - name: support-redirect\n strip_path: true\n paths:\n - /support\n plugins:\n - name: request-termination\n config:\n status_code: 302\n message: \"Redirecting to support@knoe.dev\"\n - name: response-transformer\n config:\n add:\n headers:\n - \"Location:mailto:support@knoe.dev\"\n - name: auth-v1-open\n url: http://supabase-auth:9999/verify\n routes:\n - name: auth-v1-open\n strip_path: true\n paths:\n - /auth/v1/verify\n plugins:\n - name: cors\n - name: auth-v1-open-callback\n url: http://supabase-auth:9999/callback\n routes:\n - name: auth-v1-open-callback\n strip_path: true\n paths:\n - /auth/v1/callback\n plugins:\n - name: cors\n - name: auth-v1-open-authorize\n url: http://supabase-auth:9999/authorize\n routes:\n - name: auth-v1-open-authorize\n strip_path: true\n paths:\n - /auth/v1/authorize\n plugins:\n - name: cors\n - name: auth-v1\n _comment: \"GoTrue: /auth/v1/* -> http://supabase-auth:9999/*\"\n url: http://supabase-auth:9999\n routes:\n - name: auth-v1-all\n strip_path: true\n paths:\n - /auth/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: rest-v1\n _comment: \"PostgREST: /rest/v1/* -> http://supabase-rest:3000/*\"\n url: http://supabase-rest:3000/\n routes:\n - name: rest-v1-all\n strip_path: true\n paths:\n - /rest/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: true\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: graphql-v1\n _comment: 'PostgREST: /graphql/v1/* -> http://supabase-rest:3000/rpc/graphql'\n url: http://supabase-rest:3000/rpc/graphql\n routes:\n - name: graphql-v1-all\n strip_path: true\n paths:\n - /graphql/v1\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: true\n - name: request-transformer\n config:\n add:\n headers:\n - Content-Profile:graphql_public\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: realtime-v1-ws\n _comment: \"Realtime: /realtime/v1/* -> ws://supabase-realtime:4000/socket/*\"\n url: http://supabase-realtime:4000/socket\n protocol: ws\n routes:\n - name: realtime-v1-ws\n strip_path: true\n paths:\n - /realtime/v1/\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: realtime-v1-rest\n _comment: 'Realtime: /realtime/v1/* -> http://supabase-realtime:4000/api/*'\n url: http://supabase-realtime:4000/api\n protocol: http\n routes:\n - name: realtime-v1-rest\n strip_path: true\n paths:\n - /realtime/v1/api\n plugins:\n - name: cors\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n - anon\n - name: storage-v1\n _comment: \"Storage: /storage/v1/* -> http://supabase-storage:5000/*\"\n url: http://supabase-storage:5000/\n routes:\n - name: storage-v1-all\n strip_path: true\n paths:\n - /storage/v1/\n plugins:\n - name: cors\n - name: functions-v1\n _comment: 'Edge Functions: /functions/v1/* -> http://supabase-functions:9000/*'\n url: http://supabase-functions:9000/\n routes:\n - name: functions-v1-all\n strip_path: true\n paths:\n - /functions/v1/\n plugins:\n - name: cors\n\n\n\n\n - name: meta\n _comment: \"pg-meta: /pg/* -> http://supabase-meta:8080/*\"\n url: http://supabase-meta:8080/\n routes:\n - name: meta-all\n strip_path: true\n paths:\n - /pg/\n plugins:\n - name: key-auth\n config:\n hide_credentials: false\n - name: acl\n config:\n hide_groups_header: true\n allow:\n - admin\n # Onboarding reveal page (knoe-onboard nginx pod). Listed BEFORE the\n # /-wildcard dashboard route so Kong's longest-prefix match picks\n # /onboard.html over the dashboard. The page itself is also exempted\n # from oauth2-proxy gating (`--skip-auth-route=^/onboard\\.html$`) since\n # URL fragments don't survive an OAuth redirect; URL secrecy + 24h\n # expiry + immediate-rotation is the security envelope.\n - name: onboard\n _comment: 'Onboarding reveal: /onboard.html -> knoe-onboard nginx pod'\n url: http://knoe-onboard:80/\n routes:\n - name: onboard-html\n strip_path: false\n paths:\n - /onboard.html\n plugins:\n - name: cors\n - name: dashboard\n _comment: 'Studio: /* -> http://supabase-studio:3000/*'\n url: http://supabase-studio:3000/\n routes:\n - name: dashboard-all\n strip_path: true\n paths:\n - /\n plugins:\n - name: cors\n"}}
---
{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "supabase-vector-config", "labels": {"helm.sh/chart": "knoe-supabase-0.5.0-knoe.1", "app.kubernetes.io/name": "supabase", "app.kubernetes.io/instance": "supabase", "app.kubernetes.io/managed-by": "Helm"}}, "data": {"vector.yml": "api:\n enabled: true\n address: 0.0.0.0:9001\n\nsources:\n kubernetes_host:\n type: kubernetes_logs\n extra_label_selector: app.kubernetes.io/instance=supabase,app.kubernetes.io/name!=knoe-supabase-vector\n\ntransforms:\n project_logs:\n type: remap\n inputs:\n - kubernetes_host\n source: |-\n .project = \"default\"\n .event_message = del(.message)\n .appname = del(.kubernetes.container_name)\n del(.file)\n del(.kubernetes)\n del(.source_type)\n del(.stream)\n router:\n type: route\n inputs:\n - project_logs\n route:\n kong: '.appname == \"knoe-supabase-kong\"'\n auth: '.appname == \"knoe-supabase-auth\"'\n rest: '.appname == \"knoe-supabase-rest\"'\n realtime: '.appname == \"knoe-supabase-realtime\"'\n storage: '.appname == \"knoe-supabase-storage\"'\n functions: '.appname == \"knoe-supabase-functions\"'\n db: '.appname == \"knoe-supabase-db\"'\n # Ignores non nginx errors since they are related with kong booting up\n kong_logs:\n type: remap\n inputs:\n - router.kong\n source: |-\n req, err = parse_nginx_log(.event_message, \"combined\")\n if err == null {\n .timestamp = req.timestamp\n .metadata.request.headers.referer = req.referer\n .metadata.request.headers.user_agent = req.agent\n .metadata.request.headers.cf_connecting_ip = req.client\n .metadata.response.status_code = req.status\n url, split_err = split(req.request, \" \")\n if split_err == null {\n .metadata.request.method = url[0]\n .metadata.request.path = url[1]\n .metadata.request.protocol = url[2]\n }\n }\n if err != null {\n abort\n }\n # Ignores non nginx errors since they are related with kong booting up\n kong_err:\n type: remap\n inputs:\n - router.kong\n source: |-\n .metadata.request.method = \"GET\"\n .metadata.response.status_code = 200\n parsed, err = parse_nginx_log(.event_message, \"error\")\n if err == null {\n .timestamp = parsed.timestamp\n .severity = parsed.severity\n .metadata.request.host = parsed.host\n .metadata.request.headers.cf_connecting_ip = parsed.client\n url, err = split(parsed.request, \" \")\n if err == null {\n .metadata.request.method = url[0]\n .metadata.request.path = url[1]\n .metadata.request.protocol = url[2]\n }\n }\n if err != null {\n abort\n }\n # Gotrue logs are structured json strings which frontend parses directly. But we keep metadata for consistency.\n auth_logs:\n type: remap\n inputs:\n - router.auth\n source: |-\n parsed, err = parse_json(.event_message)\n if err == null {\n .metadata.timestamp = parsed.time\n .metadata = merge!(.metadata, parsed)\n }\n # PostgREST logs are structured so we separate timestamp from message using regex\n rest_logs:\n type: remap\n inputs:\n - router.rest\n source: |-\n parsed, err = parse_regex(.event_message, r'^(?P