Secure Attributes
Sensitive attribute values — passwords, API keys, private keys — are encrypted at rest using AES-256-GCM. Encryption and decryption are transparent: the rest of the system reads and writes these attributes normally and never sees ciphertext.
What gets encrypted
- Auto-detected by name — attributes whose names look sensitive (
password,api_key,private_key, and similar) are encrypted automatically. - Explicitly marked — any attribute set with
{ secure: true }is encrypted regardless of name.
How it works
Encryption is applied through the data layer's hooks, so a value is encrypted on write and decrypted on read without driver or UI code participating. Stored values use a self-describing format:
gem-crypt:<iv>:<authTag>:<ciphertext>
The gem-crypt: prefix lets the system recognize an already-encrypted value and avoid double-encrypting it.
The encryption key
The key lives in a file named .encryption_key at the install root, generated automatically on first boot (a JSON document holding the attribute-encryption key and a separate backup key). It is not stored in the database and is git-ignored.
:::danger Losing .encryption_key is unrecoverable
Every encrypted attribute depends on this file. If it's lost, those values cannot be decrypted and must be re-entered by hand. Back it up securely and separately from the database, and carry it along when migrating to new hardware. See Configuration.
:::
GEM provides secure download/upload of the keys from the admin interface for backup and migration.
secure vs readonly
These flags solve different problems and shouldn't be conflated:
secure— the value is encrypted; it is excluded from some export/migration flows because the ciphertext is meaningless without the key.readonly— the value is configuration locked from UI editing; it is included in exports and migrations. See Attributes & the Registry.