diff --git a/apps/docs/content/guides/functions/secrets.mdx b/apps/docs/content/guides/functions/secrets.mdx
index cab98061f52..cd5e1ed8d28 100644
--- a/apps/docs/content/guides/functions/secrets.mdx
+++ b/apps/docs/content/guides/functions/secrets.mdx
@@ -1,17 +1,21 @@
---
id: 'functions-secrets'
title: 'Environment variables'
-description: 'Managing secrets and environment variables.'
-subtitle: 'Manage sensitive data securely across environments.'
+description: 'Set, read, and deploy Edge Function secrets.'
+subtitle: 'Store API keys and other secrets where your Edge Functions can read them.'
---
-Store API keys and other secrets where your Edge Functions can read them. Local development and production load them differently, so set them in both.
+Local development and production load secrets differently, so set them in both.
+
+- [Local secrets](#local-secrets) and [Production secrets](#production-secrets) have the steps for each environment.
+- [Accessing environment variables](#accessing-environment-variables) shows how to read a secret from your function code. [When your function can't read a secret](#when-your-function-cant-read-a-secret) covers the local case where nothing arrives.
+- [Reference](#reference) explains which file feeds which runtime, and lists the variables Supabase injects for you.
## Local secrets
-In development, Edge Functions read secrets from `supabase/functions/.env`, which is automatically loaded on `supabase start`. Create the file before you start the stack.
+Locally, Edge Functions read secrets from `supabase/functions/.env`. The local stack loads that file on `supabase start`.
-1. Create `supabase/functions/.env` and add each secret with the value you want the function to read. A `.env.example` template isn't enough on its own, because the runtime reads the values rather than the variable names.
+1. Create `supabase/functions/.env` and add each secret with the value you want the function to read. A `.env.example` template isn't enough, because the runtime reads the values rather than the variable names.
```bash
# supabase/functions/.env
@@ -32,7 +36,7 @@ In development, Edge Functions read secrets from `supabase/functions/.env`, whic
supabase functions new hello-world
```
- ```tsx
+ ```ts
// supabase/functions/hello-world/index.ts
Deno.serve(() => {
const secretKey = Deno.env.get('STRIPE_SECRET_KEY')
@@ -46,7 +50,7 @@ In development, Edge Functions read secrets from `supabase/functions/.env`, whic
supabase start
```
-5. Call the function. A `configured` of `true` means the runtime handed it the secret.
+5. Call the function. When `configured` comes back `true`, the runtime handed the secret to your function.
```bash
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/hello-world' \
@@ -57,9 +61,71 @@ Your function now reads the secret from your local environment.
---
+## Production secrets
+
+Set secrets for your production Edge Functions in the Supabase Dashboard or with the Supabase CLI.
+
+Creating or deleting a production secret requires the Owner or Administrator role. Developers can view secrets but not change them. See [Access control](/docs/guides/platform/access-control#edge-config-permissions) for the full matrix.
+
+A secret name can't start with `SUPABASE_`. That prefix is reserved for the variables Supabase injects, and both the Dashboard and the Management API reject it.
+
+### Using the Dashboard
+
+1. Open [Edge Function Secrets](/dashboard/project/_/functions/secrets) in the Dashboard.
+2. Enter the **Key** and **Value** for your secret, then click **Save**.
+
+
+
+You can paste multiple secrets at once.
+
+### Using the CLI
+
+1. Create a `.env` file with the secrets you want to deploy, and add it to your `.gitignore` before you commit.
+
+ ```bash
+ # .env
+ STRIPE_SECRET_KEY=sk_live_...
+ ```
+
+2. Push every secret in the file to your remote project. The command also makes them visible in the Dashboard.
+
+ ```bash
+ supabase secrets set --env-file .env
+ ```
+
+`supabase secrets set` also sets production secrets individually, without a `.env` file.
+
+```bash
+supabase secrets set STRIPE_SECRET_KEY=sk_live_...
+```
+
+List the secrets set on your remote project:
+
+```bash
+supabase secrets list
+```
+
+
+
+Your functions read a new secret immediately, so you don't need to redeploy.
+
+
+
+Your deployed functions can now read the secret.
+
+---
+
## Accessing environment variables
-Access an environment variable with the `Deno.env.get` method, passing the name of the variable you want.
+Read an environment variable with `Deno.env.get`, passing the name of the variable.
```js
Deno.env.get('NAME_OF_SECRET')
@@ -67,12 +133,14 @@ Deno.env.get('NAME_OF_SECRET')
### In an Edge Function
+Inside an Edge Function, the Supabase keys are already in the environment. Read them and pass them to `createClient`:
+
```ts
import { createClient } from 'npm:@supabase/supabase-js@2'
const SUPABASE_PUBLISHABLE_KEYS = JSON.parse(Deno.env.get('SUPABASE_PUBLISHABLE_KEYS')!)
-// For user-facing operations (respects RLS)
+// For user-facing operations (respects Row Level Security)
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
// To use a different API key, change 'default' to your preferred key name
@@ -80,7 +148,7 @@ const supabase = createClient(
)
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
-// For admin operations (bypasses RLS)
+// For admin operations (bypasses Row Level Security)
const supabaseAdmin = createClient(
Deno.env.get('SUPABASE_URL')!,
// To use a different API key, change 'default' to your preferred key name
@@ -90,7 +158,7 @@ const supabaseAdmin = createClient(
### In a Deno script
-A Deno script you run yourself, outside `supabase functions serve`, doesn't read `supabase/functions/.env`. Pass the file, and grant the script access to the environment with `--allow-env`:
+A Deno script you run yourself, outside `supabase functions serve`, doesn't read `supabase/functions/.env`. Pass the file with `--env-file`, and grant the script access to environment variables with `--allow-env`:
```bash
deno run --allow-env --env-file=supabase/functions/.env script.ts
@@ -106,7 +174,7 @@ STRIPE_SECRET_KEY=sk_test_... deno run --allow-env script.ts
## When your function can't read a secret
-The local runtime loads `supabase/functions/.env` when the stack starts, so a function that returns nothing for a variable usually means the value never reached it.
+A variable that comes back empty usually means the value never reached the runtime.
Restart the stack, or serve the function with the file passed explicitly:
@@ -114,83 +182,21 @@ Restart the stack, or serve the function with the file passed explicitly:
supabase functions serve hello-world --env-file supabase/functions/.env
```
-To keep a separate file per environment, name your own and pass it the same way:
-
-```bash
-supabase functions serve --env-file .env.local
-```
+If the value still doesn't arrive, confirm you edited the file your runtime reads.
---
-## Production secrets
+## Reference
-Set secrets for your production Edge Functions in the Dashboard or with the CLI.
+Look up which file feeds which runtime, and which variables Supabase injects for you.
-Creating or deleting a production secret requires the Owner or Administrator role. Developers can view secrets but not change them. See [Access control](/docs/guides/platform/access-control#edge-config-permissions) for the full matrix.
-
-A secret name can't start with `SUPABASE_`. That prefix is reserved for the variables Supabase injects, and both the Dashboard and the Management API reject it.
-
-### Using the Dashboard
-
-1. Open [Edge Function Secrets](/dashboard/project/_/functions/secrets) in the Dashboard.
-2. Enter the **Key** and **Value** for your secret, then click **Save**.
-
-
-
-You can paste multiple secrets at once.
-
-### Using the CLI
-
-Create a `.env` file with the secrets you want to deploy. Add it to your `.gitignore` before you commit.
-
-```bash
-# .env
-STRIPE_SECRET_KEY=sk_live_...
-```
-
-Push every secret in the file to your remote project with `supabase secrets set`, which also makes them visible in the Dashboard.
-
-```bash
-supabase secrets set --env-file .env
-```
-
-This command also sets production secrets individually, without a `.env` file.
-
-```bash
-supabase secrets set STRIPE_SECRET_KEY=sk_live_...
-```
-
-To see the secrets you have set remotely, use `supabase secrets list`.
-
-```bash
-supabase secrets list
-```
-
-
-
-Secrets are available in your functions immediately. You don't need to redeploy after setting them.
-
-
-
-Your deployed functions can now read the secret.
-
----
-
-## Where local values come from
+### Where local values come from
A project can hold more than one file that feeds local environment variables, and they aren't interchangeable:
- `supabase/functions/.env` is the one your Edge Functions read, loaded when the stack starts.
-- A file you name yourself, such as `.env.local`, passed to `supabase functions serve` with `--env-file`.
-- A `.env` at the root of your project is the one `config.toml` reads, through its `env()` function. See [Using secrets inside config.toml](/docs/guides/local-development/managing-config#using-secrets-inside-configtoml). A variable your function needs has to be in `supabase/functions/.env` too, even when the same value is already in the root file.
+- A file you name yourself, such as `.env.local`, is read only when you pass it to `supabase functions serve` with `--env-file`.
+- A `.env` at the root of your project is the one `config.toml` reads, through its `env()` function. See [Using secrets inside config.toml](/docs/guides/local-development/managing-config#using-secrets-inside-configtoml). A variable your function needs also has to be in `supabase/functions/.env`, even when the root file already holds the same value.
You can also set local values in `config.toml` itself, under `[edge_runtime.secrets]`:
@@ -199,25 +205,29 @@ You can also set local values in `config.toml` itself, under `[edge_runtime.secr
STRIPE_SECRET_KEY = "env(STRIPE_SECRET_KEY)"
```
----
-
-## Default secrets
+### Default secrets
Alongside the secrets you set yourself, Edge Functions have access to these by default:
-- `SUPABASE_URL`: The API gateway for your Supabase project
-- `SUPABASE_DB_URL`: The URL for your Postgres database. Use it to connect directly to your database
-- `SUPABASE_PUBLISHABLE_KEYS`: The `publishable` keys JSON dictionary for your Supabase API. This is safe to use in a browser when you have Row Level Security enabled
-- `SUPABASE_SECRET_KEYS`: The `secret` keys JSON dictionary for your Supabase API. This is safe to use in Edge Functions, but **never** use it in a browser. These keys bypass Row Level Security
-- `SUPABASE_JWKS`: The JSON Web Key Set used to verify user JWTs. Same value served at `https://.supabase.co/auth/v1/.well-known/jwks.json`
+| Variable | Description |
+| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `SUPABASE_URL` | The API gateway for your Supabase project. |
+| `SUPABASE_DB_URL` | The URL for your Postgres database. Use it to connect directly to your database. |
+| `SUPABASE_PUBLISHABLE_KEYS` | The `publishable` keys JSON dictionary for your Supabase API. Safe to use in a browser when you have Row Level Security enabled. |
+| `SUPABASE_SECRET_KEYS` | The `secret` keys JSON dictionary for your Supabase API. These keys bypass Row Level Security, so use them in Edge Functions and **never** in a browser. |
+| `SUPABASE_JWKS` | The JSON Web Key Set used to verify user JWTs. Same value served at `https://.supabase.co/auth/v1/.well-known/jwks.json`. |
Legacy keys:
-- `SUPABASE_ANON_KEY`: The `anon` key for your Supabase API. This is safe to use in a browser when you have Row Level Security enabled
-- `SUPABASE_SERVICE_ROLE_KEY`: The `service_role` key for your Supabase API. This is safe to use in Edge Functions, but **never** use it in a browser. This key bypasses Row Level Security
+| Variable | Description |
+| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
+| `SUPABASE_ANON_KEY` | The `anon` key for your Supabase API. Safe to use in a browser when you have Row Level Security enabled. |
+| `SUPABASE_SERVICE_ROLE_KEY` | The `service_role` key for your Supabase API. This key bypasses Row Level Security, so use it in Edge Functions and **never** in a browser. |
-In a hosted environment, functions have access to the following environment variables:
+In a hosted environment, functions also have access to these variables:
-- `SB_REGION`: The region the function was invoked in
-- `SB_EXECUTION_ID`: A UUID for the function instance, or [isolate](/docs/guides/functions/architecture#4-execution-mechanics-fast-and-isolated)
-- `DENO_DEPLOYMENT_ID`: The version of the function code, formatted as `{project_ref}_{function_id}_{version}`
+| Variable | Description |
+| -------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
+| `SB_REGION` | The region the function was invoked in. |
+| `SB_EXECUTION_ID` | A UUID for the function instance, or [isolate](/docs/guides/functions/architecture#4-execution-mechanics-fast-and-isolated). |
+| `DENO_DEPLOYMENT_ID` | The version of the function code, formatted as `{project_ref}_{function_id}_{version}`. |