diff --git a/apps/docs/app/guides/database/database-advisors/page.tsx b/apps/docs/app/guides/database/database-advisors/page.tsx index 987979377ed8d..bba7532c3ded5 100644 --- a/apps/docs/app/guides/database/database-advisors/page.tsx +++ b/apps/docs/app/guides/database/database-advisors/page.tsx @@ -2,6 +2,7 @@ import { Octokit } from '@octokit/core' import { capitalize } from 'lodash-es' import rehypeSlug from 'rehype-slug' import { Heading } from 'ui' +import { Admonition } from 'ui-patterns' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' @@ -43,7 +44,18 @@ In the dashboard, navigate to [Security Advisor](https://supabase.com/dashboard/ const getBasename = (path: string) => path.split('/').at(-1)!.replace(/\.md$/, '') const DatabaseAdvisorDocs = async () => { - const { lints, lintsList } = await getLints() + let lints: Awaited>['lints'] = [] + let lintsList: Awaited>['lintsList'] = [] + let fetchError: Error | null = null + + try { + const data = await getLints() + lints = data.lints + lintsList = data.lintsList + } catch (error) { + fetchError = error instanceof Error ? error : new Error('Unknown error fetching advisor docs') + console.error('[database-advisors] Failed to fetch advisor docs from GitHub', fetchError) + } const options = { mdxOptions: { @@ -56,19 +68,40 @@ const DatabaseAdvisorDocs = async () => { Available checks - - {lints.map((lint) => ( - + We fetch remediation guides straight from the supabase/splinter repository + during the build. GitHub timed out just now, so we’re showing the overview only. +
+
+ You can check back in a few minutes or browse the + {` `} + -
- -
-
- ))} -
+ latest Markdown on GitHub (opens in a new tab) + + . + + ) : ( + + {lints.map((lint) => ( + +
+ +
+
+ ))} +
+ )}
) } diff --git a/apps/docs/components/MetricsStackCards.tsx b/apps/docs/components/MetricsStackCards.tsx new file mode 100644 index 0000000000000..19ba4b02edec9 --- /dev/null +++ b/apps/docs/components/MetricsStackCards.tsx @@ -0,0 +1,116 @@ +import Link from 'next/link' +import { Datadog, Grafana } from 'icons' +import { Flame } from 'lucide-react' +import type { ReactNode } from 'react' + +interface MetricsStackOption { + title: string + description: ReactNode + href: string + icon: ReactNode + iconColor: string + iconBg: string + badges: { label: string; variant: 'default' | 'community' }[] +} + +const metricsStackOptions: MetricsStackOption[] = [ + { + title: 'Grafana Cloud (SaaS)', + description: ( + <> + Use Grafana Cloud’s managed Prometheus (works on Free + Pro tiers) and import the Supabase + dashboard without running any infrastructure. + + ), + href: '/guides/telemetry/metrics/grafana-cloud', + icon: , + iconColor: '#F05A28', + iconBg: 'rgba(240,90,40,0.1)', + badges: [ + { label: 'Supabase guide', variant: 'default' }, + { label: 'Community', variant: 'community' }, + ], + }, + { + title: 'Grafana + self-hosted Prometheus', + description: ( + <> + Run Prometheus yourself following the official installation guidance and pair it with + Grafana plus our dashboard JSON and alert pack. + + ), + href: '/guides/telemetry/metrics/grafana-self-hosted', + icon: , + iconColor: '#F05A28', + iconBg: 'rgba(240,90,40,0.1)', + badges: [{ label: 'Supabase guide', variant: 'default' }], + }, + { + title: 'Datadog', + description: ( + <> + Scrape the Metrics API with the Datadog Agent or Prometheus remote write and monitor + Supabase alongside your app telemetry. + + ), + href: '/guides/telemetry/metrics/datadog', + icon: , + iconColor: '#632CA6', + iconBg: 'rgba(99,44,166,0.1)', + badges: [ + { label: 'Supabase guide', variant: 'default' }, + { label: 'Community', variant: 'community' }, + ], + }, + { + title: 'Vendor-agnostic / BYO Prometheus', + description: ( + <> + Connect AWS AMP, Grafana Mimir, VictoriaMetrics, or any Prometheus-compatible SaaS with the + same scrape job pattern. + + ), + href: '/guides/telemetry/metrics/vendor-agnostic', + icon: , + iconColor: '#0BA678', + iconBg: 'rgba(11,166,120,0.1)', + badges: [{ label: 'Supabase guide', variant: 'default' }], + }, +] + +export function MetricsStackCards() { + return ( +
+ {metricsStackOptions.map((option) => ( + +
+
+ + {option.icon} + +

{option.title}

+
+
{option.description}
+
+ {option.badges.map((badge) => ( + + {badge.label} + + ))} +
+
+ + ))} +
+ ) +} diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 92037e9c9c108..50330ec471144 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -2754,6 +2754,28 @@ export const telemetry: NavMenuConstant = { { name: 'Metrics', url: '/guides/telemetry/metrics' as `/${string}`, + items: [ + { + name: 'Overview', + url: '/guides/telemetry/metrics' as `/${string}`, + }, + { + name: 'Grafana Cloud', + url: '/guides/telemetry/metrics/grafana-cloud' as `/${string}`, + }, + { + name: 'Grafana self-hosted', + url: '/guides/telemetry/metrics/grafana-self-hosted' as `/${string}`, + }, + { + name: 'Datadog', + url: '/guides/telemetry/metrics/datadog' as `/${string}`, + }, + { + name: 'Vendor-agnostic setup', + url: '/guides/telemetry/metrics/vendor-agnostic' as `/${string}`, + }, + ], }, { name: 'Sentry integration', @@ -2929,22 +2951,25 @@ export const integrations: NavMenuConstant = { }, { name: 'Build Your Own', - url: undefined, items: [ { - name: 'Build a Supabase integration', - url: '/guides/integrations/build-a-supabase-integration', + name: 'Supabase OAuth Integration', + url: '/guides/integrations/build-a-supabase-oauth-integration', items: [ { name: 'Overview', - url: '/guides/integrations/build-a-supabase-integration' as `/${string}`, + url: '/guides/integrations/build-a-supabase-oauth-integration', }, { name: 'OAuth scopes', - url: '/guides/integrations/build-a-supabase-integration/oauth-scopes' as `/${string}`, + url: '/guides/integrations/build-a-supabase-oauth-integration/oauth-scopes', }, ], }, + { + name: 'Supabase for Platforms', + url: '/guides/integrations/supabase-for-platforms', + }, ], }, { name: 'Integrations', url: undefined, items: [] }, diff --git a/apps/docs/content/_partials/metrics_access.mdx b/apps/docs/content/_partials/metrics_access.mdx new file mode 100644 index 0000000000000..5f89bdef5706b --- /dev/null +++ b/apps/docs/content/_partials/metrics_access.mdx @@ -0,0 +1,50 @@ + + +What you can do with the Metrics API} +id="how-do-i-check-when-a-user-went-through-mfa" +> + +Every Supabase project exposes a metrics feed at `https://.supabase.co/customer/v1/privileged/metrics`. Replace `` with the identifier from your project URL or from the dashboard sidebar. + +1. Copy your project reference and confirm the base URL using the helper below. + + + +2. Configure your collector to scrape once per minute. The endpoint already emits the full set of metrics on each request. +3. Authenticate with HTTP Basic Auth: + + - **Username**: `service_role` + - **Password**: a service role secret (JWT) from [**Project Settings > JWT** (opens in a new tab)](/dashboard/project/_/settings/jwt) or any other Secret API key from [**Project Settings > API keys** (opens in a new tab)](/dashboard/project/_/settings/api-keys) + +Testing locally is as simple as running `curl` with your service role secret: + +```bash +curl /customer/v1/privileged/metrics \ + --user 'service_role:sb_secret_...' +``` + +You can provision long-lived automation tokens in two ways: + +- Create an account access token once at [**Account Settings > Access Tokens (opens in a new tab)**](/dashboard/account/tokens) and reuse it wherever you configure observability tooling. +- **Optional**: programmatically exchange an access token for project API keys via the [Management API ](/docs/reference/api/management-projects-api-keys-retrieve'). + +```bash +# (Optional) Exchange an account access token for project API keys +export SUPABASE_ACCESS_TOKEN="your-access-token" +export PROJECT_REF="your-project-ref" + +curl -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ + "https://api.supabase.com/v1/projects/$PROJECT_REF/api-keys?reveal=true" +``` + + + + diff --git a/apps/docs/content/guides/integrations/build-a-supabase-integration.mdx b/apps/docs/content/guides/integrations/build-a-supabase-oauth-integration.mdx similarity index 99% rename from apps/docs/content/guides/integrations/build-a-supabase-integration.mdx rename to apps/docs/content/guides/integrations/build-a-supabase-oauth-integration.mdx index 29b785b1e698c..fae9d946305b0 100644 --- a/apps/docs/content/guides/integrations/build-a-supabase-integration.mdx +++ b/apps/docs/content/guides/integrations/build-a-supabase-oauth-integration.mdx @@ -1,5 +1,5 @@ --- -id: 'build-a-supabase-integration' +id: 'build-a-supabase-oauth-integration' title: 'Build a Supabase Integration' subtitle: "This guide steps through building a Supabase Integration using OAuth2 and the management API, allowing you to manage users' organizations and projects on their behalf." description: 'Build a Supabase Integration using OAuth2 and the Management API.' diff --git a/apps/docs/content/guides/integrations/build-a-supabase-integration/oauth-scopes.mdx b/apps/docs/content/guides/integrations/build-a-supabase-oauth-integration/oauth-scopes.mdx similarity index 100% rename from apps/docs/content/guides/integrations/build-a-supabase-integration/oauth-scopes.mdx rename to apps/docs/content/guides/integrations/build-a-supabase-oauth-integration/oauth-scopes.mdx diff --git a/apps/docs/content/guides/integrations/supabase-for-platforms.mdx b/apps/docs/content/guides/integrations/supabase-for-platforms.mdx new file mode 100644 index 0000000000000..afed634e90b51 --- /dev/null +++ b/apps/docs/content/guides/integrations/supabase-for-platforms.mdx @@ -0,0 +1,446 @@ +--- +id: 'supabase-for-platform' +title: 'Supabase for Platforms' +description: 'Use Supabase as a platform for your own business and tools.' +subtitle: 'Use Supabase as a platform for your own business and tools.' +--- + +Supabase is a [Platform as a Service](https://en.wikipedia.org/wiki/Platform_as_a_service) (PaaS) that can be managed programmatically. You can use it to offer the key primitives to your own users, such as [Database](/docs/guides/database/overview), [Auth](/docs/guides/auth), [Edge Functions](/docs/guides/functions), [Storage](/docs/guides/storage), and [Realtime](/docs/guides/realtime). Supabase is commonly used as a platform by AI Builders and frameworks needing a backend. + +This document will guide you on best practices when using Supabase for your own platform and assumes that Supabase projects are in a Supabase organization that you own. If you want to instead interact with projects that your users own, navigate to [OAuth integration](/docs/guides/integrations/build-a-supabase-oauth-integration) for more details. + +![Platform as a Service](/docs/img/integrations/paas-intro.png) + +## Overview + +All features of Supabase can be managed through the [Management API](/docs/reference/api/introduction) or the [remote MCP Server](/docs/guides/getting-started/mcp). + +## Launching projects + +Management API endpoints: + +- Create project: [`POST /v1/projects`](https://api.supabase.com/api/v1#tag/projects/post/v1/projects) +- Get smart region selection codes: [`GET /v1/projects/available-regions`](https://api.supabase.com/api/v1#tag/projects/get/v1/projects/available-regions) +- Check service health: [`GET /v1/projects/{ref}/health`](https://api.supabase.com/api/v1#tag/projects/get/v1/projects/{ref}/health) + +We recommend: + +- **a _very_ secure password for each database**. Do not reuse the same password across databases. +- **storing the encrypted version of the password**. Once you set the password during project creation, there is no way to programmatically change the password but you can do so manually in the Supabase Dashboard. +- **using smart region selection to ensure there's enough capacity**. The available smart region codes are `americas`, `emea`, and `apac` and you can make a request to [`GET /v1/projects/available-regions`](https://api.supabase.com/api/v1#tag/projects/get/v1/projects/available-regions) for region details. +- **make sure that the services are `ACTIVE_HEALTHY` after project creation**. After creating project, confirm the service that you want to make a request to has a status of `ACTIVE_HEALTHY` by polling [`GET /v1/projects/{ref}/health`](https://api.supabase.com/api/v1#tag/projects/get/v1/projects/{ref}/health). For example, before making a request to set an Auth configuration confirm that the Auth service has a status of `ACTIVE_HEALTHY`. + +```sh +curl https://api.supabase.com/v1/projects \ + --request POST \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer YOUR_SECRET_TOKEN" \ + --data '{ + "name": "Todo App", + "organization_slug": "aaaabbbbccccddddeeee", + "db_pass": "SUPER_SECURE_PASSWORD", + "region_selection": { + "type": "smartGroup", + "code": "americas" + }, + "desired_instance_size": "micro" + }' +``` + +### Pico compute instance + + + +Only select customers have access to Pico instances. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access. + + + +Pico instance is our newest compute instance and the only one that scales to zero when not used. + +### Recommended API keys + +Management API endpoints: + +- Get the API keys: [`GET /v1/projects/{ref}/api-keys`](https://api.supabase.com/api/v1#tag/secrets/get/v1/projects/{ref}/api-keys) +- Enable the API keys: [`POST /v1/projects/{ref}/api-keys`](https://api.supabase.com/api/v1#tag/secrets/post/v1/projects/{ref}/api-keys) + + + +We are in the process of migrating away from our legacy API keys `anon` and `service_role` and towards API keys `publishable` and `secret`. + +You can learn more by navigating to [Upcoming changes to Supabase API Keys #29260](https://github.com/orgs/supabase/discussions/29260). + + + +Get the API keys by making a [`GET /v1/projects/{ref}/api-keys`](https://api.supabase.com/api/v1#tag/secrets/get/v1/projects/{ref}/api-keys) request. + +```sh +curl 'https://api.supabase.com/v1/projects/{ref}/api-keys?reveal=true' \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' +``` + +If the response includes `"publishable"` and `"secret"` keys then you're all set and you should only use those from now on. + +Otherwise, enable the API keys by making two [`POST /v1/projects/{ref}/api-keys`](https://api.supabase.com/api/v1#tag/secrets/post/v1/projects/{ref}/api-keys) requests, one for `publishable` and another for `secret`. + +```sh +curl 'https://api.supabase.com/v1/projects/{ref}/api-keys' \ + --request POST \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --data '{ + "type": "publishable", + "name": "default" +}' +``` + +```sh +curl 'https://api.supabase.com/v1/projects/{ref}/api-keys?reveal=true' \ + --request POST \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --data '{ + "type": "secret", + "name": "default", + "secret_jwt_template": { + "role": "service_role" + } +}' +``` + +## Changing compute sizes + +Management API endpoint: [`PATCH /v1/projects/{ref}/billing/addons`](https://api.supabase.com/api/v1#tag/billing/patch/v1/projects/{ref}/billing/addons) + + + +Once you have access to [Pico instances](#pico-compute-instance), you will no longer be able to upgrade or downgrade to Nano instances. + + + +You can upgrade and downgrade compute sizes by making requests to [`PATCH /v1/projects/{ref}/billing/addons`](https://api.supabase.com/api/v1#tag/billing/patch/v1/projects/{ref}/billing/addons). + +```sh +curl 'https://api.supabase.com/v1/projects/{ref}/billing/addons' \ + --request PATCH \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --data '{ + "addon_type": "compute_instance", + "addon_variant": "ci_small" + }' +``` + +## Configuration changes + +Management API endpoints: + +- Auth: [`PATCH /v1/projects/{ref}/config/auth`](https://api.supabase.com/api/v1#tag/auth/patch/v1/projects/{ref}/config/auth) +- Data API (PostgREST): [`PATCH /v1/projects/{ref}/postgrest`](https://api.supabase.com/api/v1#tag/rest/patch/v1/projects/{ref}/postgrest) +- Edge Functions: + - [`PATCH /v1/projects/{ref}/functions/{function_slug}`](https://api.supabase.com/api/v1#tag/edge-functions/patch/v1/projects/{ref}/functions/{function_slug}) + - [`PUT /v1/projects/{ref}/functions`](https://api.supabase.com/api/v1#tag/edge-functions/put/v1/projects/{ref}/functions) +- Storage: [`PATCH /v1/projects/{ref}/config/storage`](https://api.supabase.com/api/v1#tag/storage/patch/v1/projects/{ref}/config/storage) +- Realtime: [`PATCH /v1/projects/{ref}/config/realtime`](https://api.supabase.com/api/v1#tag/realtime-config/patch/v1/projects/{ref}/config/realtime) + +You can manage the configuration of all services using the Management API. + +## Development workflow + +Supabase is a _stateful_ service: we store data. If anything breaks in production, you can't "roll back" to a point in time because doing so might cause your users to lose any data that their production environment received since the last checkpoint. + +Because of this, it's important that you adopt a development workflow on behalf of your users: + +![Change flow](/docs/img/integrations/change-flow.png) + +### Creating a `DEV` branch + +Management API endpoint: [`POST /v1/projects/{ref}/branches`](https://api.supabase.com/api/v1#tag/environments/post/v1/projects/{ref}/branches) + +After launching a project, it's important that all changes happen on a development branch. Branches can be treated like ephemeral servers: if anything goes wrong you can either revert the changes or destroy the branch and create a new one based off of production. + +```sh +curl 'https://api.supabase.com/v1/projects/{ref}/branches' \ + --request POST \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --data '{ + "branch_name": "DEV", + "secrets": { + "STRIPE_SECRET_KEY":"sk_test_123..." + "STRIPE_PUBLISHABLE_KEY":"pk_test_123..." + } + }' +``` + +### Make database changes + +Management API endpoint: [`POST /v1/projects/{ref}/database/migrations`](https://api.supabase.com/api/v1#tag/database/post/v1/projects/{ref}/database/migrations) + + + +Only select customers have access to database migrations endpoint. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access. + + + +For this example we will create a todos table using the [`POST /v1/projects/{ref}/database/migrations`](https://api.supabase.com/api/v1#tag/database/post/v1/projects/{ref}/database/migrations) endpoint. + +```sql +create table public.todos ( + id serial primary key, + task text not null +); + +alter table public.todos +enable row level security; +``` + +This endpoint will automatically create a migration inside the `supabase_migrations` schema and run the migration. If the schema migration fails, the changes will be rolled back. + +```sh +curl https://api.supabase.com/v1/projects/{ref}/database/migrations \ + --request POST \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --header 'Content-Type: application/json' \ + --data '{ + "query": "create table public.todos (id serial primary key, task text not null); alter table public.todos enable row level security;", + "name": "Create a todos table" + }' +``` + +### Create a restore point + + + +Only select customers have access to restore points. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access. + + + +After every change you make to the database, it's a good idea to create a restore point. This will allow you to roll back the database if you decide to go in a different direction. + +Beware that only database changes are captured when creating a restore point. + +```sh +curl https://api.supabase.com/v1/projects/{ref}/database/backups/restore-point \ + --request POST \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --header 'Content-Type: application/json' \ + --data '{ + "name": "abcdefg" + }' +``` + +### Reverting changes + +![Revert](/docs/img/integrations/revert.png) + + + +Only select customers have access to restore points. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access. + + + +After creating restore points, you are able to revert back to any restore point that you want. + +```sh +curl https://api.supabase.com/v1/projects/{ref}/database/backups/undo \ + --request POST \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --header 'Content-Type: application/json' \ + --data '{ + "name": "abcdefg" +}' +``` + +When you revert changes, you are undo-ing all database changes since the specified restore point, including: + +- Schema changes +- Any seed data that you inserted +- Any test users who have signed up (and auth tokens for sign ins) +- Pointers to files in Supabase Storage. + +It will not affect: + +- Configuration changes +- Any secrets that have been added +- Storage objects themselves +- Any deployed Edge Functions + +### Add seed data + + + +It's important that the data in development branches is NOT production data, especially for non-developers who don't understand the implications of working with data. Security and side-effects (e.g. emailing all production users) are two reasons why this is important. + + + +It's common in `DEV` branches to "seed" data. This is basically test data for users. Let's insert the following seed to our new todos table: + +```sql +insert into todos (task) +values + ('Task 1'), + ('Task 2'), + ('Task 3'); +``` + +You can use the `POST /database/query` endpoint to add data: + +```sh +curl https://api.supabase.com/v1/projects/{branch_ref}/database/query \ + --request POST \ + --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \ + --header 'Content-Type: application/json' \ + --data-binary @- < + +Only select customers have access to claim flow. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access. + + + +Your users may want to claim the project that currently lives in your org so that they can have more control over it. + +We've enabled transferring the project from your org to your user's org while you continue to retain access to interact with the project through an [OAuth integration](/docs/guides/integrations/build-a-supabase-oauth-integration). + +```sh +curl -L "https://api.supabase.com/v1/oauth/authorize/project-claim?project_ref={ref}&client_id={oauth_client_id}&response_type=code&redirect_uri={redirect_uri}" \ + --request GET \ + --header 'Authorization: Bearer {PERSONAL_ACCESS_TOKEN}' +``` + +The user is redirected to a Supabase UI: + +1. Create a new Supabase account or sign in to an existing one +2. Create a new Supabase Organization or select an existing one +3. Review your OAuth integration's permission scopes +4. Review the Project transfer details +5. Confirm the OAuth integration and the Project transfer for the selected Organization + + + +Before transferring the project to your user's org, make sure to remove any custom configuration that you do not want your user's project to retain. + + + +## Platform kit + +Docs: https://supabase.com/ui/docs/platform/platform-kit + +
+