# How to Generate an Encryption Key for FreeLLMAPI: Production and Development Setup

> Learn how to generate a 32-byte encryption key for FreeLLMAPI. Securely encrypt provider API keys at rest for production and development setups. Simple AES-256-GCM setup.

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

---

**FreeLLMAPI requires a 32-byte hexadecimal encryption key set via the `ENCRYPTION_KEY` environment variable or stored in a `.encryption-key` file to encrypt provider API keys at rest using AES-256-GCM.**

FreeLLMAPI, the open-source LLM aggregation proxy developed by tashfeenahmed, safeguards stored provider credentials using AES-256-GCM encryption. To generate an encryption key for FreeLLMAPI, you must create a cryptographically secure 64-character hex string (representing 32 bytes) and configure it before starting the server. The application supports both explicit environment variable configuration for production and automatic file-based generation for local development.

## Understanding FreeLLMAPI's Encryption Requirements

FreeLLMAPI encrypts all stored provider API keys at rest using **AES-256-GCM**. The encryption key must be exactly **32 bytes** (represented as a 64-character hexadecimal string). According to the source code in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts), the server accepts keys from two sources with the following precedence:

1. The `ENCRYPTION_KEY` environment variable (required in production)
2. A `.encryption-key` file located adjacent to the SQLite database (auto-generated in development)

The `.encryption-key` file is created with ** restrictive `0600` permissions** (read/write for owner only), ensuring no other system users can access the sensitive material.

## Methods to Generate an Encryption Key

### Production Setup Using the ENCRYPTION_KEY Variable

For production deployments, you must explicitly set the `ENCRYPTION_KEY` environment variable. As documented in [`docs/env/01-variables.md`](https://github.com/tashfeenahmed/freellmapi/blob/main/docs/env/01-variables.md), the server reads this variable at startup and uses it directly for cryptographic operations.

Generate a secure key using Node.js crypto:

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

```

Add the output to your `.env` file:

```bash
ENCRYPTION_KEY=your_generated_64_character_hex_string_here

```

This approach is referenced in the `.env.example` file, which includes a placeholder and the generation command for quick setup.

### Development Mode Auto-Generation

When `ENCRYPTION_KEY` is absent, FreeLLMAPI automatically initializes a key for local development. The function `initializeEncryptionKey()` in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts) performs the following steps:

- Checks for an existing `.encryption-key` file
- If missing, generates a fresh 32-byte key using `crypto.randomBytes(32).toString('hex')`
- Writes the key to `.encryption-key` with `0600` permissions
- Stores a SHA-256 fingerprint in the SQLite `settings` table for integrity verification

This behavior is handled automatically during the [`dev-bootstrap.sh`](https://github.com/tashfeenahmed/freellmapi/blob/main/dev-bootstrap.sh) script execution, which sets up the development environment without manual intervention.

### Manual File Creation

If you prefer to create the `.encryption-key` file manually without relying on the bootstrap process, use this command to ensure proper permissions:

```bash
node -e "require('fs').writeFileSync('.encryption-key', require('crypto').randomBytes(32).toString('hex'), {mode: 0o600})"

```

## Technical Implementation of Key Management

The core encryption logic resides in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts). When the server starts, it calls `initializeEncryptionKey()`, which determines the key source based on environment configuration. If using the file-based approach, the function ensures the key persists across restarts while maintaining strict file system permissions.

For integrity verification, the implementation includes `encryptionKeyFingerprint()`, which calculates a SHA-256 hash of the active key and stores it in the database. This fingerprint allows FreeLLMAPI to detect mismatched keys during backup restoration operations or when migrating data between instances, as detailed in [`docs/env/02-security-and-keys.md`](https://github.com/tashfeenahmed/freellmapi/blob/main/docs/env/02-security-and-keys.md).

## Configuration Examples

**One-liner to generate and append to `.env`:**

```bash
ENCRYPTION_KEY=$(node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))") && printf 'ENCRYPTION_KEY=%s\n' "$ENCRYPTION_KEY" >> .env

```

**Programmatic generation in TypeScript:**

```typescript
import { randomBytes } from 'node:crypto';
import { writeFileSync } from 'node:fs';

const keyHex = randomBytes(32).toString('hex');
writeFileSync('.encryption-key', keyHex, { mode: 0o600 });
console.log('Encryption key written to .encryption-key');

```

**Verify the current key fingerprint:**

```typescript
import { encryptionKeyFingerprint } from './server/src/lib/crypto.js';
console.log('Key fingerprint:', encryptionKeyFingerprint());

```

## Summary

- FreeLLMAPI uses **AES-256-GCM** encryption requiring a **32-byte (64 hex character)** key
- Production deployments **must** set the `ENCRYPTION_KEY` environment variable explicitly
- Development mode automatically generates `.encryption-key` with `0600` permissions via `initializeEncryptionKey()` in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts)
- Key integrity is maintained through SHA-256 fingerprints stored in the SQLite database
- Reference [`docs/env/01-variables.md`](https://github.com/tashfeenahmed/freellmapi/blob/main/docs/env/01-variables.md) for environment configuration and [`docs/env/02-security-and-keys.md`](https://github.com/tashfeenahmed/freellmapi/blob/main/docs/env/02-security-and-keys.md) for security best practices

## Frequently Asked Questions

### What happens if I don't set the ENCRYPTION_KEY environment variable?

If `ENCRYPTION_KEY` is not set, FreeLLMAPI operates in non-production mode and automatically generates a key by calling `initializeEncryptionKey()`. This creates a `.encryption-key` file next to the SQLite database with restrictive `0600` permissions. While convenient for development, this auto-generation is not recommended for production deployments where explicit key management is required.

### How secure is the .encryption-key file?

The `.encryption-key` file is created with Unix permissions `0600`, meaning only the file owner can read or write it. According to the implementation in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts), the server explicitly sets these permissions during the `initializeEncryptionKey()` routine to prevent unauthorized access by other system users. However, you must ensure the underlying file system and server user permissions are properly configured.

### Can I regenerate or rotate the encryption key?

The source code analysis reveals that FreeLLMAPI tracks key identity using `encryptionKeyFingerprint()`, which stores a SHA-256 hash in the SQLite `settings` table to detect mismatched keys during restore operations. While you can manually delete the `.encryption-key` file or change the `ENCRYPTION_KEY` variable to trigger generation of a new key, be aware that changing the encryption key will render existing encrypted provider API keys undecryptable. You would need to re-enter all provider credentials after rotation.

### Where does FreeLLMAPI store the encryption key fingerprint?

The key fingerprint is stored in the SQLite database's `settings` table. The function `encryptionKeyFingerprint()` in [`server/src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/crypto.ts) calculates this SHA-256 hash and persists it during initialization. This allows the system to verify key consistency across server restarts and detect potential configuration errors or tampering attempts.