# Installation

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](quickstart.md).

## Dependency

Add the published package dependency:

```elixir
defp deps do
  [
    {:kms, "~> 0.1.0"}
  ]
end
```

When 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](use_cases/crypto_only.md): no OTP app, no KMS DB.
- [Embedded KMS](use_cases/embedded.md): start `:kms` inside your app.
- [Remote KMS](use_cases/remote.md): run `:kms` with the optional `KMS.API` server in a dedicated authority process.

## Embedded KMS application setup

Start KMS with your app:

```elixir
def application do
  [
    mod: {MyApp.Application, []},
    extra_applications: [:logger, :runtime_tools, :kms]
  ]
end
```

Configure local client and KMS repo:

```elixir
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.Local
```

Configure local RMK key path:

```elixir
config :kms, KMS.RMK.Local,
  key_path: Path.expand("../priv/kms_rmk_#{config_env()}.key", __DIR__)
```

Run migrations:

```sh
mix ecto.migrate
```

## SQLite default

SQLite is default persistence.

Production env:

```sh
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:

```text
$KMS_DATA_DIR/kms.sqlite3
```

You can set an exact file path:

```sh
export KMS_DATABASE_PATH=/var/lib/kms/kms.sqlite3
```

See [Database configuration](database.md).

## PostgreSQL option

```sh
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:

```sh
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:

```elixir
config :kms, :api,
  server: true,
  port: 4004,
  scheme: :http,
  api_token: System.fetch_env!("KMS_API_TOKEN")
```

On client apps:

```elixir
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](use_cases/remote.md).

## Production checklist

- Set `KMS_SESSION_HASH_KEY` to a high-entropy secret.
- Set explicit RMK configuration.
- Disable crash dumps with `ERL_CRASH_DUMP_BYTES=0` or `ERL_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/ready` before serving traffic.

See [Security](security.md) and [Operations](operations.md).
