Database Encryption
Libre WebUI includes an application-level encryption service for sensitive values before they are written to storage.
Encryption Method
The backend uses AES-256-GCM through Node.js crypto. The encryption key must be 32 bytes, represented as a 64-character hex string:
ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Generate a key:
openssl rand -hex 32
Key Storage
Libre WebUI loads the key in this order:
ENCRYPTION_KEYfrom the environment.- A persisted
.encryption_keyfile underDATA_DIRorbackend/datafor Docker/data-dir installs. - A newly generated key.
If no key is found, the backend generates one and stores it:
- In persistent data storage when
DATA_DIRis set or Docker mode is enabled. - In
backend/.envfor regular development.
Important Key Rules
- Back up
ENCRYPTION_KEYwith the database. - Do not rotate the key unless you have a migration plan for encrypted values.
- Losing the key means encrypted values cannot be recovered.
- Changing the key without re-encrypting data will make existing encrypted values unreadable.
What This Protects
Encryption is applied by code paths that use the encryption service or encrypted storage helpers. It is designed for sensitive application values such as credentials and private user data handled by those helpers.
It is not full-disk encryption, SQLite page encryption, or end-to-end encryption between users and the browser. Use disk encryption and HTTPS for those layers.
Docker and Kubernetes
Set a stable key explicitly for production:
ENCRYPTION_KEY=replace-with-64-hex-characters
DATA_DIR=/data
Mount DATA_DIR on persistent storage. In Kubernetes, store the key in a Secret and mount data on a PersistentVolume.
Troubleshooting
Invalid key length
The key must be exactly 64 hex characters. Generate a new one with:
openssl rand -hex 32
Data cannot be decrypted after redeploy
Confirm the same ENCRYPTION_KEY is used and the same DATA_DIR volume is mounted.
Development generated a new key
Restart after the backend writes the generated key to backend/.env, or set ENCRYPTION_KEY manually.