# How to Use ENCRYPTION_KEY with FreeLLMAPI: Complete Configuration Guide

> Learn to use ENCRYPTION_KEY with FreeLLMAPI for secure API key storage. This guide details configuration for production and development environments to protect your sensitive data.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: how-to-guide
- Published: 2026-06-27

---

**FreeLLMAPI requires a 32-byte (64-character hex) `ENCRYPTION_KEY` environment variable to secure provider API keys with AES-256-GCM encryption; production deployments fail to start without it, while development mode auto-generates a temporary local key.**

FreeLLMAPI encrypts every provider API key stored in its SQLite database using industry-standard AES-256-GCM. This security mechanism relies on the `ENCRYPTION_KEY` environment variable, which must be supplied as a cryptographically secure hexadecimal string to initialize the encryption layer.

## How ENCRYPTION_KEY Secures Provider Credentials

FreeLLMAPI uses AES-256-GCM encryption to protect sensitive provider tokens at rest. The `ENCRYPTION_KEY` serves as the master secret for this encryption layer. When you add a provider API key through the interface, the application encrypts it using the current key before writing to the database.

According to the FreeLLMAPI source code, the encryption module validates that the key is exactly 64 hexadecimal characters (representing 32 bytes) before use. This requirement is enforced in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts) through the `parseHexKey` function.

## Where FreeLLMAPI Loads the Encryption Key

The server attempts to load the encryption key from environment variables during startup. In [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts), the initialization logic checks for the `ENCRYPTION_KEY` environment variable:

```ts
if (envKey && envKey !== PLACEHOLDER_KEY) {
  cachedKey = parseHexKey(envKey, 'env');   // ✅ valid key → cached
}

```

If the variable is present and not a placeholder, the server parses and caches it for the runtime session.

### Production Requirements

In production environments, FreeLLMAPI enforces strict key presence. The boot sequence in [`server/src/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/index.ts) includes a guard that aborts startup if the encryption key is missing:

```ts
// A boot failure (e.g. a missing production ENCRYPTION_KEY) must exit

```

If `isDevFallbackAllowed()` returns false and no valid key exists, the server throws `missingKeyError()` and exits immediately.

### Development Fallback Behavior

During development, FreeLLMAPI can operate without manual key configuration. If `ENCRYPTION_KEY` is unset and the environment allows development fallbacks, the server checks the SQLite database for a persisted key:

```ts
const row = db.prepare("SELECT value FROM settings WHERE key = 'encryption_key'").get();
if (row) {
  cachedKey = parseHexKey(row.value, 'db');
  console.warn('[crypto] No ENCRYPTION_KEY set — using auto-generated key from the local DB (dev only).');
}

```

If no key exists in the database, FreeLLMAPI generates one cryptographically using `crypto.randomBytes(KEY_BYTES)`, persists it to the settings table, and logs a warning:

```ts
cachedKey = crypto.randomBytes(KEY_BYTES);
db.prepare("INSERT INTO settings (key, value) VALUES ('encryption_key', ?)").run(cachedKey.toString('hex'));
console.warn('[crypto] No ENCRYPTION_KEY set — generated and persisted a local dev key.');

```

## Generating a Valid 64-Character Hex Key

The `ENCRYPTION_KEY` must be exactly 64 hexadecimal characters (32 bytes). FreeLLMAPI provides two standard methods for generation:

**Using OpenSSL** (macOS/Linux):

```bash
ENCRYPTION_KEY=$(openssl rand -hex 32)
echo $ENCRYPTION_KEY

```

**Using Node.js** (cross-platform):

```bash
ENCRYPTION_KEY=$(node -e 'console.log(require("crypto").randomBytes(32).toString("hex"))')
echo $ENCRYPTION_KEY

```

Both commands output a string like `a1b2c3d4...` (64 characters) suitable for the environment variable.

## Configuring ENCRYPTION_KEY in Your Environment

After generating the key, persist it in a `.env` file in the project root:

```dotenv
ENCRYPTION_KEY=a1b2c3d4e5f6...64_chars_total...
PORT=3001

```

The `.env.example` file included in the repository demonstrates the required format:

```dotenv
ENCRYPTION_KEY=your-64-char-hex-key-here

```

For Docker deployments, pass the variable through your compose configuration:

```yaml
services:
  freellmapi:
    image: ghcr.io/tashfeenahmed/freellmapi:latest
    env_file: .env
    volumes:
      - freellmapi-data:/app/server/data

```

As documented in the README and Docker instructions, generate and write the key before first launch:

```bash
ENCRYPTION_KEY="$(openssl rand -hex 32)"
printf "ENCRYPTION_KEY=%s\nPORT=3001\n" "$ENCRYPTION_KEY" > .env

```

## The Risk of Changing Your Encryption Key

**Never change the `ENCRYPTION_KEY` after provider keys are stored.** Provider API keys are encrypted using the current master key. If you change `ENCRYPTION_KEY` after data exists, FreeLLMAPI cannot decrypt the stored credentials, rendering all provider configurations unusable.

When migrating or upgrading FreeLLMAPI, ensure the same `ENCRYPTION_KEY` value accompanies the `freellmapi-data` volume. If you must change keys, you must first delete all encrypted provider configurations and re-enter them after the new key is active.

## Key Validation and Error Handling

The `parseHexKey` function in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts) validates key format strictly. If you provide a malformed key, the server throws a descriptive error:

```

Invalid ENCRYPTION_KEY (env): expected 64 hex chars (32 bytes), got X chars.
Generate one with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

```

This validation occurs early in the boot process, ensuring configuration issues fail fast before the server accepts connections.

## Summary

- FreeLLMAPI uses **AES-256-GSM encryption** requiring a **64-character hex `ENCRYPTION_KEY`** (32 bytes).
- **Production deployments** fail immediately if the variable is missing; **development mode** auto-generates and caches a temporary key.
- Generate valid keys using `openssl rand -hex 32` or Node.js `crypto.randomBytes(32)`.
- Store the key in `.env` or pass via Docker environment variables before starting the server.
- **Changing the key invalidates existing encrypted provider data**; always maintain key continuity across upgrades.

## Frequently Asked Questions

### What happens if I don't set ENCRYPTION_KEY in production?

FreeLLMAPI aborts startup with a fatal error. The boot-time guard in [`server/src/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/index.ts) checks for key presence when `isDevFallbackAllowed()` returns false, throwing `missingKeyError()` and exiting the process to prevent running with unencrypted storage.

### Can I change the ENCRYPTION_KEY after initial setup?

Only if no provider API keys are stored. Since all provider credentials are encrypted with the master key, changing it renders existing database entries unreadable. To rotate keys, you must delete the `encryption_key` entry from the settings table (or wipe the data volume) and re-configure all providers.

### How do I generate a secure ENCRYPTION_KEY?

Use the built-in cryptographic tools demonstrated in the FreeLLMAPI documentation. Run `openssl rand -hex 32` on Unix systems or `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` on any platform with Node.js. Both produce a 64-character hexadecimal string that satisfies the `parseHexKey` validator.

### Why is FreeLLMAPI rejecting my ENCRYPTION_KEY as invalid?

The key must be exactly 64 hexadecimal characters (0-9, a-f). The `parseHexKey` function rejects values with incorrect length or non-hex characters. Ensure you haven't included quotes, whitespace, or the `0x` prefix in the environment variable value.