diff --git a/apps/docs/spec/analytics_v0_config.yaml b/apps/docs/spec/analytics_v0_config.yaml index 8d9664f327..1207dc95ae 100644 --- a/apps/docs/spec/analytics_v0_config.yaml +++ b/apps/docs/spec/analytics_v0_config.yaml @@ -26,15 +26,24 @@ parameters: type: 'boolean' description: | This is will seed a singular user into the database, and will disable browser authentication. All browser usage will default to this user. Inviting team users and other team-related functionality is currently not supported for self-hosted. Logflare self-hosted is currently intended for single-user experience only. - - id: 'LOGFLARE_API_KEY' # {string} A unique identifier for this param. - title: 'LOGFLARE_API_KEY' # {string} Any name. + - id: 'LOGFLARE_PUBLIC_ACCESS_TOKEN' # {string} A unique identifier for this param. + title: 'LOGFLARE_PUBLIC_ACCESS_TOKEN' # {string} Any name. tags: ['general'] # {string[]} These tags are useful for grouping parameters links: [] # {string[]} These tags are useful for grouping parameters required: true default: '' type: 'string' description: | - Allows you to pass in an API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. It is advised to use the UI to configure the access tokens instead. If this value is not provided, the default API key will be automatically generated. + Allows you to pass in an API key that will used for authentication for ingestion only. This is intended for programmatic usage where an external program sets the API key. A default ingestion API key will be automatically generated. + - id: 'LOGFLARE_PRIVATE_ACCESS_TOKEN' # {string} A unique identifier for this param. + title: 'LOGFLARE_PRIVATE_ACCESS_TOKEN' # {string} Any name. + tags: ['general'] # {string[]} These tags are useful for grouping parameters + links: [] # {string[]} These tags are useful for grouping parameters + required: true + default: '' + type: 'string' + description: | + Allows you to pass in an Management API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. This key is considered secret. - id: 'LOGFLARE_SUPABASE_MODE' # {string} A unique identifier for this param. title: 'LOGFLARE_SUPABASE_MODE' # {string} Any name. tags: ['general'] # {string[]} These tags are useful for grouping parameters diff --git a/apps/docs/spec/functions_v0_config.yaml b/apps/docs/spec/functions_v0_config.yaml index 889b31075d..bae7d2557b 100644 --- a/apps/docs/spec/functions_v0_config.yaml +++ b/apps/docs/spec/functions_v0_config.yaml @@ -14,24 +14,3 @@ info: - id: general title: General Settings description: General server settings. - -# This section is an array of public functions which a user might need to execute. -parameters: - - id: 'LOGFLARE_SINGLE_TENANT' # {string} A unique identifier for this param. - title: 'LOGFLARE_SINGLE_TENANT' # {string} Any name. - tags: ['general'] # {string[]} These tags are useful for grouping parameters - links: [] # {string[]} These tags are useful for grouping parameters - required: true - default: 'true' - type: 'boolean' - description: | - This is will seed a singular user into the database, and will disable browser authentication. All browser usage will default to this user. Inviting team users and other team-related functionality is currently not supported for self-hosted. Logflare self-hosted is currently intended for single-user experience only. - - id: 'LOGFLARE_API_KEY' # {string} A unique identifier for this param. - title: 'LOGFLARE_API_KEY' # {string} Any name. - tags: ['general'] # {string[]} These tags are useful for grouping parameters - links: [] # {string[]} These tags are useful for grouping parameters - required: true - default: '' - type: 'string' - description: | - Allows you to pass in an API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. It is advised to use the UI to configure the access tokens instead. If this value is not provided, the default API key will be automatically generated. diff --git a/apps/studio/.env b/apps/studio/.env index 5c8eb9662c..addb3f0212 100644 --- a/apps/studio/.env +++ b/apps/studio/.env @@ -11,8 +11,9 @@ SUPABASE_PUBLIC_URL=http://localhost:8000 SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q SENTRY_IGNORE_API_RESOLUTION_ERROR=1 -LOGFLARE_URL=http://localhost:54329 -LOGFLARE_API_KEY=api-key +LOGFLARE_URL=http://localhost:4000 +LOGFLARE_PRIVATE_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-private + # TODO: evaluate these variables at runtime instead # https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables NEXT_PUBLIC_SITE_URL=http://localhost:3000 diff --git a/apps/studio/pages/api/platform/projects/[ref]/analytics/endpoints/[name].ts b/apps/studio/pages/api/platform/projects/[ref]/analytics/endpoints/[name].ts index 88fe005f71..b18473d013 100644 --- a/apps/studio/pages/api/platform/projects/[ref]/analytics/endpoints/[name].ts +++ b/apps/studio/pages/api/platform/projects/[ref]/analytics/endpoints/[name].ts @@ -1,7 +1,6 @@ import { NextApiRequest, NextApiResponse } from 'next' import apiWrapper from 'lib/api/apiWrapper' import { PROJECT_ANALYTICS_URL } from 'pages/api/constants' -import { get } from 'lib/common/fetch' export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler) @@ -11,7 +10,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { switch (method) { case 'GET': const missingEnvVars = [ - process.env.LOGFLARE_API_KEY ? null : 'LOGFLARE_API_KEY', + process.env.LOGFLARE_PRIVATE_ACCESS_TOKEN ? null : 'LOGFLARE_PRIVATE_ACCESS_TOKEN', process.env.LOGFLARE_URL ? null : 'LOGFLARE_URL', ].filter((v) => v) if (missingEnvVars.length == 0) { @@ -33,14 +32,16 @@ const proxyRequest = async (req: NextApiRequest) => { const { name, ...toForward } = req.query const payload = { ...toForward, project_tier: 'ENTERPRISE' } const search = '?' + new URLSearchParams(payload as any).toString() - const apiKey = process.env.LOGFLARE_API_KEY + const apiKey = process.env.LOGFLARE_PRIVATE_ACCESS_TOKEN const url = `${PROJECT_ANALYTICS_URL}endpoints/query/${name}${search}` - const result = await get(url, { + const result = await fetch(url, { + method: 'GET', headers: { - 'x-api-key': apiKey, + 'x-api-key': apiKey as string, 'Content-Type': 'application/json', Accept: 'application/json', }, - }) + }).then((res) => res.json()) + return result } diff --git a/docker/.env.example b/docker/.env.example index bb74500874..2ca5a229c2 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -106,14 +106,14 @@ FUNCTIONS_VERIFY_JWT=false ############ -# Logs - Configuration for Logflare +# Logs - Configuration for Analytics # 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 +# these cannot be the same value +LOGFLARE_PUBLIC_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-public +LOGFLARE_PRIVATE_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-private # Docker socket location - this value will differ depending on your OS DOCKER_SOCKET_LOCATION=/var/run/docker.sock diff --git a/docker/dev/docker-compose.dev.yml b/docker/dev/docker-compose.dev.yml index ca19a0ad78..f8b3ba7877 100644 --- a/docker/dev/docker-compose.dev.yml +++ b/docker/dev/docker-compose.dev.yml @@ -4,7 +4,7 @@ services: studio: build: context: .. - dockerfile: studio/Dockerfile + dockerfile: apps/studio/Dockerfile target: dev ports: - 8082:8082 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 8ca3d74606..ddacfad276 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -41,7 +41,7 @@ services: SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} AUTH_JWT_SECRET: ${JWT_SECRET} - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + LOGFLARE_PRIVATE_ACCESS_TOKEN: ${LOGFLARE_PRIVATE_ACCESS_TOKEN} LOGFLARE_URL: http://analytics:4000 NEXT_PUBLIC_ENABLE_LOGS: true # Comment to use Big Query backend for analytics @@ -338,7 +338,7 @@ services: analytics: container_name: supabase-analytics - image: supabase/logflare:1.12.0 + image: supabase/logflare:1.14.2 restart: unless-stopped ports: - 4000:4000 @@ -370,7 +370,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 @@ -462,7 +463,7 @@ services: interval: 5s retries: 3 environment: - LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN} command: [ "--config", diff --git a/docker/volumes/logs/vector.yml b/docker/volumes/logs/vector.yml index cce46df43d..1c438a8ecd 100644 --- a/docker/volumes/logs/vector.yml +++ b/docker/volumes/logs/vector.yml @@ -165,7 +165,9 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=gotrue.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' logflare_realtime: type: 'http' inputs: @@ -175,7 +177,9 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=realtime.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' logflare_rest: type: 'http' inputs: @@ -185,7 +189,9 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=postgREST.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' logflare_db: type: 'http' inputs: @@ -195,10 +201,12 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 + 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&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + uri: 'http://kong:8000/analytics/v1/api/logs?source_name=postgres.logs' logflare_functions: type: 'http' inputs: @@ -208,7 +216,9 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=deno-relay-logs&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' logflare_storage: type: 'http' inputs: @@ -218,7 +228,9 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=storage.logs.prod.2&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' logflare_kong: type: 'http' inputs: @@ -229,4 +241,6 @@ sinks: method: 'post' request: retry_max_duration_secs: 10 - uri: 'http://analytics:4000/api/logs?source_name=cloudflare.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}' + 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' diff --git a/turbo.json b/turbo.json index eeb3902822..6f4c5c2e08 100644 --- a/turbo.json +++ b/turbo.json @@ -82,7 +82,7 @@ "OPENAI_API_KEY", "AUTH_JWT_SECRET", "LOGFLARE_URL", - "LOGFLARE_API_KEY", + "LOGFLARE_PRIVATE_ACCESS_TOKEN", "SENTRY_ORG", "SENTRY_PROJECT", "SENTRY_AUTH_TOKEN",