diff --git a/apps/docs/spec/analytics_v0_config.yaml b/apps/docs/spec/analytics_v0_config.yaml index 8d9664f3279..1207dc95aed 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 889b31075d3..bae7d2557b0 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 5c8eb9662c2..addb3f02120 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 88fe005f718..b18473d013a 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 bb74500874d..2ca5a229c20 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 ca19a0ad781..f8b3ba78770 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 8ca3d74606e..ddacfad276d 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 cce46df43db..1c438a8ecdd 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 eeb39028227..6f4c5c2e085 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",