docs/self-hosting/migration/v2/auth/nextauth-to-betterauth.mdx
This guide helps you migrate your existing NextAuth-based LobeHub deployment to Better Auth.
<Callout type={'info'}> Better Auth is the recommended authentication solution for LobeHub. It offers simpler configuration, more SSO providers, and better self-hosting support. </Callout>
<Callout type={'error'}> Important Notice:
| Method | Best For | User Impact | Data Preserved |
|---|---|---|---|
| Simple Migration | Small deployments (≤ 10 users) | Users need to re-login | Chat history, settings |
| Full Migration | Large deployments | Seamless for users | Everything including SSO connections |
<Callout type={'info'}> Note: NextAuth never supported email/password login, so there are no password hashes to migrate. The main benefit of full migration is preserving SSO connections (Google, GitHub, etc.). </Callout>
| NextAuth (Old) | Better Auth (New) | Notes |
|---|---|---|
NEXT_PUBLIC_ENABLE_NEXT_AUTH | (Deprecated) | No longer needed, Better Auth auto-enables with database |
NEXT_AUTH_SECRET | AUTH_SECRET | Session encryption key |
AUTH_URL | APP_URL | Application URL (for OAuth callbacks) |
NEXT_AUTH_SSO_PROVIDERS | AUTH_SSO_PROVIDERS | SSO provider list (comma-separated) |
NEXT_AUTH_SSO_SESSION_STRATEGY | (Deprecated) | No longer needed, Better Auth uses DB sessions |
SSO provider environment variables follow the same format: AUTH_<PROVIDER>_ID and AUTH_<PROVIDER>_SECRET.
| NextAuth (Old) | Better Auth (New) | Notes |
|---|---|---|
AUTH_GITHUB_ID | AUTH_GITHUB_ID | ✅ Unchanged |
AUTH_GITHUB_SECRET | AUTH_GITHUB_SECRET | ✅ Unchanged |
AUTH_GOOGLE_ID | AUTH_GOOGLE_ID | ✅ Unchanged |
AUTH_GOOGLE_SECRET | AUTH_GOOGLE_SECRET | ✅ Unchanged |
AUTH_AUTH0_ID | AUTH_AUTH0_ID | ✅ Unchanged |
AUTH_AUTH0_SECRET | AUTH_AUTH0_SECRET | ✅ Unchanged |
AUTH_AUTH0_ISSUER | AUTH_AUTH0_ISSUER | ✅ Unchanged |
AUTH_AUTHENTIK_ID | AUTH_AUTHENTIK_ID | ✅ Unchanged |
AUTH_AUTHENTIK_SECRET | AUTH_AUTHENTIK_SECRET | ✅ Unchanged |
AUTH_AUTHENTIK_ISSUER | AUTH_AUTHENTIK_ISSUER | ✅ Unchanged |
microsoft-entra-id | microsoft | ⚠️ Provider renamed |
AUTH_MICROSOFT_ENTRA_ID_ID | AUTH_MICROSOFT_ID | ⚠️ Variable renamed |
AUTH_MICROSOFT_ENTRA_ID_SECRET | AUTH_MICROSOFT_SECRET | ⚠️ Variable renamed |
AUTH_MICROSOFT_ENTRA_ID_TENANT_ID | AUTH_MICROSOFT_TENANT_ID | ⚠️ Variable renamed |
AUTH_MICROSOFT_ENTRA_ID_BASE_URL | AUTH_MICROSOFT_AUTHORITY_URL | ⚠️ Variable renamed |
<Callout type={'warning'}>
Note: Microsoft Entra ID provider name changed from microsoft-entra-id to microsoft, and the environment variable prefix changed from AUTH_MICROSOFT_ENTRA_ID_ to AUTH_MICROSOFT_.
</Callout>
Better Auth supports additional features with these new environment variables:
| Environment Variable | Description |
|---|---|
AUTH_ALLOWED_EMAILS | Email whitelist (restrict registration) |
AUTH_EMAIL_VERIFICATION | Enable email verification (set to 1) |
AUTH_ENABLE_MAGIC_LINK | Enable magic link login (set to 1) |
EMAIL_SERVICE_PROVIDER | Email provider (nodemailer or resend) |
For small self-hosted deployments, the simplest approach is to let users re-login with their SSO accounts.
<Callout type={'tip'}> Casdoor Users: If you use Casdoor as your identity provider, please read the email_not_found Error section first to understand email configuration requirements. </Callout>
<Callout type={'warning'}> Limitation: This method loses SSO connection data. Use Full Migration to preserve SSO connections.
Although SSO connections will be lost, users can manually re-bind social accounts through the profile page after logging in.
Example scenario: If your previous account had two SSO accounts linked:
[email protected][email protected]After migrating, logging in with [email protected] will create a new user instead of linking to your existing account.
</Callout>
Update Environment Variables
Remove NextAuth variables and add Better Auth variables:
<GenerateSecret envName="AUTH_SECRET" /># Remove these
# NEXT_AUTH_SECRET=xxx
# AUTH_xxx related NextAuth provider configs
# Add these
AUTH_SECRET=your-secret-key # openssl rand -base64 32
# Optional: Enable Google SSO (example)
AUTH_SSO_PROVIDERS=google
AUTH_GOOGLE_ID=your-google-client-id
AUTH_GOOGLE_SECRET=your-google-client-secret
<Callout type={'tip'}> See Authentication Service Configuration for complete environment variables and SSO provider setup. </Callout>
Redeploy LobeHub
Deploy the new version with Better Auth enabled.
Notify Users
Inform users to log in again with their previous SSO account. Chat history and settings will be preserved since user IDs remain the same.
<Callout type={'tip'}> This method is quick and requires minimal setup. Users just need to re-login with their existing SSO provider. </Callout>
For larger deployments or when you need to preserve SSO connections, use the migration script. This migrates data from the nextauth_accounts table to the Better Auth accounts table.
<Callout type={'error'}> Important Notice:
Environment Requirements:
Preparation:
Clone the LobeHub repository and install dependencies:
git clone https://github.com/lobehub/lobehub.git
cd lobehub
pnpm install
Prepare the database connection string
Ensure database schema is up to date
<Callout type={'info'}> If you've been on an older version for a while, your database schema may be outdated. Run this in the cloned repository:
DATABASE_URL=your-database-url pnpm db:migrate
Create a .env file in the project root (the script will automatically load it) with all environment variables:
# ============================================
# Migration mode: test or prod
# Recommended: Start with test mode to verify on a test database,
# then switch to prod after confirming everything works
# ============================================
NEXTAUTH_TO_BETTERAUTH_MODE=test
# ============================================
# Database connection (uses corresponding variable based on mode)
# TEST_ prefix for test environment, PROD_ prefix for production
# ============================================
TEST_NEXTAUTH_TO_BETTERAUTH_DATABASE_URL=postgresql://user:pass@test-host:5432/testdb
PROD_NEXTAUTH_TO_BETTERAUTH_DATABASE_URL=postgresql://user:pass@prod-host:5432/proddb
# ============================================
# Database driver (optional)
# neon: Neon serverless driver (default)
# node: node-postgres driver
# ============================================
NEXTAUTH_TO_BETTERAUTH_DATABASE_DRIVER=neon
# ============================================
# Batch size (optional)
# Number of records to process per batch, default is 300
# ============================================
NEXTAUTH_TO_BETTERAUTH_BATCH_SIZE=300
# ============================================
# Dry Run mode (optional)
# Set to 1 to only print logs without modifying the database
# Recommended: Enable for first run, disable after verification
# ============================================
NEXTAUTH_TO_BETTERAUTH_DRY_RUN=1
# Run migration (NEXTAUTH_TO_BETTERAUTH_DRY_RUN=1, only logs without modifying database)
npx tsx scripts/nextauth-to-betterauth/index.ts
Review the output logs, confirm no issues, then proceed to the next step.
Update .env to set NEXTAUTH_TO_BETTERAUTH_DRY_RUN to 0, then execute:
# Execute migration
npx tsx scripts/nextauth-to-betterauth/index.ts
# Verify the migration
npx tsx scripts/nextauth-to-betterauth/verify.ts
After verifying the test environment migration is successful, proceed to the next step.
.env file:
NEXTAUTH_TO_BETTERAUTH_MODE to prodNEXTAUTH_TO_BETTERAUTH_DRY_RUN back to 1# Run migration (dry-run mode to verify)
npx tsx scripts/nextauth-to-betterauth/index.ts
Review the output logs, confirm no issues, then proceed to the next step.
Update .env to set NEXTAUTH_TO_BETTERAUTH_DRY_RUN to 0, then execute:
# Execute migration
npx tsx scripts/nextauth-to-betterauth/index.ts
# Verify the migration
npx tsx scripts/nextauth-to-betterauth/verify.ts
After migration is complete, follow Simple Migration - Step 1 to configure Better Auth environment variables and redeploy.
<Callout type={'tip'}> For complete Better Auth configuration, see Authentication Service Configuration, including all supported SSO providers and email service configuration. </Callout>
| Data | Simple Migration | Full Migration |
|---|---|---|
| User accounts | ✅ (via re-login) | ✅ |
| SSO connections (Google, GitHub, etc.) | ❌ | ✅ |
| Chat history | ✅ | ✅ |
| User settings | ✅ | ✅ |
<Callout type={'info'}> Note: Sessions and verification tokens are not migrated as they are temporary data. Users will need to log in again after migration. </Callout>
After migration, if you encounter login issues, try clearing your browser's site data first:
AUTH_SECRET is set correctlyAUTH_SSO_PROVIDERSAUTH_SSO_PROVIDERS with the same provider IDnextauth_accounts table exists in your databaseThis error occurs because the database schema is outdated. Run pnpm db:migrate to update the database structure before running the migration script.
If you see a redirect to signin?callbackUrl=...&error=email_not_found, it means LobeHub cannot get the user's email.
<Callout type={'warning'}> Important: Better Auth currently requires user email for authentication. All SSO providers must be configured to return email information, otherwise users cannot log in. </Callout>
Common causes:
Cause 1: SSO connection not requesting email permission
When configuring SSO connections (e.g., GitHub in Auth0), make sure to enable Email Address permission in the Attributes section. LobeHub requires user email for authentication.
Cause 2: User email not configured in identity provider
For identity providers like Casdoor or Logto, users may not have an email configured.
<Callout type={'warning'}> Note for Casdoor Users: Casdoor does not require users to have an email configured, but LobeHub strongly depends on email for authentication. If you find migration difficult due to many users without email addresses, we recommend staying on v2.0.0-next.344 for now. We plan to provide a self-service migration feature in the future, where users without email will be redirected to a bind-email page when they log in. </Callout>
Solution:
<Card href={'/docs/self-hosting/auth'} title={'Authentication Service Configuration'} />
<Card href={'/docs/self-hosting/environment-variables/auth'} title={'Auth Environment Variables'} />
<Card href={'/docs/self-hosting/auth/legacy'} title={'Legacy Authentication (NextAuth & Clerk)'} /> </Cards>