Packages

Key management service with embedded OTP runtime, optional HTTP API, SQLite/PostgreSQL storage, and external RMK providers

Current section

Files

Jump to
kms docs rmk local.md
Raw

docs/rmk/local.md

# Local RMK provider

`KMS.RMK.Local` is the default RMK provider. It encrypts RMK-protected KMS secret material with a local file-backed key.

Use it when KMS is the only key authority and host-level controls are enough for your risk model.

## Configuration

```elixir
config :kms, :rmk_provider, KMS.RMK.Local

config :kms, KMS.RMK.Local,
  key_path: System.fetch_env!("KMS_RMK_LOCAL_KEY_PATH")
```

Environment:

```sh
KMS_RMK_LOCAL_KEY_PATH=/var/lib/kms/rmk.key
```

Development and test may auto-create the key file with `0600` permissions.

Production requires an explicit existing, non-empty key file. Production startup fails when the configured file is missing, unreadable, or empty.

## When to use

Good fit:

- local development and tests;
- single-node or simple deployments;
- deployments where KMS host compromise is already considered total compromise;
- deployments where DB-only compromise is the main risk;
- operators can protect and back up one local secret file.

Poor fit:

- DB compromise cannot be tolerated without a separate key service;
- KMS host and database are managed by different trust domains;
- you need HSM-backed key custody, cloud IAM, or provider audit logs;
- you want separation between database operators and key-custody operators.

## Security notes

The local RMK key file is root key material. If an attacker gets both the KMS database and this key file, RMK-protected KMS material can be decrypted.

Protect the key file with:

- strict file permissions (`0600`);
- host disk encryption where appropriate;
- restricted service user access;
- backups separate from database backups;
- restore drills.

Do not place the key path inside the repo, container image, or database backup volume for production.

## Readiness

`KMS.RMK.ensure_ready/1` reads and validates the key:

```elixir
:ok = KMS.RMK.ensure_ready()
```

Provider-specific validation:

```elixir
:ok = KMS.RMK.Local.validate_key_file!()
```

## Caching

Local RMK calls are cheap. Caching still avoids repeated AES-GCM decrypt work, but the main cache concern is memory exposure.

Default:

```elixir
config :kms, :rmk_cache_ttl_ms, :timer.minutes(5)
```

Disable per call when needed:

```elixir
KMS.decrypt_alias(encrypted, "alias", rmk_cache_ttl_ms: 0)
```