---
title: "Environment Configuration"
description: "Required and optional environment variables for Ring Platform — database backend, Firebase Admin SDK, FCM, Auth.js (Google / Telegram / Apple), payments, locales, Tunnel, and file storage."
locale: "en"
---
# Environment Configuration

> **Info**
> This page is the **canonical reference** for every environment variable consumed by Ring Platform.
>   The source of truth is `env.local.template` in the repository root — when in doubt, consult that file.
>   Use **Founder** / **Developer** tabs in the docs sidebar to filter by audience.

## `DB_BACKEND_MODE` (required)

Ring Platform requires `DB_BACKEND_MODE` at runtime. It controls which database adapter is active and how FCM push notifications are wired.

| Value | Application database | Firebase Admin for Firestore? | Push |
|-------|---------------------|-------------------------------|------|
| `k8s-postgres-fcm` | PostgreSQL (your cluster) | No — mock Firestore | FCM via Firebase Admin messaging |
| `firebase-full` | Firestore | Yes | FCM as part of full Firebase stack |
| `supabase-fcm` | Supabase PostgreSQL | No — mock Firestore | FCM via Firebase Admin messaging |

See [Backend modes and databases](/docs/architecture/backend-modes-and-databases.md) for a deep comparison.

### For founders

## Firebase: when is it needed?

Your Ring clone **may** need Firebase project credentials in two contexts:

1. **Push notifications (FCM)** — required in all three `DB_BACKEND_MODE` values if you want push delivery. Firebase is used as the FCM transport only; your application data stays in PostgreSQL.
2. **Full Firestore backend** — only when `DB_BACKEND_MODE=firebase-full`. In this mode Firebase Admin SDK serves as the primary database.

**If you don't need push notifications**, you can omit all Firebase environment variables. The platform runs on PostgreSQL alone.

Firebase Admin SDK v14 uses **Application Default Credentials (ADC)** in the `FirebaseAdapter` (database abstraction layer). For the FCM/auth path (`firebase-admin.server.ts`), explicit service-account credentials via `AUTH_FIREBASE_CLIENT_EMAIL` + `AUTH_FIREBASE_PRIVATE_KEY` are still required when ADC is not configured.

In production (Cloud Run, Cloud Functions, GKE), ADC auto-detects credentials from the environment. You only need `AUTH_FIREBASE_PROJECT_ID`. On local dev or CI, provide the full service-account key set.

### For developers

## Database backend

```bash
# Required — selects database adapter + FCM wiring
DB_BACKEND_MODE=k8s-postgres-fcm

# PostgreSQL connection (required for k8s-postgres-fcm and supabase-fcm)
DB_HOST=localhost
DB_PORT=5432
DB_NAME=ring_platform
DB_USER=ring_user
DB_PASSWORD=ring_password_2024
DB_POOL_SIZE=20
DB_TIMEOUT=30000
DB_RETRIES=3
DB_SSL=false
```

The canonical dev setup uses `ring-postgres-dev` (postgres:16-alpine). See `docker-compose.dev.yml`.

## Firebase Admin SDK (server-side)

```bash
# Minimum for FCM-only usage:
AUTH_FIREBASE_PROJECT_ID=your_firebase_project_id

# Required when ADC is not configured (local dev / CI):
AUTH_FIREBASE_CLIENT_EMAIL=your_firebase_client_email
AUTH_FIREBASE_PRIVATE_KEY="your_firebase_private_key"

# Optional
FIREBASE_DATABASE_URL=https://your-project-default-rtdb.firebaseio.com
FIREBASE_PRIVATE_KEY_ID=your_firebase_private_key_id
FIREBASE_CLIENT_ID="your_firebase_client_id"
FIREBASE_FIRESTORE_DEBUG=true
```

- **`lib/firebase-admin.server.ts`** (FCM + Auth path): always requires `AUTH_FIREBASE_PROJECT_ID`. When `AUTH_FIREBASE_CLIENT_EMAIL` and `AUTH_FIREBASE_PRIVATE_KEY` are present, uses explicit `cert()`. Falls back to ADC if they are absent.
- **`lib/database/adapters/FirebaseAdapter.ts`** (database abstraction): uses ADC first. If `credentials.clientEmail` and `credentials.privateKey` are in the backend config, falls back to explicit `cert()`. This path is only active in `firebase-full` mode.

> **Tip**
> On Cloud Run / Cloud Functions / GKE: set only `AUTH_FIREBASE_PROJECT_ID`. The SDK auto-detects credentials via ADC.
>   On local dev: set `AUTH_FIREBASE_CLIENT_EMAIL` and `AUTH_FIREBASE_PRIVATE_KEY` from your service-account JSON key.

## Firebase Client SDK (browser-side)

Required when your Ring clone uses Firebase for **client-side features** (FCM push token registration, FirebaseUI auth):

```bash
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_firebase_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-YCZKPV315E
NEXT_PUBLIC_FIREBASE_VAPID_KEY=your_vapid_key
```

Get client SDK keys from **Firebase Console → Project Settings → General → Web apps**. Set `NEXT_PUBLIC_FIREBASE_VAPID_KEY` from **Cloud Messaging → Web Push certificates** for that same project (build-time for the browser). RFC dual-stack runtime secrets: `VAPID_*` — see [Push notifications (FCM)](/docs/features/push-notifications-fcm.md).

## Auth providers

```bash
# Auth.js core
AUTH_SECRET=your_auth_secret
AUTH_TRUST_HOST=true

# Google OAuth (required for Google sign-in)
AUTH_GOOGLE_ID=your_google_client_id
AUTH_GOOGLE_SECRET=your_google_client_secret

# Telegram Web Login OIDC (BotFather → Bot Settings → Web Login)
# Allowed URLs: https:// and https:///api/auth/callback/telegram
AUTH_TELEGRAM_ID=your_telegram_oidc_client_id
AUTH_TELEGRAM_SECRET=your_telegram_oidc_client_secret
# ADMIN_BOT_TOKEN=...  # Login Widget hash + admin bot API (not the OIDC secret)

# Apple Sign-In (required for Apple sign-in)
AUTH_APPLE_ID=your_apple_client_id
AUTH_APPLE_SECRET=your_apple_private_key

# Ring Mailer — OTP / magic link / reset (own SMTP; no AUTH_RESEND_*)
# EMAIL_MODE=ethereal
SMTP_HOST=mail.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=noreply@example.com
SMTP_PASSWORD=
SMTP_FROM=Ring Platform <noreply@example.com>
# OTP_HMAC_SECRET=
```

Auth.js v5 reads `AUTH_*` prefixed vars for OAuth/OIDC providers (Google, Telegram, Apple). Email auth uses Ring Mailer — see [Ring Mailer](/docs/features/ring-mailer.md) and [Authentication](/docs/features/authentication.md).

## Payments (PaymentConductor)

```bash
# Default processor
PAYMENT_DEFAULT_PROCESSOR=stripe

# Per-purpose overrides (optional)
PAYMENT_STORE_PROCESSOR=stripe
PAYMENT_MEMBERSHIP_PROCESSOR=stripe
PAYMENT_NEWS_PROCESSOR=stripe

# WayForPay
WAYFORPAY_MERCHANT_ACCOUNT=your_merchant
WAYFORPAY_SECRET_KEY=your_secret

# Stripe (alternative)
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
PAYMENT_FIAT_CURRENCY=USD
```

Apply `data/migrations/004_payment_transactions.sql` before production payments.

## Locales

```bash
NEXT_PUBLIC_SUPPORTED_LOCALES=en,uk,ru
NEXT_PUBLIC_DEFAULT_LOCALE=en
```

See `lib/locale-config.ts`. Supported locales: `en`, `uk`, `ru`.

## Generative conductors (xAI Grok)

```bash
XAI_API_KEY=your_xai_key
XAI_API_BASE_URL=https://api.x.ai/v1
```

Per‑purpose prefixes:
- `IMAGE_GEN_*` / `XAI_IMAGE_*` — ImageConductor
- `TEXT_GEN_*` / `XAI_TEXT_*` — TextConductor (cited articles)
- `TTS_*` / `XAI_TTS_*` — AudioConductor (narration)
- `NEWS_AUTOGEN_*` — newsroom draft defaults

Requires `NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase` (or `ring-config.json` `storage.provider`) with `RINGBASE_API_URL` and `RINGBASE_API_TOKEN` for CDN-backed uploads. See [RingFileBase](/docs/integrations/ring-filebase.md) and [Ring CDN](/docs/integrations/ring-cdn.md).

## File storage (`file()`)

Provider SSOT: `lib/storage/storage-config.ts` — env → `ring-config.json` `storage.provider` → default (`local_storage` in development, `vercel_blob` in production).

```bash
# local_storage | vercel_blob | ring_filebase | firebase_storage
NEXT_PUBLIC_STORAGE_PROVIDER=local_storage

# vercel_blob
# BLOB_READ_WRITE_TOKEN=vercel_blob_rw_...

# local_storage
# NEXT_PUBLIC_LOCAL_STORAGE_URL=/uploads
# LOCAL_STORAGE_DIR=public/uploads

# ring_filebase (self-hosted / k8s) — write authority is k3s-or primary
# Prod (in-cluster):
# RINGBASE_API_URL=http://ring-filebase-api.ring-filebase.svc.cluster.local
# Local / CI (public write API on primary):
# RINGBASE_API_URL=https://filebase-api.ring-platform.org
# RINGBASE_API_TOKEN=...   # Secret — claim-shaped Bearer for ring-filebase-api
# RINGBASE_PUBLIC_URL=https://cdn.ring-platform.org
# NEXT_PUBLIC_RINGBASE_API_URL=   # optional fallback for API URL
# REFMAGIC_CDN_INTERNAL_URL=http://ring-filebase-cdn.ring-filebase.svc.cluster.local
```

CDN slaves (k3s-3 / k8s-1) are pull-mirrors only — never point uploads at them.
Do **not** set `RINGBASE_API_URL` to your Next.js `api.` hostname — that ingress serves the app, not RingFileBase.

## WalletConnect / Reown (EVM mobile QR)

```bash
# WalletConnect / Reown Cloud project ID (https://cloud.reown.com)
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=
```

Buyer-writable on Order Lab **Secrets** (`public_shared`). Without a real Project ID, WalletConnect stays disabled (injected MetaMask still works). Step-by-step: [WalletConnect Project ID](/docs/configuration/walletconnect.md). Wagmi stack: [Ethereum wallets](/docs/integrations/ethereum-wallets.md).

## Ring Tunnel (real-time)

```bash
# vercel | k8s | self-hosted
RING_DEPLOY_TARGET=self-hosted
NEXT_PUBLIC_RING_DEPLOY_TARGET=self-hosted

# Optional explicit WS URL (default: same host /api/tunnel/ws)
# NEXT_PUBLIC_TUNNEL_WS_URL=wss://ring-platform.org/api/tunnel/ws
```

## Feature flags

```bash
FEATURE_DOCUMENTATION=true
FEATURE_NETWORKING=true
FEATURE_MESSAGING=true
FEATURE_WALLET=true
FEATURE_AI_MATCHER=true
FEATURE_WEB3_INTEGRATION=true
```

## Platform

```bash
NEXT_PUBLIC_BASE_URL=https://ring-platform.org
NODE_ENV=development
```

## Optional — Email AI-CRM, CRON, backup

See `env.local.template` for the complete commented reference. Key optional blocks:

```bash
# Email CRM (IMAP poll + admin UI)
# IMAP_HOST=mail.example.com
# IMAP_PORT=993
# ...

# CRON protection
# CRON_SECRET=generate-a-long-random-string

# Backup & compliance
# BACKUP_ENABLED=true
# BACKUP_SCHEDULE=0 2 * * *
```

> **Warning**
> **Never commit real secrets to Git.** The `env.local.template` file uses placeholder values. Copy it to `.env.local` (gitignored) and fill in your production values. Use K8s secrets or your deployment system's secret store for production.

## Related documentation

  
- [configuration](/docs/configuration.md) — Next-step: Order Lab configuration hub (public vars, secrets, services).

  
- [configuration/walletconnect](/docs/configuration/walletconnect.md) — Same-workflow: create Reown Cloud Project ID for NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID.

  
- [architecture/backend-modes-and-databases](/docs/architecture/backend-modes-and-databases.md) — Deep-dive: DB_BACKEND_MODE comparison and Firebase vs PostgreSQL.

  
- [customization/database-selection](/docs/customization/database-selection.md) — See-also: decision guide for choosing your backend mode.

  
- [architecture/authentication](/docs/architecture/authentication.md) — Depends-on: Auth.js v5 provider configuration.

  
- [deployment/docker](/docs/deployment/docker.md) — See-also: container build and deployment.
