This guide covers adding KMS to an Elixir/Phoenix application or running KMS from this repository.
For a copy/paste Phoenix field-encryption flow, start with Quickstart.
Dependency
Add the published package dependency:
defp deps do
[
{:kms, "~> 0.1.0"}
]
endWhen working from this repository, the example application instead uses {:kms, path: "../.."}.
Remote-only clients still use the KMS package so the KMS facade and KMS.Client.Remote are available.
Choose a deployment mode
- Crypto-only: no OTP app, no KMS DB.
- Embedded KMS: start
:kmsinside your app. - Remote KMS: run
:kmswith the optionalKMS.APIserver in a dedicated authority process.
Embedded KMS application setup
Start KMS with your app:
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools, :kms]
]
endConfigure local client and KMS repo:
config :my_app,
ecto_repos: [MyApp.Repo, KMS.Repo.SQLite]
config :kms, ecto_repos: [KMS.Repo.SQLite]
config :kms, KMS.Repo, repo: KMS.Repo.SQLite
config :kms, :client, KMS.Client.Local
config :kms, :rmk_provider, KMS.RMK.LocalConfigure local RMK key path:
config :kms, KMS.RMK.Local,
key_path: Path.expand("../priv/kms_rmk_#{config_env()}.key", __DIR__)Run migrations:
mix ecto.migrate
SQLite default
SQLite is default persistence.
Production env:
export KMS_DATABASE_BACKEND=sqlite # optional
export KMS_DATA_DIR=/var/lib/kms
export KMS_RMK_LOCAL_KEY_PATH=/var/lib/kms/rmk.key
export KMS_SESSION_HASH_KEY=<high-entropy-secret>
export ERL_CRASH_DUMP_BYTES=0
mix ecto.migrate
Database path defaults to:
$KMS_DATA_DIR/kms.sqlite3You can set an exact file path:
export KMS_DATABASE_PATH=/var/lib/kms/kms.sqlite3
PostgreSQL option
export KMS_DATABASE_BACKEND=postgres
export KMS_DATABASE_URL=ecto://postgres:postgres@localhost/kms_prod
mix ecto.create
mix ecto.migrate
Or use discrete variables:
export KMS_DATABASE_HOST=localhost
export KMS_DATABASE_NAME=kms_prod
export KMS_DATABASE_USER=postgres
export KMS_DATABASE_PASSWORD=postgres
Remote KMS service setup
On the KMS authority service:
config :kms, :api,
server: true,
port: 4004,
scheme: :http,
api_token: System.fetch_env!("KMS_API_TOKEN")On client apps:
config :kms, :client, KMS.Client.Remote
config :kms, KMS.Client.Remote,
base_url: "https://kms.internal.example.com",
api_token: System.fetch_env!("KMS_REMOTE_API_TOKEN")See Remote KMS service.
Production checklist
- Set
KMS_SESSION_HASH_KEYto a high-entropy secret. - Set explicit RMK configuration.
- Disable crash dumps with
ERL_CRASH_DUMP_BYTES=0orERL_CRASH_DUMP_SECONDS=0. - Protect SQLite DB/WAL/SHM files or PostgreSQL credentials.
- Protect RMK key files or cloud RMK credentials.
- Disable request-body logging for KMS routes.
- Use TLS or trusted private networking for remote KMS.
- Run
/health/readybefore serving traffic.
See Security and Operations.