From 766d03f013e4b11372f32e6f79094e6b863c6eb5 Mon Sep 17 00:00:00 2001 From: Pratik Borole Date: Sat, 18 May 2024 13:45:12 +0530 Subject: [PATCH] chore: remove supabase selfhost config --- .prettierignore | 2 - docker/.env.example | 104 ------- docker/compose.dev.yaml | 14 - docker/supabase-selfhost.yaml | 388 ------------------------ docker/volumes/api/kong.yml | 223 -------------- docker/volumes/db/init/data.sql | 0 docker/volumes/db/jwt.sql | 5 - docker/volumes/db/logs.sql | 4 - docker/volumes/db/realtime.sql | 4 - docker/volumes/db/roles.sql | 8 - docker/volumes/db/webhooks.sql | 208 ------------- docker/volumes/functions/hello/index.ts | 15 - docker/volumes/functions/main/index.ts | 94 ------ docker/volumes/logs/vector.yml | 232 -------------- useful_commands.md | 4 +- 15 files changed, 2 insertions(+), 1303 deletions(-) delete mode 100644 .prettierignore delete mode 100644 docker/.env.example delete mode 100644 docker/compose.dev.yaml delete mode 100644 docker/supabase-selfhost.yaml delete mode 100644 docker/volumes/api/kong.yml delete mode 100755 docker/volumes/db/init/data.sql delete mode 100644 docker/volumes/db/jwt.sql delete mode 100644 docker/volumes/db/logs.sql delete mode 100644 docker/volumes/db/realtime.sql delete mode 100644 docker/volumes/db/roles.sql delete mode 100644 docker/volumes/db/webhooks.sql delete mode 100644 docker/volumes/functions/hello/index.ts delete mode 100644 docker/volumes/functions/main/index.ts delete mode 100644 docker/volumes/logs/vector.yml diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index f13ecd5..0000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -# required in order for supabase-kong to work -docker/volumes/api/kong.yml diff --git a/docker/.env.example b/docker/.env.example deleted file mode 100644 index cdc6a10..0000000 --- a/docker/.env.example +++ /dev/null @@ -1,104 +0,0 @@ -############ -# Secrets -# YOU MUST CHANGE THESE BEFORE GOING INTO PRODUCTION -############ - -POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password -JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long -ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE -SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q -DASHBOARD_USERNAME=supabase -DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated - -############ -# Database - You can change these to any PostgreSQL database that has logical replication enabled. -############ - -POSTGRES_HOST=db -POSTGRES_DB=postgres -POSTGRES_PORT=5432 -# default user is postgres - -############ -# API Proxy - Configuration for the Kong Reverse proxy. -############ - -KONG_HTTP_PORT=8000 -KONG_HTTPS_PORT=8443 - - -############ -# API - Configuration for PostgREST. -############ - -PGRST_DB_SCHEMAS=public,storage,graphql_public - - -############ -# Auth - Configuration for the GoTrue authentication server. -############ - -## General -SITE_URL=http://localhost:3000 -ADDITIONAL_REDIRECT_URLS= -JWT_EXPIRY=3600 -DISABLE_SIGNUP=false -API_EXTERNAL_URL=http://localhost:8000 - -## Mailer Config -MAILER_URLPATHS_CONFIRMATION="/auth/v1/verify" -MAILER_URLPATHS_INVITE="/auth/v1/verify" -MAILER_URLPATHS_RECOVERY="/auth/v1/verify" -MAILER_URLPATHS_EMAIL_CHANGE="/auth/v1/verify" - -## Email auth -ENABLE_EMAIL_SIGNUP=true -ENABLE_EMAIL_AUTOCONFIRM=false -SMTP_ADMIN_EMAIL=admin@example.com -SMTP_HOST=supabase-mail -SMTP_PORT=2500 -SMTP_USER=fake_mail_user -SMTP_PASS=fake_mail_password -SMTP_SENDER_NAME=fake_sender - -## Phone auth -ENABLE_PHONE_SIGNUP=true -ENABLE_PHONE_AUTOCONFIRM=true - - -############ -# Studio - Configuration for the Dashboard -############ - -STUDIO_DEFAULT_ORGANIZATION=Default Organization -STUDIO_DEFAULT_PROJECT=Default Project - -STUDIO_PORT=3000 -# replace if you intend to use Studio outside of localhost -SUPABASE_PUBLIC_URL=http://localhost:8000 - -# Enable webp support -IMGPROXY_ENABLE_WEBP_DETECTION=true - -############ -# Functions - Configuration for Functions -############ -# NOTE: VERIFY_JWT applies to all functions. Per-function VERIFY_JWT is not supported yet. -FUNCTIONS_VERIFY_JWT=false - -############ -# Logs - Configuration for Logflare -# 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=your-super-secret-and-long-logflare-key - -# 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 diff --git a/docker/compose.dev.yaml b/docker/compose.dev.yaml deleted file mode 100644 index 140b7d5..0000000 --- a/docker/compose.dev.yaml +++ /dev/null @@ -1,14 +0,0 @@ -version: '3.8' - -include: - - supabase-selfhost.yaml -services: - app: - container_name: rearwing-dev - build: - context: .. - dockerfile: Dockerfile.dev - ports: - - "8081:8081" - env_file: - - .env diff --git a/docker/supabase-selfhost.yaml b/docker/supabase-selfhost.yaml deleted file mode 100644 index 28c6654..0000000 --- a/docker/supabase-selfhost.yaml +++ /dev/null @@ -1,388 +0,0 @@ -version: "3.8" -services: - studio: - container_name: supabase-studio - image: supabase/studio:20240101-8e4a094 - restart: unless-stopped - healthcheck: - test: - [ - "CMD", - "node", - "-e", - "require('http').get('http://localhost:3000/api/profile', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})", - ] - timeout: 5s - interval: 5s - retries: 3 - depends_on: - analytics: - condition: service_healthy - environment: - STUDIO_PG_META_URL: http://meta:8080 - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - - DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION} - DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT} - - SUPABASE_URL: http://kong:8000 - SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL} - SUPABASE_ANON_KEY: ${ANON_KEY} - SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} - - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} - LOGFLARE_URL: http://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 - - kong: - container_name: supabase-kong - image: kong:2.8.1 - restart: unless-stopped - # https://unix.stackexchange.com/a/294837 - entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start' - ports: - - ${KONG_HTTP_PORT}:8000/tcp - - ${KONG_HTTPS_PORT}:8443/tcp - depends_on: - analytics: - condition: service_healthy - environment: - KONG_DATABASE: "off" - 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_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k - KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k - SUPABASE_ANON_KEY: ${ANON_KEY} - SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} - DASHBOARD_USERNAME: ${DASHBOARD_USERNAME} - DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD} - volumes: - # https://github.com/supabase/supabase/issues/12661 - - ./volumes/api/kong.yml:/home/kong/temp.yml:ro - - auth: - container_name: supabase-auth - image: supabase/gotrue:v2.132.3 - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - analytics: - condition: service_healthy - healthcheck: - test: - [ - "CMD", - "wget", - "--no-verbose", - "--tries=1", - "--spider", - "http://localhost:9999/health", - ] - timeout: 5s - interval: 5s - retries: 3 - restart: unless-stopped - environment: - 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_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM} - # GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED: true - # GOTRUE_SMTP_MAX_FREQUENCY: 1s - GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL} - GOTRUE_SMTP_HOST: ${SMTP_HOST} - GOTRUE_SMTP_PORT: ${SMTP_PORT} - GOTRUE_SMTP_USER: ${SMTP_USER} - GOTRUE_SMTP_PASS: ${SMTP_PASS} - GOTRUE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME} - GOTRUE_MAILER_URLPATHS_INVITE: ${MAILER_URLPATHS_INVITE} - 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} - - rest: - container_name: supabase-rest - image: postgrest/postgrest:v12.0.1 - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - analytics: - condition: service_healthy - restart: unless-stopped - environment: - PGRST_DB_URI: postgres://authenticator:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} - PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS} - PGRST_DB_ANON_ROLE: anon - PGRST_JWT_SECRET: ${JWT_SECRET} - PGRST_DB_USE_LEGACY_GUCS: "false" - PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET} - PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY} - command: "postgrest" - - realtime: - # This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain - container_name: realtime-dev.supabase-realtime - image: supabase/realtime:v2.25.50 - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - analytics: - condition: service_healthy - healthcheck: - test: ["CMD", "bash", "-c", "printf \\0 > /dev/tcp/localhost/4000"] - timeout: 5s - interval: 5s - retries: 3 - restart: unless-stopped - environment: - PORT: 4000 - DB_HOST: ${POSTGRES_HOST} - DB_PORT: ${POSTGRES_PORT} - DB_USER: supabase_admin - DB_PASSWORD: ${POSTGRES_PASSWORD} - DB_NAME: ${POSTGRES_DB} - DB_AFTER_CONNECT_QUERY: "SET search_path TO _realtime" - DB_ENC_KEY: supabaserealtime - API_JWT_SECRET: ${JWT_SECRET} - FLY_ALLOC_ID: fly123 - FLY_APP_NAME: realtime - SECRET_KEY_BASE: UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq - ERL_AFLAGS: -proto_dist inet_tcp - ENABLE_TAILSCALE: "false" - DNS_NODES: "''" - command: > - sh -c "/app/bin/migrate && /app/bin/realtime eval 'Realtime.Release.seeds(Realtime.Repo)' && /app/bin/server" - - storage: - container_name: supabase-storage - image: supabase/storage-api:v0.46.4 - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - rest: - condition: service_started - imgproxy: - condition: service_started - healthcheck: - test: - [ - "CMD", - "wget", - "--no-verbose", - "--tries=1", - "--spider", - "http://localhost:5000/status", - ] - timeout: 5s - interval: 5s - retries: 3 - restart: unless-stopped - environment: - ANON_KEY: ${ANON_KEY} - SERVICE_KEY: ${SERVICE_ROLE_KEY} - POSTGREST_URL: http://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 - FILE_STORAGE_BACKEND_PATH: /var/lib/storage - TENANT_ID: stub - # TODO: https://github.com/supabase/storage-api/issues/55 - REGION: stub - GLOBAL_S3_BUCKET: stub - ENABLE_IMAGE_TRANSFORMATION: "true" - IMGPROXY_URL: http://imgproxy:5001 - volumes: - - ./volumes/storage:/var/lib/storage:z - - imgproxy: - container_name: supabase-imgproxy - image: darthsim/imgproxy:v3.8.0 - healthcheck: - test: ["CMD", "imgproxy", "health"] - timeout: 5s - interval: 5s - retries: 3 - environment: - IMGPROXY_BIND: ":5001" - IMGPROXY_LOCAL_FILESYSTEM_ROOT: / - IMGPROXY_USE_ETAG: "true" - IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION} - volumes: - - ./volumes/storage:/var/lib/storage:z - - meta: - container_name: supabase-meta - image: supabase/postgres-meta:v0.80.0 - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - analytics: - condition: service_healthy - restart: unless-stopped - environment: - PG_META_PORT: 8080 - PG_META_DB_HOST: ${POSTGRES_HOST} - PG_META_DB_PORT: ${POSTGRES_PORT} - PG_META_DB_NAME: ${POSTGRES_DB} - PG_META_DB_USER: supabase_admin - PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD} - - functions: - container_name: supabase-edge-functions - image: supabase/edge-runtime:v1.33.5 - restart: unless-stopped - depends_on: - analytics: - condition: service_healthy - environment: - JWT_SECRET: ${JWT_SECRET} - SUPABASE_URL: http://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}" - volumes: - - ./volumes/functions:/home/deno/functions:Z - command: - - start - - --main-service - - /home/deno/functions/main - - analytics: - container_name: supabase-analytics - image: supabase/logflare:1.4.0 - healthcheck: - test: ["CMD", "curl", "http://localhost:4000/health"] - timeout: 5s - interval: 5s - retries: 10 - restart: unless-stopped - depends_on: - db: - # Disable this if you are using an external Postgres database - condition: service_healthy - # Uncomment to use Big Query backend for analytics - # volumes: - # - type: bind - # source: ${PWD}/gcloud.json - # target: /opt/app/rel/logflare/bin/gcloud.json - # read_only: true - environment: - LOGFLARE_NODE_HOST: 127.0.0.1 - DB_USERNAME: supabase_admin - DB_DATABASE: ${POSTGRES_DB} - DB_HOSTNAME: ${POSTGRES_HOST} - DB_PORT: ${POSTGRES_PORT} - DB_PASSWORD: ${POSTGRES_PASSWORD} - DB_SCHEMA: _analytics - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} - LOGFLARE_SINGLE_TENANT: true - LOGFLARE_SUPABASE_MODE: true - - # Comment variables to use Big Query backend for analytics - POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} - POSTGRES_BACKEND_SCHEMA: _analytics - LOGFLARE_FEATURE_FLAG_OVERRIDE: multibackend=true - # Uncomment to use Big Query backend for analytics - # GOOGLE_PROJECT_ID: ${GOOGLE_PROJECT_ID} - # GOOGLE_PROJECT_NUMBER: ${GOOGLE_PROJECT_NUMBER} - ports: - - 4000:4000 - - # Comment out everything below this point if you are using an external Postgres database - db: - container_name: supabase-db - image: supabase/postgres:15.1.0.147 - healthcheck: - test: pg_isready -U postgres -h localhost - interval: 5s - timeout: 5s - retries: 10 - depends_on: - vector: - condition: service_healthy - command: - - postgres - - -c - - config_file=/etc/postgresql/postgresql.conf - - -c - - log_min_messages=fatal # prevents Realtime polling queries from appearing in logs - restart: unless-stopped - ports: - # Pass down internal port because it's set dynamically by other services - - ${POSTGRES_PORT}:${POSTGRES_PORT} - environment: - POSTGRES_HOST: /var/run/postgresql - PGPORT: ${POSTGRES_PORT} - POSTGRES_PORT: ${POSTGRES_PORT} - PGPASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - PGDATABASE: ${POSTGRES_DB} - POSTGRES_DB: ${POSTGRES_DB} - JWT_SECRET: ${JWT_SECRET} - JWT_EXP: ${JWT_EXPIRY} - volumes: - - ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z - # Must be superuser to create event trigger - - ./volumes/db/webhooks.sql:/docker-entrypoint-initdb.d/init-scripts/98-webhooks.sql:Z - # Must be superuser to alter reserved role - - ./volumes/db/roles.sql:/docker-entrypoint-initdb.d/init-scripts/99-roles.sql:Z - # Initialize the database settings with JWT_SECRET and JWT_EXP - - ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z - # PGDATA directory is persisted between restarts - - ./volumes/db/data:/var/lib/postgresql/data:Z - # Changes required for Analytics support - - ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z - - vector: - container_name: supabase-vector - image: timberio/vector:0.28.1-alpine - healthcheck: - test: - [ - "CMD", - "wget", - "--no-verbose", - "--tries=1", - "--spider", - "http://vector:9001/health", - ] - timeout: 5s - interval: 5s - retries: 3 - volumes: - - ./volumes/logs/vector.yml:/etc/vector/vector.yml:ro - - ${DOCKER_SOCKET_LOCATION}:/var/run/docker.sock:ro - - command: ["--config", "etc/vector/vector.yml"] diff --git a/docker/volumes/api/kong.yml b/docker/volumes/api/kong.yml deleted file mode 100644 index 4a07995..0000000 --- a/docker/volumes/api/kong.yml +++ /dev/null @@ -1,223 +0,0 @@ -_format_version: '2.1' -_transform: true - -### -### Consumers / Users -### -consumers: - - username: DASHBOARD - - username: anon - keyauth_credentials: - - key: $SUPABASE_ANON_KEY - - username: service_role - keyauth_credentials: - - key: $SUPABASE_SERVICE_KEY - -### -### Access Control List -### -acls: - - consumer: anon - group: anon - - consumer: service_role - group: admin - -### -### Dashboard credentials -### -basicauth_credentials: -- consumer: DASHBOARD - username: $DASHBOARD_USERNAME - password: $DASHBOARD_PASSWORD - - -### -### API Routes -### -services: - - ## Open Auth routes - - name: auth-v1-open - url: http://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://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://auth:9999/authorize - routes: - - name: auth-v1-open-authorize - strip_path: true - paths: - - /auth/v1/authorize - plugins: - - name: cors - - ## Secure Auth routes - - name: auth-v1 - _comment: 'GoTrue: /auth/v1/* -> http://auth:9999/*' - url: http://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 - - ## Secure REST routes - - name: rest-v1 - _comment: 'PostgREST: /rest/v1/* -> http://rest:3000/*' - url: http://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 - - ## Secure GraphQL routes - - name: graphql-v1 - _comment: 'PostgREST: /graphql/v1/* -> http://rest:3000/rpc/graphql' - url: http://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 - - ## Secure Realtime routes - - name: realtime-v1 - _comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*' - url: http://realtime-dev.supabase-realtime:4000/socket/ - routes: - - name: realtime-v1-all - 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 - - ## Storage routes: the storage server manages its own auth - - name: storage-v1 - _comment: 'Storage: /storage/v1/* -> http://storage:5000/*' - url: http://storage:5000/ - routes: - - name: storage-v1-all - strip_path: true - paths: - - /storage/v1/ - plugins: - - name: cors - - ## Edge Functions routes - - name: functions-v1 - _comment: 'Edge Functions: /functions/v1/* -> http://functions:9000/*' - url: http://functions:9000/ - routes: - - name: functions-v1-all - strip_path: true - paths: - - /functions/v1/ - plugins: - - 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/ - - ## Secure Database routes - - name: meta - _comment: 'pg-meta: /pg/* -> http://pg-meta:8080/*' - url: http://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 - - ## Protected Dashboard - catch all remaining routes - - name: dashboard - _comment: 'Studio: /* -> http://studio:3000/*' - url: http://studio:3000/ - routes: - - name: dashboard-all - strip_path: true - paths: - - / - plugins: - - name: cors - - name: basic-auth - config: - hide_credentials: true diff --git a/docker/volumes/db/init/data.sql b/docker/volumes/db/init/data.sql deleted file mode 100755 index e69de29..0000000 diff --git a/docker/volumes/db/jwt.sql b/docker/volumes/db/jwt.sql deleted file mode 100644 index cfd3b16..0000000 --- a/docker/volumes/db/jwt.sql +++ /dev/null @@ -1,5 +0,0 @@ -\set jwt_secret `echo "$JWT_SECRET"` -\set jwt_exp `echo "$JWT_EXP"` - -ALTER DATABASE postgres SET "app.settings.jwt_secret" TO :'jwt_secret'; -ALTER DATABASE postgres SET "app.settings.jwt_exp" TO :'jwt_exp'; diff --git a/docker/volumes/db/logs.sql b/docker/volumes/db/logs.sql deleted file mode 100644 index 22fc247..0000000 --- a/docker/volumes/db/logs.sql +++ /dev/null @@ -1,4 +0,0 @@ -\set pguser `echo "$POSTGRES_USER"` - -create schema if not exists _analytics; -alter schema _analytics owner to :pguser; diff --git a/docker/volumes/db/realtime.sql b/docker/volumes/db/realtime.sql deleted file mode 100644 index 4d4b9ff..0000000 --- a/docker/volumes/db/realtime.sql +++ /dev/null @@ -1,4 +0,0 @@ -\set pguser `echo "$POSTGRES_USER"` - -create schema if not exists _realtime; -alter schema _realtime owner to :pguser; diff --git a/docker/volumes/db/roles.sql b/docker/volumes/db/roles.sql deleted file mode 100644 index 8f7161a..0000000 --- a/docker/volumes/db/roles.sql +++ /dev/null @@ -1,8 +0,0 @@ --- NOTE: change to your own passwords for production environments -\set pgpass `echo "$POSTGRES_PASSWORD"` - -ALTER USER authenticator WITH PASSWORD :'pgpass'; -ALTER USER pgbouncer WITH PASSWORD :'pgpass'; -ALTER USER supabase_auth_admin WITH PASSWORD :'pgpass'; -ALTER USER supabase_functions_admin WITH PASSWORD :'pgpass'; -ALTER USER supabase_storage_admin WITH PASSWORD :'pgpass'; diff --git a/docker/volumes/db/webhooks.sql b/docker/volumes/db/webhooks.sql deleted file mode 100644 index 5837b86..0000000 --- a/docker/volumes/db/webhooks.sql +++ /dev/null @@ -1,208 +0,0 @@ -BEGIN; - -- Create pg_net extension - CREATE EXTENSION IF NOT EXISTS pg_net SCHEMA extensions; - -- Create supabase_functions schema - CREATE SCHEMA supabase_functions AUTHORIZATION supabase_admin; - GRANT USAGE ON SCHEMA supabase_functions TO postgres, anon, authenticated, service_role; - ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role; - ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS TO postgres, anon, authenticated, service_role; - ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role; - -- supabase_functions.migrations definition - CREATE TABLE supabase_functions.migrations ( - version text PRIMARY KEY, - inserted_at timestamptz NOT NULL DEFAULT NOW() - ); - -- Initial supabase_functions migration - INSERT INTO supabase_functions.migrations (version) VALUES ('initial'); - -- supabase_functions.hooks definition - CREATE TABLE supabase_functions.hooks ( - id bigserial PRIMARY KEY, - hook_table_id integer NOT NULL, - hook_name text NOT NULL, - created_at timestamptz NOT NULL DEFAULT NOW(), - request_id bigint - ); - CREATE INDEX supabase_functions_hooks_request_id_idx ON supabase_functions.hooks USING btree (request_id); - CREATE INDEX supabase_functions_hooks_h_table_id_h_name_idx ON supabase_functions.hooks USING btree (hook_table_id, hook_name); - COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.'; - CREATE FUNCTION supabase_functions.http_request() - RETURNS trigger - LANGUAGE plpgsql - AS $function$ - DECLARE - request_id bigint; - payload jsonb; - url text := TG_ARGV[0]::text; - method text := TG_ARGV[1]::text; - headers jsonb DEFAULT '{}'::jsonb; - params jsonb DEFAULT '{}'::jsonb; - timeout_ms integer DEFAULT 1000; - BEGIN - IF url IS NULL OR url = 'null' THEN - RAISE EXCEPTION 'url argument is missing'; - END IF; - - IF method IS NULL OR method = 'null' THEN - RAISE EXCEPTION 'method argument is missing'; - END IF; - - IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN - headers = '{"Content-Type": "application/json"}'::jsonb; - ELSE - headers = TG_ARGV[2]::jsonb; - END IF; - - IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN - params = '{}'::jsonb; - ELSE - params = TG_ARGV[3]::jsonb; - END IF; - - IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN - timeout_ms = 1000; - ELSE - timeout_ms = TG_ARGV[4]::integer; - END IF; - - CASE - WHEN method = 'GET' THEN - SELECT http_get INTO request_id FROM net.http_get( - url, - params, - headers, - timeout_ms - ); - WHEN method = 'POST' THEN - payload = jsonb_build_object( - 'old_record', OLD, - 'record', NEW, - 'type', TG_OP, - 'table', TG_TABLE_NAME, - 'schema', TG_TABLE_SCHEMA - ); - - SELECT http_post INTO request_id FROM net.http_post( - url, - payload, - params, - headers, - timeout_ms - ); - ELSE - RAISE EXCEPTION 'method argument % is invalid', method; - END CASE; - - INSERT INTO supabase_functions.hooks - (hook_table_id, hook_name, request_id) - VALUES - (TG_RELID, TG_NAME, request_id); - - RETURN NEW; - END - $function$; - -- Supabase super admin - DO - $$ - BEGIN - IF NOT EXISTS ( - SELECT 1 - FROM pg_roles - WHERE rolname = 'supabase_functions_admin' - ) - THEN - CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; - END IF; - END - $$; - GRANT ALL PRIVILEGES ON SCHEMA supabase_functions TO supabase_functions_admin; - GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA supabase_functions TO supabase_functions_admin; - GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA supabase_functions TO supabase_functions_admin; - ALTER USER supabase_functions_admin SET search_path = "supabase_functions"; - ALTER table "supabase_functions".migrations OWNER TO supabase_functions_admin; - ALTER table "supabase_functions".hooks OWNER TO supabase_functions_admin; - ALTER function "supabase_functions".http_request() OWNER TO supabase_functions_admin; - GRANT supabase_functions_admin TO postgres; - -- Remove unused supabase_pg_net_admin role - DO - $$ - BEGIN - IF EXISTS ( - SELECT 1 - FROM pg_roles - WHERE rolname = 'supabase_pg_net_admin' - ) - THEN - REASSIGN OWNED BY supabase_pg_net_admin TO supabase_admin; - DROP OWNED BY supabase_pg_net_admin; - DROP ROLE supabase_pg_net_admin; - END IF; - END - $$; - -- pg_net grants when extension is already enabled - DO - $$ - BEGIN - IF EXISTS ( - SELECT 1 - FROM pg_extension - WHERE extname = 'pg_net' - ) - THEN - GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - END IF; - END - $$; - -- Event trigger for pg_net - CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access() - RETURNS event_trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF EXISTS ( - SELECT 1 - FROM pg_event_trigger_ddl_commands() AS ev - JOIN pg_extension AS ext - ON ev.objid = ext.oid - WHERE ext.extname = 'pg_net' - ) - THEN - GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - END IF; - END; - $$; - COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net'; - DO - $$ - BEGIN - IF NOT EXISTS ( - SELECT 1 - FROM pg_event_trigger - WHERE evtname = 'issue_pg_net_access' - ) THEN - CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end WHEN TAG IN ('CREATE EXTENSION') - EXECUTE PROCEDURE extensions.grant_pg_net_access(); - END IF; - END - $$; - INSERT INTO supabase_functions.migrations (version) VALUES ('20210809183423_update_grants'); - ALTER function supabase_functions.http_request() SECURITY DEFINER; - ALTER function supabase_functions.http_request() SET search_path = supabase_functions; - REVOKE ALL ON FUNCTION supabase_functions.http_request() FROM PUBLIC; - GRANT EXECUTE ON FUNCTION supabase_functions.http_request() TO postgres, anon, authenticated, service_role; -COMMIT; diff --git a/docker/volumes/functions/hello/index.ts b/docker/volumes/functions/hello/index.ts deleted file mode 100644 index 0447d32..0000000 --- a/docker/volumes/functions/hello/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Follow this setup guide to integrate the Deno language server with your editor: -// 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 () => { - return new Response(`"Hello from Edge Functions!"`, { - headers: { "Content-Type": "application/json" }, - }); -}); - -// To invoke: -// curl 'http://localhost:/functions/v1/hello' \ -// --header 'Authorization: Bearer ' diff --git a/docker/volumes/functions/main/index.ts b/docker/volumes/functions/main/index.ts deleted file mode 100644 index f406e21..0000000 --- a/docker/volumes/functions/main/index.ts +++ /dev/null @@ -1,94 +0,0 @@ -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"); - -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; -} - -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" }, - }); - } -}); diff --git a/docker/volumes/logs/vector.yml b/docker/volumes/logs/vector.yml deleted file mode 100644 index ef5cdbe..0000000 --- a/docker/volumes/logs/vector.yml +++ /dev/null @@ -1,232 +0,0 @@ -api: - enabled: true - address: 0.0.0.0:9001 - -sources: - docker_host: - type: docker_logs - exclude_containers: - - supabase-vector - -transforms: - project_logs: - type: remap - inputs: - - docker_host - source: |- - .project = "default" - .event_message = del(.message) - .appname = del(.container_name) - del(.container_created_at) - del(.container_id) - del(.source_type) - del(.stream) - del(.label) - del(.image) - del(.host) - del(.stream) - router: - type: route - inputs: - - project_logs - route: - kong: '.appname == "supabase-kong"' - auth: '.appname == "supabase-auth"' - rest: '.appname == "supabase-rest"' - realtime: '.appname == "supabase-realtime"' - storage: '.appname == "supabase-storage"' - functions: '.appname == "supabase-functions"' - db: '.appname == "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.request.method = req.method - .metadata.request.path = req.path - .metadata.request.protocol = req.protocol - .metadata.response.status_code = req.status - } - 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