# BETTER_AUTH_SECRET generator for Better Auth

> Generate a BETTER_AUTH_SECRET for Better Auth in your browser: 32 random bytes in Base64, and how to rotate it with BETTER_AUTH_SECRETS without losing data.

URL: https://crunu.com/tools/secret-generator/better-auth-secret
Language: en
Updated: 2026-10-31

**Generate a BETTER_AUTH_SECRET**

A random secret for Better Auth: 32 random bytes in Base64, the same as the openssl command in the Better Auth installation guide. Put it in BETTER_AUTH_SECRET, with its own value in every environment that runs your app.

No sign-up. Runs in your browser. Nothing you type is sent anywhere.

## At a glance

- **Variable:** BETTER_AUTH_SECRET; Better Auth also reads AUTH_SECRET
- **Format:** 32 random bytes in Base64: 44 characters with one = at the end
- **Randomness:** 256 bits
- **Requirement:** At least 32 characters, generated with high entropy

## The same without a browser

Better Auth CLI:

```sh
npx auth@latest secret
```

openssl:

```sh
openssl rand -base64 32
```

[Need another format? Use the general secret generator.](https://crunu.com/tools/secret-generator)

## What the secret protects

Better Auth's options reference describes it as the secret used for encryption, signing and hashing. The session_token cookie is an opaque session identifier signed with it. If you turn on the session cookie cache, the compact strategy adds an HMAC made with the secret, and the jwe strategy encrypts the cached session with it. In production Better Auth throws an error when no secret is set; outside production it falls back to a fixed default value, so a missing variable can go unnoticed until you deploy.

## What breaks when you change it

Swap the value outright and cookies signed with the old secret no longer verify, so people have to sign in again, and anything Better Auth encrypted with the old secret can no longer be decrypted. The docs describe the versioned BETTER_AUTH_SECRETS variable as the way to move to a new secret without invalidating existing data.

## Changing it without losing data

Set BETTER_AUTH_SECRETS to a comma-separated list of version:value pairs, newest first, such as 2:new-value,1:old-value. Better Auth encrypts new data with the first entry, keeps the rest for decryption only, and re-encrypts data with the current key the next time it is written. BETTER_AUTH_SECRET keeps working as a fallback for data written before the versioned format. The security reference says ordinary rotation needs no database migration and no downtime.

## How Crunu handles this: A separate value for every environment

In Crunu each environment has its own key, sealed separately to each person and machine allowed to read it, so a value generated for staging never travels with production. When you add a variable, Generate in the editor fills it with 40 random letters and digits right in the environment's table, so the value goes into the encrypted environment instead of through a clipboard and a chat window. The server stores values only as ciphertext.

[Read about the vault](https://crunu.com/features/vault)

## Questions about this tool

### How long should BETTER_AUTH_SECRET be?

The installation guide asks for at least 32 characters, generated with high entropy, and suggests openssl rand -base64 32. That command turns 32 random bytes into 44 Base64 characters, the same size as the value on this page.

### BETTER_AUTH_SECRET or AUTH_SECRET?

When the secret isn't set in code, Better Auth reads BETTER_AUTH_SECRET first and AUTH_SECRET second. Use BETTER_AUTH_SECRET, so it's clear which library the value belongs to and nothing else picks it up by accident.

### What happens if the variable is missing?

In production Better Auth throws an error. Outside production it falls back to a fixed default value that is printed in its documentation, so anyone could sign cookies with it. Set a real value in every environment you deploy, including previews.

### Do I need a different secret for each environment?

Yes. Give development, staging and production their own values, so a development secret pasted into a test, a log or a screenshot can't be used against production sessions.

## Read more

- [Environment variables in Next.js](https://crunu.com/environment-variables/nextjs)
- [Environment variables in SvelteKit](https://crunu.com/environment-variables/sveltekit)
- [Key rotation](https://crunu.com/learn/key-rotation)
- [Generate a NEXTAUTH_SECRET (AUTH_SECRET)](https://crunu.com/tools/secret-generator/nextauth-secret)
- [Generate a Django SECRET_KEY](https://crunu.com/tools/secret-generator/django-secret-key)
- [Generate a Rails secret_key_base](https://crunu.com/tools/secret-generator/rails-secret-key-base)
- [Generate a Laravel APP_KEY](https://crunu.com/tools/secret-generator/laravel-app-key)
- [Generate a JWT signing secret](https://crunu.com/tools/secret-generator/jwt-secret)

## Other free tools

- [Secret key generator](https://crunu.com/tools/secret-generator): Random secrets in Base64, Base64URL, hex or letters and digits, from 128 to 512 bits, with a ready .env line.
- [.env linter](https://crunu.com/tools/env-linter): Finds lines that loaders read differently, values that run as commands when sourced, duplicates and values that look like real keys.
- [.env converter](https://crunu.com/tools/env-converter): Turns a .env file into JSON, YAML, a Docker --env-file or a systemd EnvironmentFile, and back again.
- [Compare two .env files](https://crunu.com/tools/env-diff): Shows which variables exist in only one file and which have different values, with values hidden until you ask.
- [OIDC trust policy generator](https://crunu.com/tools/oidc-policy-builder): Trust policies and credentials for GitHub Actions, GitLab CI and Bitbucket Pipelines on AWS, Google Cloud and Azure, with the CI snippet.
- [Offboarding checklist generator](https://crunu.com/tools/offboarding-checklist): Pick the services someone could reach and get an ordered checklist of what to close and which keys to reissue, with links.
