diff --git a/.gitignore b/.gitignore index 5dca0196d5baa8c7a308b58ba4adbe1d2b06a7bb..d74c5012ce80d2c9216b569552c2b93cc066840a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .vscode -**/*.code-workspace \ No newline at end of file +**/*.code-workspace +.env +supabase/volumes +supabase/.env \ No newline at end of file diff --git a/backend/defense_finder_api/settings.py b/backend/defense_finder_api/settings.py index 878ff3ed4bf38a7154acc01cba7f3e4143b35561..0c01396c6fef648cbc70b43eb0d582239f33cbe2 100644 --- a/backend/defense_finder_api/settings.py +++ b/backend/defense_finder_api/settings.py @@ -93,13 +93,13 @@ WSGI_APPLICATION = "defense_finder_api.wsgi.application" DATABASES = { "default": env.db(), - # { + # "default": { # "ENGINE": "django.db.backends.postgresql", - # "NAME": "df-db", - # "USER": "df", - # "PASSWORD": "password", - # "HOST": "postgresql", - # "PORT": "5432", + # "NAME": "postgres", + # "USER": "postgres", + # "PASSWORD": "postgres", + # "HOST": "127.0.0.1", + # "PORT": "54322", # } } diff --git a/docker-compose.yml b/docker-compose.yml index 93062fcebf0b469ab4236c069891922be368f362..bb4f7c790b997655b59658df48fd23e5b265efde 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,7 @@ version: "3.9" +include: + - supabase/docker-compose.yml + services: defense-finder-api: build: ./backend @@ -6,98 +9,99 @@ services: - sh - -c - > - python manage.py runserver 0.0.0.0:8000 + python manage.py runserver 0.0.0.0:8001 volumes: - ./backend/:/code ports: - - 8000:8000 + - 8001:8001 environment: DEBUG: True + DATABASE_URL: "psql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}" depends_on: - - postgresql - labels: - - "traefik.enable=true" - - "traefik.docker.network=main" - - "traefik.http.routers.backend.rule=Host(`localhost`) && PathPrefix(`/api`)" - - "traefik.http.routers.backend.entrypoints=web" - - "traefik.http.services.backend-service.loadbalancer.server.port=8000" + - db + # labels: + # - "traefik.enable=true" + # - "traefik.docker.network=main" + # - "traefik.http.routers.backend.rule=Host(`localhost`) && PathPrefix(`/api`)" + # - "traefik.http.routers.backend.entrypoints=web" + # - "traefik.http.services.backend-service.loadbalancer.server.port=8000" # - "traefik.http.routers.backendadmin.rule=Host(`localhost`) && PathPrefix(`/admin`)" # - "traefik.http.routers.backendadmin.entrypoints=web" # - "traefik.http.services.backendadmin-service.loadbalancer.server.port=8000" # - "traefik.http.middlewares.strip-backend.stripprefix.prefixes=/api" # - "traefik.http.routers.backend.middlewares=strip-backend" - networks: - - main + # networks: + # - main - nuxt: - build: - context: ./frontend - target: dev - container_name: nuxt - volumes: - - ./frontend/:/usr/src/app - - defensefinder_node_modules:/usr/src/app/node_modules - - /usr/src/app/.nuxt - ports: - - "3000:3000" - - "24678:24678" - - "4000:4000" - depends_on: - - defense-finder-api - labels: - - "traefik.enable=true" - - "traefik.docker.network=main" + # nuxt: + # build: + # context: ./frontend + # target: dev + # container_name: nuxt + # volumes: + # - ./frontend/:/usr/src/app + # - defensefinder_node_modules:/usr/src/app/node_modules + # - /usr/src/app/.nuxt + # ports: + # - "3000:3000" + # - "24678:24678" + # - "4000:4000" + # depends_on: + # - defense-finder-api + # labels: + # - "traefik.enable=true" + # - "traefik.docker.network=main" - - "traefik.http.routers.nuxt.service=nuxt-service" - - "traefik.http.routers.nuxt.rule=Host(`localhost`)" - - "traefik.http.routers.nuxt.entrypoints=web" - - "traefik.http.services.nuxt-service.loadbalancer.server.port=3000" + # - "traefik.http.routers.nuxt.service=nuxt-service" + # - "traefik.http.routers.nuxt.rule=Host(`localhost`)" + # - "traefik.http.routers.nuxt.entrypoints=web" + # - "traefik.http.services.nuxt-service.loadbalancer.server.port=3000" # - "traefik.http.routers.nuxtsocket.service=nuxtsocket-service" # - "traefik.http.routers.nuxtsocket.rule=Host(`localhost`) && PathPrefix(`/_nuxt/`)" # - "traefik.http.routers.nuxtsocket.entrypoints=web" # - "traefik.http.services.nuxtsocket-service.loadbalancer.server.port=24678" - networks: - - main + # networks: + # - supabase_network_supabase - postgresql: - image: postgres:15.2-alpine - container_name: db - shm_size: "2gb" - ports: - - "5434:5432" - environment: - POSTGRES_PASSWORD: password - POSTGRES_USER: "df" - POSTGRES_DB: "df-db" + # postgresql: + # image: postgres:15.2-alpine + # container_name: db + # shm_size: "2gb" + # ports: + # - "5434:5432" + # environment: + # POSTGRES_PASSWORD: password + # POSTGRES_USER: "df" + # POSTGRES_DB: "df-db" - volumes: - - defensefinder_db:/var/lib/postgresql/data - networks: - - main + # volumes: + # - defensefinder_db:/var/lib/postgresql/data + # networks: + # - main - traefik: - image: traefik:v2.9 - command: - - "--log.level=DEBUG" - - "--api.insecure=true" - - "--providers.docker=true" - - "--providers.docker.exposedbydefault=true" - - "--entrypoints.web.address=:80" + # traefik: + # image: traefik:v2.9 + # command: + # - "--log.level=DEBUG" + # - "--api.insecure=true" + # - "--providers.docker=true" + # - "--providers.docker.exposedbydefault=true" + # - "--entrypoints.web.address=:80" - ports: - - "8082:80" - - "8080:8080" - volumes: - - "/var/run/docker.sock:/var/run/docker.sock:ro" - networks: - - main + # ports: + # - "8082:80" + # - "8080:8080" + # volumes: + # - "/var/run/docker.sock:/var/run/docker.sock:ro" + # networks: + # - main volumes: defensefinder_db: defensefinder_node_modules: -networks: - main: - driver: bridge +# networks: +# main: +# driver: bridge diff --git a/supabase/docker-compose.yml b/supabase/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..4ac4d54d570405711376ee23e909c5219e58782f --- /dev/null +++ b/supabase/docker-compose.yml @@ -0,0 +1,405 @@ +# Usage +# Start: docker compose up +# With helpers: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml up +# Stop: docker compose down +# Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans + +name: supabase +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" + + # To use S3 backed storage: docker compose -f docker-compose.yml -f docker-compose.s3.yml up + 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.75.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" ]