Skip to main content

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.