From 6fd70d06cb626ed471a4815bd290564583bb3f7d Mon Sep 17 00:00:00 2001 From: kadma Date: Sat, 21 Feb 2026 10:19:41 -0500 Subject: [PATCH 1/7] Update Supabase 1.26.01 --- blueprints/supabase/docker-compose.yml | 116 ++++++++++---------- blueprints/supabase/template.toml | 144 +++++++++++++++++-------- meta.json | 2 +- 3 files changed, 160 insertions(+), 102 deletions(-) diff --git a/blueprints/supabase/docker-compose.yml b/blueprints/supabase/docker-compose.yml index 506ddc907..a83696839 100644 --- a/blueprints/supabase/docker-compose.yml +++ b/blueprints/supabase/docker-compose.yml @@ -5,13 +5,13 @@ # Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans # Reset everything: ./reset.sh -name: supabase +name: ${CONTAINER_PREFIX}-supabase services: studio: container_name: ${CONTAINER_PREFIX}-studio - image: supabase/studio:2025.04.21-sha-173cc56 + image: supabase/studio:2026.02.16-sha-26c615c restart: unless-stopped healthcheck: test: @@ -19,7 +19,7 @@ services: "CMD", "node", "-e", - "fetch('http://studio:3000/api/platform/profile').then((r) => {if (r.status !== 200) throw new Error(r.status)})" + "fetch('http://${CONTAINER_PREFIX}-studio:3000/api/platform/profile').then((r) => {if (r.status !== 200) throw new Error(r.status)})" ] timeout: 10s interval: 5s @@ -28,34 +28,37 @@ services: analytics: condition: service_healthy environment: - STUDIO_PG_META_URL: http://meta:8080 + HOSTNAME: "::" + STUDIO_PG_META_URL: http://${CONTAINER_PREFIX}-meta:8080 + POSTGRES_PORT: ${POSTGRES_PORT} + POSTGRES_HOST: ${POSTGRES_HOST} + POSTGRES_DB: ${POSTGRES_DB} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - + PG_META_CRYPTO_KEY: ${PG_META_CRYPTO_KEY} DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION} DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT} OPENAI_API_KEY: ${OPENAI_API_KEY:-} - SUPABASE_URL: ${SUPABASE_PUBLIC_URL} SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL} SUPABASE_ANON_KEY: ${ANON_KEY} SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} AUTH_JWT_SECRET: ${JWT_SECRET} - - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} - LOGFLARE_URL: http://analytics:4000 + LOGFLARE_API_KEY: ${LOGFLARE_PUBLIC_ACCESS_TOKEN} + LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN} + LOGFLARE_PRIVATE_ACCESS_TOKEN: ${LOGFLARE_PRIVATE_ACCESS_TOKEN} + LOGFLARE_URL: http://${CONTAINER_PREFIX}-analytics:4000 NEXT_PUBLIC_ENABLE_LOGS: true - # Comment to use Big Query backend for analytics NEXT_ANALYTICS_BACKEND_PROVIDER: postgres - # Uncomment to use Big Query backend for analytics - # NEXT_ANALYTICS_BACKEND_PROVIDER: bigquery + SNIPPETS_MANAGEMENT_FOLDER: /app/snippets + EDGE_FUNCTIONS_MANAGEMENT_FOLDER: /app/edge-functions + volumes: + - ./volumes/snippets:/app/snippets:Z + - ./volumes/functions:/app/edge-functions:Z kong: container_name: ${CONTAINER_PREFIX}-kong image: kong:2.8.1 restart: unless-stopped - # ports: - # - ${KONG_HTTP_PORT}:8000/tcp - # - ${KONG_HTTPS_PORT}:8443/tcp expose: - 8000 - 8443 @@ -70,7 +73,7 @@ services: KONG_DECLARATIVE_CONFIG: /home/kong/kong.yml # https://github.com/supabase/cli/issues/14 KONG_DNS_ORDER: LAST,A,CNAME - KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth + KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth,request-termination,ip-restriction KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k SUPABASE_ANON_KEY: ${ANON_KEY} @@ -83,7 +86,7 @@ services: auth: container_name: ${CONTAINER_PREFIX}-auth - image: supabase/gotrue:v2.171.0 + image: supabase/gotrue:v2.186.0 restart: unless-stopped healthcheck: test: @@ -110,27 +113,21 @@ services: GOTRUE_API_HOST: 0.0.0.0 GOTRUE_API_PORT: 9999 API_EXTERNAL_URL: ${API_EXTERNAL_URL} - GOTRUE_DB_DRIVER: postgres GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} - GOTRUE_SITE_URL: ${SITE_URL} GOTRUE_URI_ALLOW_LIST: ${ADDITIONAL_REDIRECT_URLS} GOTRUE_DISABLE_SIGNUP: ${DISABLE_SIGNUP} - GOTRUE_JWT_ADMIN_ROLES: service_role GOTRUE_JWT_AUD: authenticated GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated GOTRUE_JWT_EXP: ${JWT_EXPIRY} GOTRUE_JWT_SECRET: ${JWT_SECRET} - GOTRUE_EXTERNAL_EMAIL_ENABLED: ${ENABLE_EMAIL_SIGNUP} GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: ${ENABLE_ANONYMOUS_USERS} GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM} - # Uncomment to bypass nonce check in ID Token flow. Commonly set to true when using Google Sign In on mobile. # GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: true - # GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED: true # GOTRUE_SMTP_MAX_FREQUENCY: 1s GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL} @@ -143,32 +140,26 @@ services: GOTRUE_MAILER_URLPATHS_CONFIRMATION: ${MAILER_URLPATHS_CONFIRMATION} GOTRUE_MAILER_URLPATHS_RECOVERY: ${MAILER_URLPATHS_RECOVERY} GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE: ${MAILER_URLPATHS_EMAIL_CHANGE} - GOTRUE_EXTERNAL_PHONE_ENABLED: ${ENABLE_PHONE_SIGNUP} GOTRUE_SMS_AUTOCONFIRM: ${ENABLE_PHONE_AUTOCONFIRM} # Uncomment to enable custom access token hook. Please see: https://supabase.com/docs/guides/auth/auth-hooks for full list of hooks and additional details about custom_access_token_hook - # GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED: "true" # GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI: "pg-functions://postgres/public/custom_access_token_hook" # GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_SECRETS: "" - # GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_ENABLED: "true" # GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_URI: "pg-functions://postgres/public/mfa_verification_attempt" - # GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_ENABLED: "true" # GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_URI: "pg-functions://postgres/public/password_verification_attempt" - # GOTRUE_HOOK_SEND_SMS_ENABLED: "false" # GOTRUE_HOOK_SEND_SMS_URI: "pg-functions://postgres/public/custom_access_token_hook" # GOTRUE_HOOK_SEND_SMS_SECRETS: "v1,whsec_VGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgc2hvcnRlciBCYXNlNjQgc3RyaW5n" - # GOTRUE_HOOK_SEND_EMAIL_ENABLED: "false" # GOTRUE_HOOK_SEND_EMAIL_URI: "http://host.docker.internal:54321/functions/v1/email_sender" # GOTRUE_HOOK_SEND_EMAIL_SECRETS: "v1,whsec_VGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgc2hvcnRlciBCYXNlNjQgc3RyaW5n" rest: container_name: ${CONTAINER_PREFIX}-rest - image: postgrest/postgrest:v12.2.11 + image: postgrest/postgrest:v14.5 restart: unless-stopped depends_on: db: @@ -191,8 +182,8 @@ services: realtime: # This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain - container_name: realtime-dev.${CONTAINER_PREFIX}-realtime - image: supabase/realtime:v2.34.47 + container_name: ${CONTAINER_PREFIX}-realtime + image: supabase/realtime:v2.76.5 restart: unless-stopped depends_on: db: @@ -214,8 +205,9 @@ services: "http://localhost:4000/api/tenants/realtime-dev/health" ] timeout: 5s - interval: 5s + interval: 30s retries: 3 + start_period: 10s environment: PORT: 4000 DB_HOST: ${POSTGRES_HOST} @@ -233,14 +225,13 @@ services: APP_NAME: realtime SEED_SELF_HOST: true RUN_JANITOR: true + DISABLE_HEALTHCHECK_LOGGING: "true" # To use S3 backed storage: docker compose -f docker-compose.yml -f docker-compose.s3.yml up storage: container_name: ${CONTAINER_PREFIX}-storage - image: supabase/storage-api:v1.22.7 + image: supabase/storage-api:v1.37.8 restart: unless-stopped - volumes: - - ../files/volumes/storage:/var/lib/storage:z healthcheck: test: [ @@ -265,25 +256,30 @@ services: environment: ANON_KEY: ${ANON_KEY} SERVICE_KEY: ${SERVICE_ROLE_KEY} - POSTGREST_URL: http://rest:3000 + POSTGREST_URL: http://${CONTAINER_PREFIX}-rest:3000 PGRST_JWT_SECRET: ${JWT_SECRET} DATABASE_URL: postgres://supabase_storage_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} FILE_SIZE_LIMIT: 52428800 STORAGE_BACKEND: file + GLOBAL_S3_BUCKET: ${GLOBAL_S3_BUCKET} FILE_STORAGE_BACKEND_PATH: /var/lib/storage - TENANT_ID: stub + TENANT_ID: ${STORAGE_TENANT_ID} # TODO: https://github.com/supabase/storage-api/issues/55 - REGION: stub - GLOBAL_S3_BUCKET: stub + REGION: ${REGION} ENABLE_IMAGE_TRANSFORMATION: "true" - IMGPROXY_URL: http://imgproxy:5001 + IMGPROXY_URL: http://${CONTAINER_PREFIX}-imgproxy:5001 + # S3 protocol endpoint configuration + S3_PROTOCOL_ACCESS_KEY_ID: ${S3_PROTOCOL_ACCESS_KEY_ID} + S3_PROTOCOL_ACCESS_KEY_SECRET: ${S3_PROTOCOL_ACCESS_KEY_SECRET} + volumes: + - ./volumes/storage:/var/lib/storage:z imgproxy: container_name: ${CONTAINER_PREFIX}-imgproxy - image: darthsim/imgproxy:v3.8.0 + image: darthsim/imgproxy:v3.30.1 restart: unless-stopped volumes: - - ../files/volumes/storage:/var/lib/storage:z + - ./volumes/storage:/var/lib/storage:z healthcheck: test: [ @@ -299,10 +295,11 @@ services: IMGPROXY_LOCAL_FILESYSTEM_ROOT: / IMGPROXY_USE_ETAG: "true" IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION} + IMGPROXY_MAX_SRC_RESOLUTION: 16.8 meta: container_name: ${CONTAINER_PREFIX}-meta - image: supabase/postgres-meta:v0.88.9 + image: supabase/postgres-meta:v0.95.2 restart: unless-stopped depends_on: db: @@ -317,24 +314,27 @@ services: PG_META_DB_NAME: ${POSTGRES_DB} PG_META_DB_USER: supabase_admin PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD} + CRYPTO_KEY: ${PG_META_CRYPTO_KEY} functions: container_name: ${CONTAINER_PREFIX}-edge-functions - image: supabase/edge-runtime:v1.67.4 + image: supabase/edge-runtime:v1.70.3 restart: unless-stopped volumes: - ../files/volumes/functions:/home/deno/functions:Z + - deno-cache:/root/.cache/deno depends_on: analytics: condition: service_healthy environment: JWT_SECRET: ${JWT_SECRET} - SUPABASE_URL: http://kong:8000 + SUPABASE_URL: http://${CONTAINER_PREFIX}-kong:8000 SUPABASE_ANON_KEY: ${ANON_KEY} SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY} SUPABASE_DB_URL: postgresql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} # TODO: Allow configuring VERIFY_JWT per function. This PR might help: https://github.com/supabase/cli/pull/786 VERIFY_JWT: "${FUNCTIONS_VERIFY_JWT}" + CONTAINER_PREFIX: ${CONTAINER_PREFIX} command: [ "start", @@ -344,7 +344,7 @@ services: analytics: container_name: ${CONTAINER_PREFIX}-analytics - image: supabase/logflare:1.12.0 + image: supabase/logflare:1.31.2 restart: unless-stopped # ports: # - 4000:4000 @@ -378,7 +378,8 @@ services: DB_PORT: ${POSTGRES_PORT} DB_PASSWORD: ${POSTGRES_PASSWORD} DB_SCHEMA: _analytics - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN} + LOGFLARE_PRIVATE_ACCESS_TOKEN: ${LOGFLARE_PRIVATE_ACCESS_TOKEN} LOGFLARE_SINGLE_TENANT: true LOGFLARE_SUPABASE_MODE: true LOGFLARE_MIN_CLUSTER_SIZE: 1 @@ -394,7 +395,7 @@ services: # Comment out everything below this point if you are using an external Postgres database db: container_name: ${CONTAINER_PREFIX}-db - image: supabase/postgres:15.8.1.060 + image: supabase/postgres:15.8.1.085 restart: unless-stopped volumes: - ../files/volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z @@ -451,7 +452,7 @@ services: vector: container_name: ${CONTAINER_PREFIX}-vector - image: timberio/vector:0.28.1-alpine + image: timberio/vector:0.53.0-alpine restart: unless-stopped volumes: - ../files/volumes/logs/vector.yml:/etc/vector/vector.yml:ro,z @@ -470,7 +471,8 @@ services: interval: 5s retries: 3 environment: - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN} + CONTAINER_PREFIX: ${CONTAINER_PREFIX} command: [ "--config", @@ -482,11 +484,11 @@ services: # Update the DATABASE_URL if you are using an external Postgres database supavisor: container_name: ${CONTAINER_PREFIX}-pooler - image: supabase/supavisor:2.5.1 + image: supabase/supavisor:2.7.4 restart: unless-stopped - ports: # expose supavisor to the host to enable db pooler connection - - ${POSTGRES_PORT}:5432 - - ${POOLER_PROXY_PORT_TRANSACTION}:6543 + expose: # expose supavisor to the host to enable db pooler connection + - ${POSTGRES_PORT} + - ${POOLER_PROXY_PORT_TRANSACTION} volumes: - ../files/volumes/pooler/pooler.exs:/etc/pooler/pooler.exs:ro,z healthcheck: @@ -525,6 +527,7 @@ services: POOLER_DEFAULT_POOL_SIZE: ${POOLER_DEFAULT_POOL_SIZE} POOLER_MAX_CLIENT_CONN: ${POOLER_MAX_CLIENT_CONN} POOLER_POOL_MODE: transaction + DB_POOL_SIZE: ${POOLER_DB_POOL_SIZE} command: [ "/bin/sh", @@ -533,4 +536,5 @@ services: ] volumes: - db-config: \ No newline at end of file + db-config: + deno-cache: \ No newline at end of file diff --git a/blueprints/supabase/template.toml b/blueprints/supabase/template.toml index f70c93ccc..63f808915 100644 --- a/blueprints/supabase/template.toml +++ b/blueprints/supabase/template.toml @@ -3,10 +3,16 @@ main_domain = "${domain}" postgres_password = "${password:32}" dashboard_password = "${password:32}" logflare_api_key = "${password:32}" +logflare_public = "${password:32}, +logflare_private = "${password:32}, secret_key_base = "${password:64}" vault_enc_key = "${password:32}" jwt_secret = "${password:32}" +pg_meta_crypto_key = "${password:32}" container_name_prefix = "${APP_NAME}-supabase" +s3_protocol_id="${password:32}" +s3_protocol_secret="${password:64}" +minio_password="${password:32}" anon_key_payload = """{ "role": "anon", "iss": "supabase", @@ -59,6 +65,7 @@ env = [ 'DASHBOARD_PASSWORD=${dashboard_password}', 'SECRET_KEY_BASE=${secret_key_base}', 'VAULT_ENC_KEY=${vault_enc_key}', +'PG_META_CRYPTO_KEY=${pg_meta_crypto_key}', '', '', '############', @@ -78,6 +85,7 @@ env = [ 'POOLER_DEFAULT_POOL_SIZE=20', 'POOLER_MAX_CLIENT_CONN=100', 'POOLER_TENANT_ID=your-tenant-id', +'POOLER_DB_POOL_SIZE=5', '', '', '############', @@ -159,17 +167,28 @@ env = [ '# Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction', '############', '', -'LOGFLARE_LOGGER_BACKEND_API_KEY=your-super-secret-and-long-logflare-key', -'', -'# Change vector.toml sinks to reflect this change', -'LOGFLARE_API_KEY=${logflare_api_key}', +'LOGFLARE_PUBLIC_ACCESS_TOKEN=${logflare_public}', +'LOGFLARE_PRIVATE_ACCESS_TOKEN=${logflare_private}', '', '# Docker socket location - this value will differ depending on your OS', 'DOCKER_SOCKET_LOCATION=/var/run/docker.sock', '', '# Google Cloud Project details', 'GOOGLE_PROJECT_ID=GOOGLE_PROJECT_ID', -'GOOGLE_PROJECT_NUMBER=GOOGLE_PROJECT_NUMBER'] +'GOOGLE_PROJECT_NUMBER=GOOGLE_PROJECT_NUMBER' +'############', +'# Storage - Configuration for the storage', +'############', +'', +'STORAGE_TENANT_ID=stub', +'GLOBAL_S3_BUCKET=stub', +'REGION=stub', +'S3_PROTOCOL_ACCESS_KEY_ID=${s3_protocol_id}', +'S3_PROTOCOL_ACCESS_KEY_SECRET=${s3_protocol_secret}', +'', +'# Used in docker-compose.s3.yml for minio', +'MINIO_ROOT_USER=supa-storage', +'MINIO_ROOT_PASSWORD=${minio_password}'] [[config.mounts]] filePath = "/volumes/api/kong.yml" @@ -309,7 +328,7 @@ services: ## Secure Realtime routes - name: realtime-v1-ws _comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*' - url: http://realtime-dev.${CONTAINER_PREFIX}-realtime:4000/socket + url: http://realtime:4000/socket protocol: ws routes: - name: realtime-v1-ws @@ -329,7 +348,7 @@ services: - anon - name: realtime-v1-rest _comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*' - url: http://realtime-dev.${CONTAINER_PREFIX}-realtime:4000/api + url: http://realtime:4000/api protocol: http routes: - name: realtime-v1-rest @@ -717,8 +736,7 @@ serve(async () => { [[config.mounts]] filePath = "/volumes/functions/main/index.ts" -content = """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' +content = """import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts' console.log('main function started') @@ -749,7 +767,7 @@ async function verifyJWT(jwt: string): Promise { return true } -serve(async (req: Request) => { +Deno.serve(async (req: Request) => { if (req.method !== 'OPTIONS' && VERIFY_JWT) { try { const token = getAuthToken(req) @@ -823,7 +841,7 @@ sources: docker_host: type: docker_logs exclude_containers: - - ${container_name_prefix}-vector + - supabase-vector transforms: project_logs: @@ -833,7 +851,7 @@ transforms: source: |- .project = "default" .event_message = del(.message) - .appname = replace!(del(.container_name), "${container_name_prefix}", "supabase") + .appname = del(.container_name) del(.container_created_at) del(.container_id) del(.source_type) @@ -847,13 +865,13 @@ transforms: inputs: - project_logs route: - kong: '.appname == "supabase-kong"' - auth: '.appname == "supabase-auth"' - rest: '.appname == "supabase-rest"' - realtime: '.appname == "realtime-dev.${CONTAINER_PREFIX}-realtime"' - storage: '.appname == "supabase-storage"' - functions: '.appname == "supabase-edge-functions"' - db: '.appname == "supabase-db"' + kong: '.appname == "${CONTAINER_PREFIX}-kong"' + auth: '.appname == "${CONTAINER_PREFIX}-auth"' + rest: '.appname == "${CONTAINER_PREFIX}-rest"' + realtime: '.appname == "${CONTAINER_PREFIX}-realtime"' + storage: '.appname == "${CONTAINER_PREFIX}-storage"' + functions: '.appname == "${CONTAINER_PREFIX}-edge-functions"' + db: '.appname == "${CONTAINER_PREFIX}-db"' # Ignores non nginx errors since they are related with kong booting up kong_logs: type: remap @@ -866,10 +884,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 @@ -918,22 +939,35 @@ transforms: parsed, err = parse_regex(.event_message, r'^(?P