Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/app/reference/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default async function ReferencePage(props: { params: Promise<{ slug: Arr
} else if (isCliReference) {
return <CliReferencePage />
} else if (isApiReference) {
return <ApiReferencePage />
return <ApiReferencePage path={parsedPath.path} />
} else if (isSelfHostingReference) {
return (
<SelfHostingReferencePage service={parsedPath.service} servicePath={parsedPath.servicePath} />
Expand Down
12 changes: 11 additions & 1 deletion apps/docs/components/MetricsStackCards.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export type MetricsStackOption = {
title: string
description: string
href: string
iconKind: 'grafana' | 'datadog' | 'flame'
iconKind: 'grafana' | 'datadog' | 'elastic' | 'flame'
iconColor: string
iconBg: string
badges: { label: string; variant: 'default' | 'community' }[]
Expand Down Expand Up @@ -39,6 +39,16 @@ export const metricsStackOptions: MetricsStackOption[] = [
iconBg: 'rgba(99,44,166,0.1)',
badges: [{ label: 'Community', variant: 'community' }],
},
{
title: 'Elastic',
description:
"Use Elastic's managed Supabase integration to scrape metrics. The integration automatically installs dashboards, alert templates, and SLO templates as data arrives.",
href: 'https://www.elastic.co/docs/reference/integrations/supabase',
iconKind: 'elastic',
iconColor: '#00BFB3',
iconBg: 'rgba(0,191,179,0.1)',
badges: [{ label: 'Community', variant: 'community' }],
},
{
title: 'Vendor-agnostic / BYO Prometheus',
description:
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/components/MetricsStackCards.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Datadog, Grafana } from 'icons'
import { Datadog, Elastic, Grafana } from 'icons'
import { Flame } from 'lucide-react'
import Link from 'next/link'
import type { ReactNode } from 'react'
Expand All @@ -8,6 +8,7 @@ import { metricsStackOptions, type MetricsStackOption } from './MetricsStackCard
const ICONS: Record<MetricsStackOption['iconKind'], ReactNode> = {
grafana: <Grafana className="h-5 w-5" />,
datadog: <Datadog className="h-5 w-5" />,
elastic: <Elastic className="h-5 w-5" />,
flame: <Flame className="h-5 w-5" strokeWidth={1.5} />,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3047,6 +3047,10 @@ export const telemetry: NavMenuConstant = {
name: 'Datadog',
url: 'https://docs.datadoghq.com/integrations/supabase/' as `/${string}`,
},
{
name: 'Elastic',
url: 'https://www.elastic.co/docs/reference/integrations/supabase' as `/${string}`,
},
{
name: 'Vendor-agnostic setup',
url: '/guides/monitoring-and-debugging/metrics/vendor-agnostic' as `/${string}`,
Expand Down Expand Up @@ -3626,7 +3630,7 @@ export const references = [
label: 'Management API',
description: 'something about the reference',
icon: '/docs/img/icons/api-icon.svg',
url: '/reference/management-api/start',
url: '/reference/api/introduction',
},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ Pick the workflow that best matches your tooling. Cards link to Supabase-authore
- [Supabase Grafana repository](https://github.com/supabase/supabase-grafana) for dashboard JSON and alert examples.
- [Grafana Cloud’s Supabase integration doc](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-supabase/) (community-maintained, built on this Metrics API).
- [Datadog’s Supabase integration doc](https://docs.datadoghq.com/integrations/supabase/) (community-maintained, built on this Metrics API).
- [Elastic’s Supabase integration doc](https://www.elastic.co/docs/reference/integrations/supabase) (community-maintained).
- [Log Drains ](/docs/guides/monitoring-and-debugging/log-drains) for exporting event-based telemetry alongside metrics.
- [Query Performance report](/dashboard/project/_/observability/query-performance) for built-in visualizations based on the same underlying metrics.
41 changes: 26 additions & 15 deletions apps/docs/content/guides/platform/privatelink.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: 'Secure private network connectivity to your Supabase database usin

<Admonition type="note">

PrivateLink is currently in beta and available only to Team and Enterprise customers.
PrivateLink is available only to Team and Enterprise customers.
Contact support if you would like to create a PrivateLink connection for a read-only replica.

</Admonition>
Expand All @@ -20,13 +20,12 @@ By enabling PrivateLink, database connections never traverse the public internet
Supabase PrivateLink is an organisation level configuration. It works by sharing a [VPC Lattice Resource Configuration](https://docs.aws.amazon.com/vpc-lattice/latest/ug/resource-configuration.html) to any number of AWS Accounts for each of your Supabase projects. Connectivity can be achieved by either associating the Resource Configuration to a PrivateLink endpoint, or a [VPC Lattice Service Network](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html). This means:

- Database traffic flows through private AWS infrastructure only
- Connection latency is typically reduced compared to public internet routing
- Network isolation provides enhanced security posture
- Attack surface is minimized by eliminating public exposure

The connection architecture changes from public internet routing to a dedicated private path through AWS's secure network backbone.

Supabase PrivateLink currently supports direct database and PgBouncer connections only. It does not support other Supabase services like API, Storage, Auth, or Realtime. These services will continue to operate over public internet connections.
Supabase PrivateLink supports direct database connections on port `5432` and PgBouncer connections on port `6543`. It does not support other Supabase services like API, Storage, Auth, or Realtime. These services will continue to operate over public internet connections.

## Requirements

Expand Down Expand Up @@ -76,9 +75,11 @@ Ensure your security groups allow traffic on the appropriate ports:
1. Navigate to the [VPC console > Security Groups](https://console.aws.amazon.com/vpcconsole/home#SecurityGroups:)
2. Create a new security group for the endpoint or service network by clicking [Create security group](https://console.aws.amazon.com/vpcconsole/home#CreateSecurityGroup:)
3. Give your security group a descriptive name and select the appropriate VPC
4. Add an inbound rule for:
- Type: Postgres (TCP, port 5432)
- Destination that is appropriate for your network. i.e. the subnet of your VPC or security group of your application instances
4. Add inbound rule(s) for the connection mode you use:
- Direct connection: Postgres (TCP, port `5432`)
- PgBouncer connection: Custom TCP (port `6543`)
- If you use both direct and PgBouncer connections, add both rules
- Set the destination appropriate for your network (for example, your VPC subnet or your application instances' security group)
5. Finish creating the security group by clicking **Create security group**

### Step 4: Create connection
Expand Down Expand Up @@ -127,7 +128,11 @@ Verify the private connection is working correctly from your VPC:
3. Test the connection using the private endpoint:

```bash
# Direct connection (Postgres)
psql "postgresql://[username]:[password]@[private-endpoint]:5432/postgres"

# PgBouncer connection
psql "postgresql://[username]:[password]@[private-endpoint]:6543/postgres"
```

You should see a successful connection without any public internet traffic.
Expand All @@ -141,27 +146,33 @@ Configure your applications to use the private connection details:
3. Update any database connection pooling configurations
4. Test application connectivity thoroughly

Example connection string update:
Example connection string updates:

```
# Direct connection (Postgres)
# Before (public)
postgresql://user:pass@db.[project-ref].supabase.co:5432/postgres

# After (private)
postgresql://user:pass@your-private-endpoint.vpce.amazonaws.com:5432/postgres
```

### Step 7: Disable public connectivity (optional)
# PgBouncer connection
# Before (public)
postgresql://user:pass@db.[project-ref].supabase.co:6543/postgres

# After (private)
postgresql://user:pass@your-private-endpoint.vpce.amazonaws.com:6543/postgres
```

For maximum security, you can disable public internet access for your database:
### Step 7: Restrict public database access (optional)

1. Contact Supabase support to disable public connectivity
2. Ensure all applications are successfully using the private connection
3. Update any monitoring or backup tools to use the private endpoint
For maximum security, you can restrict public database access in your project settings:

## Beta limitations
1. Go to [**Database** > **Settings**](/dashboard/project/_/database/settings)
2. In **Network Restrictions**, enable **Restrict all access**
3. Ensure all applications, monitoring, and backup tools are using the private endpoint before enabling this setting

During the beta phase:
## Limitations

- **Read Replicas**: To establish PrivateLink with a Read Replica, reach out to your account rep.
- **Feature Evolution**: The setup process and capabilities may evolve as we refine the offering
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/guides/security/platform-security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ For configuration information, see [PrivateLink](/docs/guides/platform/privateli

<Admonition type="note">

PrivateLink is currently in beta. To establish PrivateLink with a Read Replica, reach out to your account rep.
To establish PrivateLink with a Read Replica, reach out to your account rep.

</Admonition>
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,38 @@ PostgREST logs showing the error:
- Currently, we don't really shutdown PostgREST when the Data API is disabled. You will see a schema called `pg_pgrst_no_exposed_schemas` added in the exposed schemas.
- This should not adversely affect the project, although it may result in additional entries in your logs.
- We're aware of this issue and are working on it.

## Workaround

To stop the missing-schema log entries:

1. Open the SQL Editor.
2. Run the following statements:

```sql
-- Create a schema with nothing inside
create schema pgrst_no_exposed_schemas;

-- Set the db-schemas configuration
alter role authenticator set pgrst.db_schemas = 'pgrst_no_exposed_schemas';

-- Reload PostgREST's schema cache and configuration
notify pgrst;
```

PostgREST now exposes an empty schema, which stops the missing-schema errors.

## Re-enable the Data API

Before you re-enable the data API:

1. Open the SQL Editor.
2. Run the following statements:

```sql
-- Reset the db-schemas configuration
alter role authenticator reset pgrst.db_schemas;

-- Reload PostgREST's schema cache and configuration
notify pgrst;
```
34 changes: 24 additions & 10 deletions apps/docs/features/docs/Reference.apiPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
import { notFound, redirect } from 'next/navigation'

import { MenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu'
import { reference_api } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
import { ClientLibIntroduction } from '~/features/docs/Reference.introduction'
import { getSectionsBySlug } from '~/features/docs/Reference.generated.singleton'
import { ReferenceNavigation } from '~/features/docs/Reference.navigation'
import { ReferenceContentScrollHandler } from '~/features/docs/Reference.navigation.client'
import { RefSections } from '~/features/docs/Reference.sections'
import { SectionSwitch } from '~/features/docs/Reference.sections'
import { LayoutMainContent } from '~/layouts/DefaultLayout'
import { SidebarSkeleton } from '~/layouts/MainSkeleton'

export async function ApiReferencePage() {
export async function ApiReferencePage({ path }: { path: Array<string> }) {
const operationSlug = path[0]

if (!operationSlug) {
redirect('/reference/api/introduction')
}

return <ApiOperationPage operationSlug={operationSlug} />
}

// DOCS-1268: one endpoint per page, reusing the same SectionSwitch (and
// therefore the same ApiEndpointSection/MarkdownSection) that used to render
// every operation on the single monolithic /reference/api page.
async function ApiOperationPage({ operationSlug }: { operationSlug: string }) {
const sectionsBySlug = await getSectionsBySlug('api', 'latest')
const section = sectionsBySlug?.get(operationSlug)
if (!section) notFound()

return (
<ReferenceContentScrollHandler libPath="api" version="latest" isLatestVersion={true}>
<SidebarSkeleton
Expand All @@ -20,18 +39,13 @@ export async function ApiReferencePage() {
libPath="api"
version="latest"
isLatestVersion={true}
realNavigation
/>
}
>
<LayoutMainContent>
<article className="@container/article">
<ClientLibIntroduction
libPath="api"
version="latest"
isLatestVersion={true}
className="max-w-[unset]"
/>
<RefSections libraryId="api" version="latest" />
<SectionSwitch libraryId="api" version="latest" section={section} />
</article>
</LayoutMainContent>
</SidebarSkeleton>
Expand Down
24 changes: 17 additions & 7 deletions apps/docs/features/docs/Reference.navigation.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,16 @@ export function RefLink({
section,
skipChildren = false,
className,
realNavigation,
}: {
basePath: string
section: AbbrevApiReferenceSection
skipChildren?: boolean
className?: string
// Spike (DOCS-1268): when true, this link does a real navigation instead of
// the scroll-hijack below — used only by the API reference, whose endpoints
// are now real pages. Undefined everywhere else preserves current behavior.
realNavigation?: boolean
}) {
const ref = useRef<HTMLAnchorElement>(null)

Expand All @@ -260,8 +265,11 @@ export function RefLink({
}, [isActive, className])

const onClick = useCallback(
(evt: MouseEvent) => createReferenceSubsectionNavigator(href, section.slug)(evt),
[href, section.slug]
(evt: MouseEvent) => {
if (realNavigation) return
createReferenceSubsectionNavigator(href, section.slug)(evt)
},
[href, section.slug, realNavigation]
)

if (!('title' in section)) return null
Expand All @@ -272,13 +280,13 @@ export function RefLink({
return (
<>
{isCompoundSection ? (
<CompoundRefLink basePath={basePath} section={section} />
<CompoundRefLink basePath={basePath} section={section} realNavigation={realNavigation} />
) : (
<Link
ref={ref}
// We don't use these links because we never do real navigation, so
// prefetching just wastes egress
prefetch={false}
// Scroll-hijack links never navigate, so disable prefetch. Real API
// pages omit the prop and keep Next.js's default prefetch behavior.
{...(!realNavigation ? { prefetch: false } : {})}
href={href}
className={getLinkStyles(isActive, className)}
onClick={onClick}
Expand Down Expand Up @@ -321,9 +329,11 @@ function useCompoundRefLinkActive(basePath: string, section: AbbrevApiReferenceS
function CompoundRefLink({
basePath,
section,
realNavigation,
}: {
basePath: string
section: AbbrevApiReferenceSection
realNavigation?: boolean
}) {
const { open, setOpen, isActive } = useCompoundRefLinkActive(basePath, section)

Expand Down Expand Up @@ -357,7 +367,7 @@ function CompoundRefLink({
{(section.items || []).map((item, idx) => {
return (
<li key={`${section.id}-${idx}`}>
<RefLink basePath={basePath} section={item} />
<RefLink basePath={basePath} section={item} realNavigation={realNavigation} />
</li>
)
})}
Expand Down
13 changes: 10 additions & 3 deletions apps/docs/features/docs/Reference.navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ interface ReferenceNavigationProps {
libPath: string
version: string
isLatestVersion: boolean
// Spike (DOCS-1268): API reference sidebar links navigate to real pages
// instead of scrolling within one giant page. SDK/CLI/self-hosting callers
// never pass this, so their behavior is unchanged.
realNavigation?: boolean
}

export async function ReferenceNavigation({
Expand All @@ -28,6 +32,7 @@ export async function ReferenceNavigation({
libPath,
version,
isLatestVersion,
realNavigation,
}: ReferenceNavigationProps) {
const navSections = await getReferenceSections(libraryId, version)
const filteredNavSections = navSections?.filter((section) => section.title !== 'Auth')
Expand All @@ -46,11 +51,11 @@ export async function ReferenceNavigation({
{displayedNavSections?.map((section, index) =>
section.type === 'category' ? (
<li key={section.id ?? String(index)}>
<RefCategory basePath={basePath} section={section} />
<RefCategory basePath={basePath} section={section} realNavigation={realNavigation} />
</li>
) : (
<li key={section.id ?? String(index)} className={topLvlRefNavItemStyles}>
<RefLink basePath={basePath} section={section} />
<RefLink basePath={basePath} section={section} realNavigation={realNavigation} />
</li>
)
)}
Expand All @@ -64,9 +69,11 @@ const topLvlRefNavItemStyles = 'leading-5'
function RefCategory({
basePath,
section,
realNavigation,
}: {
basePath: string
section: AbbrevApiReferenceSection
realNavigation?: boolean
}) {
if (!('items' in section && section.items && section.items.length > 0)) return null

Expand All @@ -77,7 +84,7 @@ function RefCategory({
<ul className="space-y-2">
{section.items?.map((item) => (
<li key={item.id} className={topLvlRefNavItemStyles}>
<RefLink basePath={basePath} section={item} />
<RefLink basePath={basePath} section={item} realNavigation={realNavigation} />
</li>
))}
</ul>
Expand Down
Loading
Loading