Unstack Pro Docs

Environment Variables

Complete guide to configuring Unstack Pro environment variables

Environment Variables

All environment variables must be set in Convex. Set them locally in .env.local for development, but they must also be configured in your Convex environment for production.

Security Notice: Never commit your .env.local file to version control. Keep your secrets secure!

What You're Configuring

All environment variables listed in this guide are required. Set them in .env.local for local development, but they must also be configured in your Convex environment for production:

  • Authentication: Better Auth configuration and secrets
  • Convex: Database connection and deployment URLs
  • Resend: Email service (required for sign-in and notifications)
  • Autumn: Billing and payment processing (required for organizations)
  • Application: URLs, domain configuration, and app name
  • Passkeys: WebAuthn/passkey authentication configuration

The auth system itself is already configured and working - you just need to connect the services.

Quick Setup

Copy the example file and fill in your values:

cp .env.example .env.local

Required Variables

All of these environment variables are required for the application to work properly:

Authentication

BETTER_AUTH_SECRET

Required: Yes Type: String Where: Everywhere (both .env.local and Convex environment and production)

Your secret key for Better Auth session encryption and security.

Generate with:

openssl rand -base64 32

Example:

BETTER_AUTH_SECRET="dGhpcyBpcyBhIHNlY3JldCBrZXkgZm9yIGF1dGhlbnRpY2F0aW9u"

This must be the same in both your .env.local file and Convex environment variables!

JWKS

Required: Yes Type: JSON String Where: Convex environment (required for production)

JSON Web Key Set containing the public/private key pair used for JWT token validation. This is automatically generated and rotated.

Generate or rotate keys with:

bunx convex run betterAuth/auth:rotateKeys | bunx convex env set JWKS

Key rotation will log out all users! Run this only when necessary, such as during low-traffic periods.

For production deployment, JWKS is automatically generated when you first set it up. The keys are stored in your Convex environment and used for validating JWT tokens across all requests.

Note: The betterAuth/auth:rotateKeys function must exist in your deployment. Run npx convex dev at least once to push your Convex functions before running this command.

BETTER_AUTH_URL

Required: Yes
Type: URL
Where: .env.local (and Convex environment for production)

The public URL where your application is accessible.

Development:

BETTER_AUTH_URL="http://localhost:3000"

Production:

BETTER_AUTH_URL="https://yourdomain.com"

OAuth callbacks and email links will use this URL. Make sure it matches your actual domain!

Convex Configuration

CONVEX_DEPLOYMENT

Required: Yes
Type: String
Where: .env.local (and production)

Your Convex deployment identifier.

Example:

CONVEX_DEPLOYMENT="dev:merry-bison-13"

This will be different for production (e.g., prod:your-prod-deployment-name).

Get this by:

NEXT_PUBLIC_CONVEX_URL

Required: Yes
Type: URL
Where: .env.local (and production)

Your Convex cloud deployment URL for client-side access.

Example:

NEXT_PUBLIC_CONVEX_URL="https://merry-bison-13.convex.cloud"

Variables prefixed with NEXT_PUBLIC_ are exposed to the browser.

NEXT_PUBLIC_CONVEX_SITE_URL

Required: Yes
Type: URL
Where: .env.local (and production)

Your Convex site URL for hosting static assets and functions.

Example:

NEXT_PUBLIC_CONVEX_SITE_URL="https://merry-bison-13.convex.site"

Application URLs

NEXT_PUBLIC_APP_URL

Required: Yes
Type: URL
Where: .env.local (and production)

Your application's public URL exposed to the browser.

Example:

NEXT_PUBLIC_APP_URL="https://dev.untraceable.dev"

For local development, this should be your local dev URL (e.g., https://dev.untraceable.dev). For production, use your production domain.

NEXT_PUBLIC_APP_NAME

Required: Yes
Type: String
Where: .env.local (and production)

The name of your application, used throughout the UI and emails.

Example:

NEXT_PUBLIC_APP_NAME="Unstack Pro"

Email Configuration

Required for email verification, password resets, and notifications. Email verification is required for users to sign in.

Email variables must be set in your Convex environment (where emails are sent from). You can also add them to .env.local for reference, but Convex is where they're actually used.

RESEND_API_KEY

Required: Yes
Type: String
Where: Convex environment (required), .env.local (optional, for reference)

Your Resend API key for sending transactional emails.

Example:

RESEND_API_KEY="re_123456789abcdefghijklmnop"

Get this by:

  1. Sign up at resend.com
  2. Create an API key in your dashboard
  3. Verify your sending domain (for production)

During development, you can use the test API key, but emails will only be sent to verified addresses.

EMAIL_FROM

Required: Yes
Type: String (Email format)
Where: Convex environment (required), .env.local (optional, for reference)

The sender email address and name for outgoing emails.

Example:

EMAIL_FROM="Unstack Pro <no-reply@auth.unstack.pro>"

Format: "Display Name <email@domain.com>"

The domain must be verified in your Resend account for production use.

Passkey Configuration

PASSKEY_RP_ID

Required: Yes
Type: String (Domain)
Where: .env.local (and production)

The Relying Party ID for WebAuthn/passkey authentication. Must match your domain.

Development:

PASSKEY_RP_ID="localhost"

Production:

PASSKEY_RP_ID="yourdomain.com"

The RP ID must match the domain where your app is hosted. For local development, use localhost. For production with subdomains, use the main domain (e.g., example.com not app.example.com) so that passkeys work across all subdomains.

Payments

AUTUMN_API_KEY

Required: Yes
Type: String
Where: Convex environment

Your Autumn API key for payment processing. Required for organization billing features.

Example:

AUTUMN_API_KEY="am_sk_test_key"

Autumn is optional. It's only required if you want per-seat billing for organizations. See the Billing documentation for instructions on removing it.

Setting Convex Environment Variables

All environment variables must be set in your Convex environment. Use the Convex CLI to set them:

# Authentication
npx convex env set BETTER_AUTH_SECRET "your-generated-secret-here"
npx convex env set BETTER_AUTH_URL "http://localhost:3000"

# Email configuration
npx convex env set RESEND_API_KEY "re_your_resend_api_key"
npx convex env set EMAIL_FROM "Your App <no-reply@yourdomain.com>"

# Payments (optional - only if using organization billing)
npx convex env set AUTUMN_API_KEY "am_sk_your_autumn_key"

# Application URLs
npx convex env set NEXT_PUBLIC_APP_URL "http://localhost:3000"
npx convex env set NEXT_PUBLIC_APP_NAME "Your App Name"

# Passkeys
npx convex env set PASSKEY_RP_ID "localhost"

You can view and manage Convex environment variables in your Convex dashboard.

Complete Example

Here's a complete .env.local file with all required variables:

.env.local
# Authentication (REQUIRED)
BETTER_AUTH_SECRET="your-generated-secret-here"
BETTER_AUTH_URL="http://localhost:3000"

# Email Configuration (REQUIRED)
RESEND_API_KEY="re_your_resend_api_key"
EMAIL_FROM="Your App <no-reply@yourdomain.com>"

# Payments (OPTIONAL - only if using organization billing)
AUTUMN_API_KEY="am_sk_your_autumn_key"

# Application URLs (REQUIRED)
NEXT_PUBLIC_APP_URL="http://localhost:3000"
NEXT_PUBLIC_APP_NAME="Your App Name"

# Convex Configuration (REQUIRED)
CONVEX_DEPLOYMENT="dev:your-deployment-name"
NEXT_PUBLIC_CONVEX_URL="https://your-deployment.convex.cloud"
NEXT_PUBLIC_CONVEX_SITE_URL="https://your-deployment.convex.site"

# Passkeys (REQUIRED)
PASSKEY_RP_ID="localhost"

Note: For production, update URLs to use your actual domain with HTTPS (e.g., https://yourdomain.com).

Environment Variable Checklist

Before deploying, make sure all these required variables are set:

  • BETTER_AUTH_SECRET is set in both .env.local and Convex
  • BETTER_AUTH_URL matches your actual domain
  • RESEND_API_KEY is configured in Convex
  • EMAIL_FROM is configured with verified domain in Convex
  • AUTUMN_API_KEY is configured in Convex (if using billing)
  • NEXT_PUBLIC_APP_URL matches your actual URL
  • NEXT_PUBLIC_APP_NAME is set to your application name
  • CONVEX_DEPLOYMENT is set correctly
  • NEXT_PUBLIC_CONVEX_URL is set correctly
  • NEXT_PUBLIC_CONVEX_SITE_URL is set correctly
  • PASSKEY_RP_ID matches your domain (localhost for dev, your domain for production)
  • .env.local is in .gitignore
  • Production secrets are different from development

Troubleshooting

Authentication Not Working

  1. Check BETTER_AUTH_SECRET is the same everywhere
  2. Verify BETTER_AUTH_URL matches your actual URL
  3. Clear cookies and try again

Emails Not Sending

  1. Verify RESEND_API_KEY is correct
  2. Check domain is verified in Resend
  3. Ensure EMAIL_FROM uses verified domain
  4. Variables are set in both .env.local and Convex

Passkeys Not Working

  1. PASSKEY_RP_ID must match your domain exactly
  2. For local development, use localhost
  3. For production, use your root domain

Convex Connection Issues

  1. Run npx convex dev to ensure deployment is active
  2. Check all three Convex URLs are correct
  3. Verify deployment exists in Convex dashboard

Security Best Practices

  1. Never commit secrets: Add .env.local to .gitignore
  2. Rotate secrets regularly: Especially BETTER_AUTH_SECRET
  3. Rotate JWKS keys periodically: Use bunx convex run betterAuth/auth:rotateKeys | bunx convex env set JWKS
  4. Use different secrets: Development and production should have different values
  5. Restrict API keys: Use the minimum permissions necessary
  6. Monitor access: Review Convex and Resend logs regularly

Production Reminder: Always use HTTPS in production. Never use http:// URLs for BETTER_AUTH_URL or NEXT_PUBLIC_APP_URL.

On this page