A security-focused fork of MinIO KES, the key encryption server that sits between MinIO and a key store and manages the keys MinIO uses for server-side encryption. MinIO archived KES in June 2025.
This fork continues from kypello-io/kes, a community fork that carries all of
upstream minio/kes plus its own Go, AWS SDK and lint updates. It is based on kypello-io/kes at commit
d935da4.
The fork is deliberately narrow. It supports one deployment shape, KES in front of HashiCorp Vault with mutual TLS on every connection, and removes everything else. If you need another key store or a less strict mode, use upstream KES or kypello-io/kes instead.
This project is not affiliated with or endorsed by MinIO, Inc.
- Vault is the only key store, over
https://only, with the K/V v2 engine and AppRole login. The AWS, Azure, GCP, Fortanix, Gemalto, Entrust and filesystem stores, K/V v1 and Kubernetes login are removed. - TLS 1.3 everywhere. The server, the Vault client and the CLI refuse anything older.
- Every connection needs a client certificate. The per-route
skip_authoption and the TLS-proxy option are removed. - Vault trust comes from the config file only. KES refuses to start if any
VAULT_*variable is set, never uses an HTTP proxy for Vault, and fails on an unreadable CA file. - A configured CA replaces the system roots rather than adding to them.
- Strict configuration. Unknown or removed keys fail startup.
- No insecure or demo modes.
kes server --dev,kes update,kes migrate, the CLI's-k/--insecureand--coloroptions are gone. The CLI verifies the server againstMINIO_KES_CA_FILEwhen it is set. - Current dependencies. Every module is kept on its newest stable release once that release is at least 48 hours old.
These changes break compatibility with upstream configurations that use any removed option.
KES needs Go 1.27 or later. The Go module path is still github.com/minio/kes, so
go install github.com/minio/kes/... fetches the archived upstream, not this fork. Build from a clone instead:
CGO_ENABLED=0 go build -trimpath -o kes ./cmd/kes
./kes --versionThe test suite runs offline:
go test ./...The Dockerfile runs gofmt, go vet and the tests, then builds a static binary into a scratch image. Its
default builder image is a private mirror, so pass a Go image yourself, ideally pinned by digest:
docker build \
--build-arg GO_IMAGE=golang:1.27.1-alpine3.24 \
--build-arg SOURCE_COMMIT="$(git rev-parse HEAD)" \
-t kes .The image contains only /kes and the licence. It runs as 65532:65532, listens on port 7373 and starts
kes server --config /etc/kes/config.yaml. It has no system CA roots: KES trusts only the CA files named in
its configuration, so mount them alongside the config, certificates and keys.
server-config.yaml documents every option. A minimal configuration for MinIO looks like
this:
address: 0.0.0.0:7373
tls:
cert: /etc/kes/server.crt
key: /etc/kes/server.key
admin:
identity: disabled # no admin identity; access is granted only through policies
policy:
minio:
allow:
- /v1/key/create/*
- /v1/key/generate/*
- /v1/key/decrypt/*
- /v1/key/bulk/decrypt/*
- /v1/key/list/*
- /v1/status
- /v1/metrics
- /v1/log/audit
- /v1/log/error
identities:
- ${MINIO_IDENTITY} # environment variables are expanded
keystore:
vault:
endpoint: https://vault.example.invalid:8200
engine: kv
version: v2
prefix: kes
transit:
engine: transit
key: kes
approle:
id: ${KES_APPROLE_ID}
secret: ${KES_APPROLE_SECRET}
tls:
ca: /etc/kes/vault-ca.crtPoints that differ from upstream:
- Clients are identified by the hash of their certificate's public key (
kes identity of <cert>). Withtls.authunset oroff, any client certificate completes the handshake and policies decide what it may do. Withon, the certificate must also chain totls.ca. A client without a certificate is always rejected. keystore.vault.versionmust bev2andendpointmust behttps://.- Do not name configuration variables
VAULT_*in the server's own environment: KES refuses to start if anyVAULT_*variable is set. Use other names, as above.
The kes client commands (key, policy, identity, status, log, metric) read these variables:
| Variable | Meaning |
|---|---|
MINIO_KES_SERVER |
Server endpoint(s), comma-separated. Defaults to 127.0.0.1:7373. |
MINIO_KES_CERT_FILE, MINIO_KES_KEY_FILE |
Client certificate and private key. |
MINIO_KES_API_KEY |
An API key, as an alternative to a certificate and key. |
MINIO_KES_CA_FILE |
CA certificates used to verify the server. If unset, the system roots are used. |
There is no option to skip server certificate verification.
Report vulnerabilities privately as described in SECURITY.md. Please do not open public issues for security problems.
KES is licensed under the GNU Affero General Public License v3.0; see LICENSE. This is a modified
version of MinIO KES: kypello-io/kes changed it until March 2026, and this fork has changed it since October
2026. The commit history records each change. Copyright in the upstream code remains with MinIO, Inc. and its
contributors, and the changes in this fork are released under the same licence.