Updated Dify, Supabase and Plane

This commit is contained in:
Ahson Shaikh
2026-03-10 17:27:09 +05:00
parent 8f226ea714
commit c8467d2d11
22 changed files with 766 additions and 153 deletions
+25 -10
View File
@@ -27,8 +27,8 @@ acls:
###
basicauth_credentials:
- consumer: DASHBOARD
username: $DASHBOARD_USERNAME
password: $DASHBOARD_PASSWORD
username: '$DASHBOARD_USERNAME'
password: '$DASHBOARD_PASSWORD'
###
### API Routes
@@ -197,14 +197,29 @@ services:
- name: cors
## Analytics routes
- name: analytics-v1
_comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*'
url: http://analytics:4000/
routes:
- name: analytics-v1-all
strip_path: true
paths:
- /analytics/v1/
## Not used - Studio and Vector talk directly to analytics via Docker networking.
## If external access is needed, add routes with key-auth matching Logflare's x-api-key auth.
# - name: analytics-v1-api
# _comment: 'Analytics: /analytics/v1/api/endpoints/* -> http://logflare:4000/api/endpoints/*'
# url: http://analytics:4000/api/endpoints
# routes:
# - name: analytics-v1-api
# strip_path: true
# paths:
# - /analytics/v1/api/endpoints/
# - name: analytics-v1
# _comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*'
# url: http://analytics:4000/
# routes:
# - name: dashboard-v1-all
# strip_path: true
# paths:
# - /analytics/v1
# plugins:
# - name: cors
# - name: basic-auth
# config:
# hide_credentials: true
## Secure Database routes
- name: meta
@@ -2,9 +2,7 @@
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import { serve } from "https://deno.land/std@0.177.1/http/server.ts"
serve(async () => {
Deno.serve(async () => {
return new Response(
`"Hello from Edge Functions!"`,
{ headers: { "Content-Type": "application/json" } },
@@ -1,4 +1,3 @@
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts'
console.log('main function started')
@@ -30,7 +29,7 @@ async function verifyJWT(jwt: string): Promise<boolean> {
return true
}
serve(async (req: Request) => {
Deno.serve(async (req: Request) => {
if (req.method !== 'OPTIONS' && VERIFY_JWT) {
try {
const token = getAuthToken(req)
+32 -17
View File
@@ -49,10 +49,13 @@ transforms:
.metadata.request.headers.referer = req.referer
.metadata.request.headers.user_agent = req.agent
.metadata.request.headers.cf_connecting_ip = req.client
.metadata.request.method = req.method
.metadata.request.path = req.path
.metadata.request.protocol = req.protocol
.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
@@ -101,14 +104,20 @@ transforms:
parsed, err = parse_regex(.event_message, r'^(?P<time>.*): (?P<msg>.*)$')
if err == null {
.event_message = parsed.msg
.timestamp = to_timestamp!(parsed.time)
.timestamp = parse_timestamp!(value: parsed.time,format: "%d/%b/%Y:%H:%M:%S %z")
.metadata.host = .project
}
# Filter out healthcheck logs from Realtime
realtime_logs_filtered:
type: filter
inputs:
- router.realtime
condition: '!contains(string!(.event_message), "/health")'
# Realtime logs are structured so we parse the severity level using regex (ignore time because it has no date)
realtime_logs:
type: remap
inputs:
- router.realtime
- realtime_logs_filtered
source: |-
.metadata.project = del(.project)
.metadata.external_id = .metadata.project
@@ -154,7 +163,7 @@ transforms:
if err != null || parsed == null {
.metadata.parsed.error_severity = "info"
}
if parsed != null {
if parsed.level != null {
.metadata.parsed.error_severity = parsed.level
}
if .metadata.parsed.error_severity == "info" {
@@ -171,7 +180,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=gotrue.logs.prod'
@@ -183,7 +193,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=realtime.logs.prod'
@@ -195,7 +206,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=postgREST.logs.prod'
@@ -207,13 +219,13 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
# We must route the sink through kong because ingesting logs before logflare is fully initialised will
# lead to broken queries from studio. This works by the assumption that containers are started in the
# following order: vector > db > logflare > kong
uri: 'http://kong:8000/analytics/v1/api/logs?source_name=postgres.logs'
# Route directly to analytics like other sinks. Retry handles the startup
# race where analytics may not be ready yet when early DB logs arrive.
uri: 'http://analytics:4000/api/logs?source_name=postgres.logs'
logflare_functions:
type: 'http'
inputs:
@@ -222,7 +234,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=deno-relay-logs'
@@ -234,7 +247,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=storage.logs.prod.2'
@@ -247,7 +261,8 @@ sinks:
codec: 'json'
method: 'post'
request:
retry_max_duration_secs: 10
retry_max_duration_secs: 30
retry_initial_backoff_secs: 1
headers:
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
uri: 'http://analytics:4000/api/logs?source_name=cloudflare.logs.prod'
@@ -0,0 +1,36 @@
{$PROXY_DOMAIN} {
@supabase_api path /auth/v1/* /rest/v1/* /graphql/v1/* /realtime/v1/* /functions/v1/* /mcp
handle @supabase_api {
reverse_proxy kong:8000
}
handle_path /storage/v1/* {
# CORS headers for Storage (bypasses Kong, which normally handles CORS)
@cors_preflight method OPTIONS
handle @cors_preflight {
header Access-Control-Allow-Origin *
header Access-Control-Allow-Methods "GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS"
header Access-Control-Allow-Headers *
respond 204
}
header Access-Control-Allow-Origin *
reverse_proxy storage:5000 {
# Required for TUS resumable upload Location headers and S3 signature verification.
header_up X-Forwarded-Prefix /{http.request.orig_uri.path.0}/{http.request.orig_uri.path.1}
}
}
handle {
basic_auth {
# PROXY_AUTH_PASSWORD is overwritten with the bcrypt on startup
{$PROXY_AUTH_USERNAME} {$PROXY_AUTH_PASSWORD}
}
reverse_proxy studio:3000
}
header -server
}
@@ -0,0 +1,109 @@
upstream kong_upstream {
server kong:8000;
keepalive 2;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name ${PROXY_DOMAIN};
server_tokens off;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
ssl_certificate /etc/letsencrypt/live/${PROXY_DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${PROXY_DOMAIN}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/${PROXY_DOMAIN}/chain.pem;
ssl_dhparam /etc/letsencrypt/dhparams/dhparam.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Prevent 502 errors from large Supabase auth cookies
large_client_header_buffers 4 16k;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
location / {
auth_basic "supabase";
auth_basic_user_file /etc/nginx/user_conf.d/dashboard-passwd;
proxy_pass http://studio:3000;
}
location /auth {
proxy_pass http://kong_upstream;
}
location /rest {
proxy_pass http://kong_upstream;
}
location /realtime/v1/ {
proxy_pass http://kong_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
location /storage/v1/ {
proxy_pass http://storage:5000/;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
# Required for TUS resumable upload Location headers and S3 signature verification.
proxy_set_header X-Forwarded-Prefix /storage/v1;
client_max_body_size 0;
# CORS headers for Storage (bypasses Kong, which normally handles CORS)
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
}
location /functions {
proxy_pass http://kong_upstream;
}
location /graphql {
proxy_pass http://kong_upstream;
}
location /mcp {
proxy_pass http://kong_upstream;
}
}