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**. + +The Edge Function Secrets page in the Supabase Dashboard. An Add new secrets card holds a Key field whose placeholder reads "e.g. CLIENT_KEY" and a Value field with a reveal toggle and a remove button, above an Add another button and a Save button. + +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**. - -The Edge Function Secrets page in the Supabase Dashboard. An Add new secrets card holds a Key field hinting e.g. CLIENT_KEY and a Value field with a reveal toggle and a remove button, above an Add another button and a Save button. - -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}`. |