--- # Source: knoe-supabase/templates/analytics/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-analytics labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/auth/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-auth labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/functions/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: knoe-supabase-knoe-supabase-functions labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/imgproxy/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: knoe-supabase-knoe-supabase-imgproxy labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/kong/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: knoe-supabase-knoe-supabase-kong labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/meta/serviceaccount.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/realtime/serviceaccount.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/rest/serviceaccount.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/storage/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: knoe-supabase-knoe-supabase-storage labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/studio/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-studio labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/vector/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: knoe-supabase-knoe-supabase-vector labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm --- # Source: knoe-supabase/templates/secrets/analytics.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: privateAccessToken: eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXByaXZhdGU= publicAccessToken: eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXB1YmxpYw== --- # Source: knoe-supabase/templates/secrets/dashboard.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: openAiApiKey: a2V5X3N1cGVyX3NlY3JldA== password: dGhpc19wYXNzd29yZF9pc19pbnNlY3VyZV9hbmRfc2hvdWxkX2JlX3VwZGF0ZWQ= username: c3VwYWJhc2U= --- # Source: knoe-supabase/templates/secrets/db.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: database: cG9zdGdyZXM= password: ZnIzc3R5bDM= password_encoded: ZnIzc3R5bDM= --- # Source: knoe-supabase/templates/secrets/jwt.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: anonKey: ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaVlXNXZiaUlzSW1semN5STZJbkJ5YjJ4bExYTjFjR0ZpWVhObElpd2lhV0YwSWpveE56YzBPVFE1TkRreExDSmxlSEFpT2pJd09UQXpNRGswT1RGOS5KTDNRdFd6cmEtR3RhcWF4bXpYU2JNbnc1WTc4alpSWjNqVXVuNlVDNFFr secret: MWM3YjU5Y2MxMzM3YzY1YmMyZWRjMmU1OGQzZmZiZTU4NGI5ZjllZjY2MzA1NzA1ZmNhNjMzNjgyOTU0Zjk2NQ== serviceKey: ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnliMnhsSWpvaWMyVnlkbWxqWlY5eWIyeGxJaXdpYVhOeklqb2ljSEp2YkdVdGMzVndZV0poYzJVaUxDSnBZWFFpT2pFM056UTVORGswT1RFc0ltVjRjQ0k2TWpBNU1ETXdPVFE1TVgwLjFfeE1oQkMwVnNGWnhUSlYyQUR1RGphZjA0UkZUQlpjWDVhaGRUUWRWMWM= --- # Source: knoe-supabase/templates/secrets/meta.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: cryptoKey: eW91ci1lbmNyeXB0aW9uLWtleS0zMi1jaGFycy1taW4= --- # Source: knoe-supabase/templates/secrets/minio.yaml apiVersion: v1 kind: Secret metadata: name: supabase-minio labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: password: c2VjcmV0MTIzNA== user: c3VwYS1zdG9yYWdl --- # Source: knoe-supabase/templates/secrets/realtime.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: secretKeyBase: VXBOVm50bjNjRHhISnBxOTlZTWMxVDFBUWdRcGM4a2ZZVHVSZ0JpWWExNUJMcng4ZXRRb1h6M2dadjEvdTJvcQ== --- # Source: knoe-supabase/templates/secrets/s3.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: accessKey: ZHVtbXktc2VjcmV0 keyId: ZHVtbXkta2V5 --- # Source: knoe-supabase/templates/secrets/smtp.yaml 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: knoe-supabase app.kubernetes.io/managed-by: Helm type: Opaque data: password: ZmFrZV9tYWlsX3Bhc3N3b3Jk username: ZmFrZV9tYWlsX3VzZXI= --- # Source: knoe-supabase/templates/functions/functions.config.yaml apiVersion: v1 kind: ConfigMap metadata: name: knoe-supabase-knoe-supabase-functions-main labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm data: index.ts: | import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts' console.log('main function started') const JWT_SECRET = Deno.env.get('JWT_SECRET') const VERIFY_JWT = Deno.env.get('VERIFY_JWT') === 'true' function getAuthToken(req: Request) { const authHeader = req.headers.get('authorization') if (!authHeader) { throw new Error('Missing authorization header') } const [bearer, token] = authHeader.split(' ') if (bearer !== 'Bearer') { throw new Error(`Auth header is not 'Bearer {token}'`) } return token } async function verifyJWT(jwt: string): Promise { const encoder = new TextEncoder() const secretKey = encoder.encode(JWT_SECRET) try { await jose.jwtVerify(jwt, secretKey) } catch (err) { console.error(err) return false } return true } Deno.serve(async (req: Request) => { if (req.method !== 'OPTIONS' && VERIFY_JWT) { try { const token = getAuthToken(req) const isValidJWT = await verifyJWT(token) if (!isValidJWT) { return new Response(JSON.stringify({ msg: 'Invalid JWT' }), { status: 401, headers: { 'Content-Type': 'application/json' }, }) } } catch (e) { console.error(e) return new Response(JSON.stringify({ msg: e.toString() }), { status: 401, headers: { 'Content-Type': 'application/json' }, }) } } const url = new URL(req.url) const { pathname } = url const path_parts = pathname.split('/') const service_name = path_parts[1] if (!service_name || service_name === '') { const error = { msg: 'missing function name in request' } return new Response(JSON.stringify(error), { status: 400, headers: { 'Content-Type': 'application/json' }, }) } const servicePath = `/home/deno/functions/${service_name}` console.error(`serving the request with ${servicePath}`) const memoryLimitMb = 150 const workerTimeoutMs = 1 * 60 * 1000 const noModuleCache = false const importMapPath = null const envVarsObj = Deno.env.toObject() const envVars = Object.keys(envVarsObj).map((k) => [k, envVarsObj[k]]) try { const worker = await EdgeRuntime.userWorkers.create({ servicePath, memoryLimitMb, workerTimeoutMs, noModuleCache, importMapPath, envVars, }) return await worker.fetch(req) } catch (e) { const error = { msg: e.toString() } return new Response(JSON.stringify(error), { status: 500, headers: { 'Content-Type': 'application/json' }, }) } }) --- # Source: knoe-supabase/templates/kong/config.yaml apiVersion: v1 kind: ConfigMap metadata: name: knoe-supabase-knoe-supabase-kong labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm data: wrapper.sh: | #!/bin/bash set -euo pipefail echo "Replacing env placeholders of /usr/local/kong/kong.yml" sed \ -e "s|\${SUPABASE_ANON_KEY}|${SUPABASE_ANON_KEY}|" \ -e "s|\${SUPABASE_SERVICE_KEY}|${SUPABASE_SERVICE_KEY}|" \ -e "s|\${DASHBOARD_USERNAME}|${DASHBOARD_USERNAME}|" \ -e "s|\${DASHBOARD_PASSWORD}|${DASHBOARD_PASSWORD}|" \ /usr/local/kong/template.yml \ > /usr/local/kong/kong.yml exec /docker-entrypoint.sh kong docker-start template.yml: | _format_version: '2.1' _transform: true consumers: - username: DASHBOARD - username: anon keyauth_credentials: - key: ${SUPABASE_ANON_KEY} - username: service_role keyauth_credentials: - key: ${SUPABASE_SERVICE_KEY} acls: - consumer: anon group: anon - consumer: service_role group: admin basicauth_credentials: - consumer: DASHBOARD username: ${DASHBOARD_USERNAME} password: ${DASHBOARD_PASSWORD} services: - name: auth-v1-open url: http://supabase-auth:9999/verify routes: - name: auth-v1-open strip_path: true paths: - /auth/v1/verify plugins: - name: cors - name: auth-v1-open-callback url: http://supabase-auth:9999/callback routes: - name: auth-v1-open-callback strip_path: true paths: - /auth/v1/callback plugins: - name: cors - name: auth-v1-open-authorize url: http://supabase-auth:9999/authorize routes: - name: auth-v1-open-authorize strip_path: true paths: - /auth/v1/authorize plugins: - name: cors - name: auth-v1 _comment: "GoTrue: /auth/v1/* -> http://supabase-auth:9999/*" url: http://supabase-auth:9999 routes: - name: auth-v1-all strip_path: true paths: - /auth/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - admin - anon - name: rest-v1 _comment: "PostgREST: /rest/v1/* -> http://supabase-rest:3000/*" url: http://supabase-rest:3000/ routes: - name: rest-v1-all strip_path: true paths: - /rest/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: true - name: acl config: hide_groups_header: true allow: - admin - anon - name: graphql-v1 _comment: 'PostgREST: /graphql/v1/* -> http://supabase-rest:3000/rpc/graphql' url: http://supabase-rest:3000/rpc/graphql routes: - name: graphql-v1-all strip_path: true paths: - /graphql/v1 plugins: - name: cors - name: key-auth config: hide_credentials: true - name: request-transformer config: add: headers: - Content-Profile:graphql_public - name: acl config: hide_groups_header: true allow: - admin - anon - name: realtime-v1-ws _comment: "Realtime: /realtime/v1/* -> ws://supabase-realtime:4000/socket/*" url: http://supabase-realtime:4000/socket protocol: ws routes: - name: realtime-v1-ws strip_path: true paths: - /realtime/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - admin - anon - name: realtime-v1-rest _comment: 'Realtime: /realtime/v1/* -> http://supabase-realtime:4000/api/*' url: http://supabase-realtime:4000/api protocol: http routes: - name: realtime-v1-rest strip_path: true paths: - /realtime/v1/api plugins: - name: cors - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - admin - anon - name: storage-v1 _comment: "Storage: /storage/v1/* -> http://knoe-supabase-knoe-supabase-storage:5000/*" url: http://knoe-supabase-knoe-supabase-storage:5000/ routes: - name: storage-v1-all strip_path: true paths: - /storage/v1/ plugins: - name: cors - name: functions-v1 _comment: 'Edge Functions: /functions/v1/* -> http://knoe-supabase-knoe-supabase-functions:9000/*' url: http://knoe-supabase-knoe-supabase-functions:9000/ routes: - name: functions-v1-all strip_path: true paths: - /functions/v1/ plugins: - name: cors - name: meta _comment: "pg-meta: /pg/* -> http://supabase-meta:8080/*" url: http://supabase-meta:8080/ routes: - name: meta-all strip_path: true paths: - /pg/ plugins: - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - admin - name: dashboard _comment: 'Studio: /* -> http://supabase-studio:3000/*' url: http://supabase-studio:3000/ routes: - name: dashboard-all strip_path: true paths: - / plugins: - name: cors - name: basic-auth config: hide_credentials: true --- # Source: knoe-supabase/templates/vector/config.yaml apiVersion: v1 kind: ConfigMap metadata: name: knoe-supabase-knoe-supabase-vector-config labels: helm.sh/chart: knoe-supabase-0.5.0-knoe.1 app.kubernetes.io/name: supabase app.kubernetes.io/instance: knoe-supabase app.kubernetes.io/managed-by: Helm data: vector.yml: | api: enabled: true address: 0.0.0.0:9001 sources: kubernetes_host: type: kubernetes_logs extra_label_selector: app.kubernetes.io/instance=knoe-supabase,app.kubernetes.io/name!=knoe-supabase-vector transforms: project_logs: type: remap inputs: - kubernetes_host source: |- .project = "default" .event_message = del(.message) .appname = del(.kubernetes.container_name) del(.file) del(.kubernetes) del(.source_type) del(.stream) router: type: route inputs: - project_logs route: kong: '.appname == "knoe-supabase-kong"' auth: '.appname == "knoe-supabase-auth"' rest: '.appname == "knoe-supabase-rest"' realtime: '.appname == "knoe-supabase-realtime"' storage: '.appname == "knoe-supabase-storage"' functions: '.appname == "knoe-supabase-functions"' db: '.appname == "knoe-supabase-db"' # Ignores non nginx errors since they are related with kong booting up kong_logs: type: remap inputs: - router.kong source: |- req, err = parse_nginx_log(.event_message, "combined") if err == null { .timestamp = req.timestamp .metadata.request.headers.referer = req.referer .metadata.request.headers.user_agent = req.agent .metadata.request.headers.cf_connecting_ip = req.client .metadata.response.status_code = req.status url, split_err = split(req.request, " ") if split_err == null { .metadata.request.method = url[0] .metadata.request.path = url[1] .metadata.request.protocol = url[2] } } if err != null { abort } # Ignores non nginx errors since they are related with kong booting up kong_err: type: remap inputs: - router.kong source: |- .metadata.request.method = "GET" .metadata.response.status_code = 200 parsed, err = parse_nginx_log(.event_message, "error") if err == null { .timestamp = parsed.timestamp .severity = parsed.severity .metadata.request.host = parsed.host .metadata.request.headers.cf_connecting_ip = parsed.client url, err = split(parsed.request, " ") if err == null { .metadata.request.method = url[0] .metadata.request.path = url[1] .metadata.request.protocol = url[2] } } if err != null { abort } # Gotrue logs are structured json strings which frontend parses directly. But we keep metadata for consistency. auth_logs: type: remap inputs: - router.auth source: |- parsed, err = parse_json(.event_message) if err == null { .metadata.timestamp = parsed.time .metadata = merge!(.metadata, parsed) } # PostgREST logs are structured so we separate timestamp from message using regex rest_logs: type: remap inputs: - router.rest source: |- parsed, err = parse_regex(.event_message, r'^(?P