KMS
KMS is an Elixir key-management toolkit packaged as one OTP application, :kms.
It provides clean primitives and deployment patterns for:
- direct AES-GCM encryption with AAD;
- Phoenix/Ecto field-level encryption;
- embedded KMS storage with SQLite by default;
- optional
KMS.APIHTTP server for remote clients; - principal/session/binding authorization when KMS should enforce decrypt rights;
- local or external root master key (RMK) providers;
- RMK-wrapped P-256 signing-key custody and caller-process digest signing.
Start with:
Quick example
{:ok, _kek} = KMS.create_alias("owner:alice")
{:ok, encrypted} =
KMS.encrypt_alias("secret", "owner:alice", aad: "document:123/body")
{:ok, "secret"} =
KMS.decrypt_alias(encrypted, "owner:alice", aad: "document:123/body")
AAD binds ciphertext to context. In this example, copying the ciphertext to a different document id or field makes decrypt fail.
Choose a mode
| Mode | Use when | Start here |
|---|---|---|
| Crypto-only | App may decrypt at any time; no KMS storage needed. | Crypto-only |
| Embedded KMS | One Elixir/Phoenix app runs KMS in-process. | Embedded KMS |
| Phoenix field encryption | Encrypt Ecto fields with virtual plaintext fields. | Quickstart |
| Remote KMS | App servers call a dedicated KMS authority process. | Remote KMS |
| Multi-user KMS | KMS enforces per-principal permissions. | Multi-user encryption |
| Factor-bound aliases | Recipient secrets must cryptographically protect alias keys; share and revoke access. | Factor-bound aliases |
Persistence
KMS defaults to SQLite:
export KMS_DATA_DIR=/var/lib/kms
mix ecto.migrate
PostgreSQL remains supported:
export KMS_DATABASE_BACKEND=postgres
export KMS_DATABASE_URL=ecto://postgres:postgres@localhost/kms_prod
mix ecto.migrate
HTTP API
The optional HTTP API lives under KMS.API and runs inside the :kms OTP application when enabled.
Non-health routes require a bearer token. See HTTP API and Security stance.
Root master keys
The RMK protects persisted KMS secret material.
Providers:
- local file-backed RMK (
KMS.RMK.Local, default); - StackIT KMS;
- AWS KMS;
- Google Cloud KMS.
See Root master keys.
Security posture
- Treat local KMS calls without
session:as trusted application/admin execution. - Treat the HTTP API as an admin backend API.
- Use TLS or a trusted private network for remote KMS.
- Disable request-body logging and production crash dumps.
- Do not log plaintext, ciphertext payloads, bearer tokens, passwords, factor codes, RMK material, or private keys.
- Embedded signing copies decoded private-key material from sensitive cache into active caller processes; disable production crash dumps.
See Security.
Docs
- Installation
- Configuration
- Elixir API
- HTTP API
- Authorization and bindings
- Operations
- Observability
- Fallback recovery
- Migrations and upgrades
Development validation
Useful commands:
mix format --check-formatted
mix compile --warnings-as-errors
mix test.sqlite
mix test.postgresql