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.localRequired 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 32Example:
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 JWKSKey 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:
- Running
npx convex dev - Or from your Convex dashboard
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:
- Sign up at resend.com
- Create an API key in your dashboard
- 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:
# 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_SECRETis set in both.env.localand Convex -
BETTER_AUTH_URLmatches your actual domain -
RESEND_API_KEYis configured in Convex -
EMAIL_FROMis configured with verified domain in Convex -
AUTUMN_API_KEYis configured in Convex (if using billing) -
NEXT_PUBLIC_APP_URLmatches your actual URL -
NEXT_PUBLIC_APP_NAMEis set to your application name -
CONVEX_DEPLOYMENTis set correctly -
NEXT_PUBLIC_CONVEX_URLis set correctly -
NEXT_PUBLIC_CONVEX_SITE_URLis set correctly -
PASSKEY_RP_IDmatches your domain (localhostfor dev, your domain for production) -
.env.localis in.gitignore - Production secrets are different from development
Troubleshooting
Authentication Not Working
- Check
BETTER_AUTH_SECRETis the same everywhere - Verify
BETTER_AUTH_URLmatches your actual URL - Clear cookies and try again
Emails Not Sending
- Verify
RESEND_API_KEYis correct - Check domain is verified in Resend
- Ensure
EMAIL_FROMuses verified domain - Variables are set in both
.env.localand Convex
Passkeys Not Working
PASSKEY_RP_IDmust match your domain exactly- For local development, use
localhost - For production, use your root domain
Convex Connection Issues
- Run
npx convex devto ensure deployment is active - Check all three Convex URLs are correct
- Verify deployment exists in Convex dashboard
Security Best Practices
- Never commit secrets: Add
.env.localto.gitignore - Rotate secrets regularly: Especially
BETTER_AUTH_SECRET - Rotate JWKS keys periodically: Use
bunx convex run betterAuth/auth:rotateKeys | bunx convex env set JWKS - Use different secrets: Development and production should have different values
- Restrict API keys: Use the minimum permissions necessary
- 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.