Skip to content

Secrets Management

Fluxbase provides a secure secrets management system for storing API keys, database credentials, and other sensitive values that your edge functions and background jobs need at runtime.

Secrets are:

  • Encrypted at rest using AES-256-GCM
  • Scoped to global or namespace level
  • Version controlled with rollback support
  • Injected automatically into function runtime as environment variables

View all secrets (values are never displayed):

Terminal window
# List all secrets
fluxbase secrets list
# Filter by scope
fluxbase secrets list --scope global
fluxbase secrets list --scope namespace
# Filter by namespace
fluxbase secrets list --namespace production
Terminal window
# Create a global secret
fluxbase secrets set API_KEY "sk-your-api-key"
# Create a namespace-scoped secret
fluxbase secrets set DATABASE_URL "postgres://..." --scope namespace --namespace production
# Add a description
fluxbase secrets set STRIPE_KEY "sk_live_..." --description "Stripe production API key"
# Set an expiration
fluxbase secrets set TEMP_TOKEN "xyz" --expires 30d
Terminal window
# Get metadata (value is never returned)
fluxbase secrets get API_KEY
# For namespaced secrets
fluxbase secrets get DATABASE_URL --namespace production
Terminal window
# Delete a secret
fluxbase secrets delete API_KEY
# Delete a namespaced secret
fluxbase secrets delete DATABASE_URL --namespace production

Secrets maintain version history for audit and rollback:

Terminal window
# View version history
fluxbase secrets history API_KEY
# Rollback to a previous version
fluxbase secrets rollback API_KEY 2

Secrets support two scope levels:

ScopeDescriptionUse Case
globalAvailable to all functions in all namespacesShared API keys, common credentials
namespaceAvailable only to functions in a specific namespaceEnvironment-specific secrets (prod vs staging)

When a function requests a secret, Fluxbase resolves it in this order:

  1. Namespace-scoped secret (if function is in a namespace)
  2. Global secret (fallback)

This allows you to override global defaults with namespace-specific values.

Secrets are injected as environment variables with the FLUXBASE_SECRET_ prefix:

functions/send-email.ts
export default async function handler(req: Request): Promise<Response> {
// Access secrets via environment variables
const apiKey = Deno.env.get("FLUXBASE_SECRET_SENDGRID_API_KEY");
if (!apiKey) {
return new Response("Missing API key", { status: 500 });
}
const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
// email data
}),
});
return new Response("Email sent");
}

For cleaner code, use the built-in secrets object:

functions/process-payment.ts
export default async function handler(req: Request): Promise<Response> {
// Use the secrets helper
const stripeKey = secrets.get("STRIPE_SECRET_KEY");
// Or require the secret (throws if missing)
const requiredKey = secrets.getRequired("STRIPE_SECRET_KEY");
// Your logic here
}

Background jobs have the same access to secrets:

jobs/sync-data.ts
export default async function handler(payload: unknown): Promise<void> {
const apiKey = Deno.env.get("FLUXBASE_SECRET_EXTERNAL_API_KEY");
const dbUrl = Deno.env.get("FLUXBASE_SECRET_ANALYTICS_DB");
// Sync data to external service
await syncToExternalService(apiKey, payload);
}

Fluxbase provides two secrets systems:

Featurefluxbase settings secretsfluxbase secrets
Storageapp.settings tablefunctions.secrets table
ScopesSystem, UserGlobal, Namespace
User-specificYes (with HKDF encryption)No
Version historyNoYes
Function accesssecrets.get()Deno.env.get("FLUXBASE_SECRET_*")
Best forApplication config, per-user keysFunction runtime secrets

For new projects, consider which system fits your needs:

  • Edge function secrets: Use fluxbase secrets (this guide)
  • Application configuration: Use fluxbase settings secrets
  • Per-user API keys: Use fluxbase settings secrets --user

Separate production and development secrets:

Terminal window
# Development
fluxbase secrets set STRIPE_KEY "sk_test_..." --scope namespace --namespace development
# Production
fluxbase secrets set STRIPE_KEY "sk_live_..." --scope namespace --namespace production
Terminal window
# Expires in 30 days
fluxbase secrets set TEMP_TOKEN "xyz" --expires 30d
# Expires in 1 year
fluxbase secrets set ANNUAL_KEY "abc" --expires 1y
Terminal window
# Good
fluxbase secrets set SENDGRID_API_KEY "..." --description "SendGrid transactional email API key"
# Avoid
fluxbase secrets set KEY1 "..."

Use version history to track changes:

Terminal window
# Update the secret (creates new version)
fluxbase secrets set API_KEY "new-value"
# View history
fluxbase secrets history API_KEY
# Rollback if needed
fluxbase secrets rollback API_KEY 1

Check which functions use which secrets:

Terminal window
# Review function logs for secret access
fluxbase logs list --category execution --search "FLUXBASE_SECRET"

You can also provide secrets via environment variables when running Fluxbase:

Terminal window
# These are available to all functions
export FLUXBASE_SECRET_API_KEY="your-key"
export FLUXBASE_SECRET_DATABASE_URL="postgres://..."

Environment variables take precedence over stored secrets, useful for:

  • Local development
  • CI/CD pipelines
  • Kubernetes secrets injection

Name-based endpoints are the recommended way to work with secrets. They use the secret name instead of UUIDs, making them easier to use.

MethodEndpointDescription
GET/api/v1/secrets/by-name/:nameGet secret by name (query: namespace)
PUT/api/v1/secrets/by-name/:nameUpdate secret by name (query: namespace)
DELETE/api/v1/secrets/by-name/:nameDelete secret by name (query: namespace)
GET/api/v1/secrets/by-name/:name/versionsGet version history by name (query: namespace)
POST/api/v1/secrets/by-name/:name/rollback/:versionRollback by name (query: namespace)

UUID-based endpoints are kept for backward compatibility. For new code, prefer name-based endpoints above.

MethodEndpointDescription
GET/api/v1/secretsList all secrets (query: scope, namespace)
GET/api/v1/secrets/statsGet secret statistics
POST/api/v1/secretsCreate a secret
GET/api/v1/secrets/:idGet secret metadata by UUID
PUT/api/v1/secrets/:idUpdate a secret by UUID
DELETE/api/v1/secrets/:idDelete a secret by UUID
GET/api/v1/secrets/:id/versionsGet version history by UUID
POST/api/v1/secrets/:id/rollback/:versionRollback to version by UUID
{
"name": "API_KEY",
"value": "sk-your-secret-key",
"scope": "global",
"namespace": "production",
"description": "External API key",
"expires_at": "2025-12-31T00:00:00Z"
}

Note: namespace is only required when scope is "namespace". The :id in UUID-based endpoints is a UUID returned after creation.

{
"value": "new-secret-value",
"description": "Updated description",
"expires_at": "2026-12-31T00:00:00Z"
}

The TypeScript SDK provides a secrets manager with both name-based and UUID-based methods:

import { createClient } from "@nimbleflux/fluxbase-sdk";
const client = createClient({ url: "http://localhost:8080" });
// Create a secret
const secret = await client.secrets.create({
name: "API_KEY",
value: "sk-your-api-key",
scope: "global",
description: "External API key",
});
// Get secret by name (recommended)
const secret = await client.secrets.get("API_KEY");
// Get namespace-scoped secret
const secret = await client.secrets.get("DATABASE_URL", {
namespace: "production",
});
// Update secret by name
await client.secrets.update("API_KEY", { value: "new-api-key" });
// Delete secret by name
await client.secrets.delete("OLD_KEY");
// Get version history
const versions = await client.secrets.getVersions("API_KEY");
// Rollback to version 2
await client.secrets.rollback("API_KEY", 2);
// List all secrets
const secrets = await client.secrets.list();
// List by scope
const globalSecrets = await client.secrets.list({ scope: "global" });
// Get statistics
const stats = await client.secrets.stats();