<home>/kms.yaml, at startup. Relative paths anywhere in the file resolve against the --home directory. Validation runs at kms start; a rejected field is named in the error.
For task-shaped setup, see Configure a signing backend; this page is the complete field list.
chains
Declares one chain to sign for. One entry per chain.validators
Declares one outbound connection to a validator node’s privval listener. A chain can have multiple entries, for example a primary and a backup node.keys
Binds one signing key to one or more chains. Each chain must be backed by exactly one key. Thebackend field selects the custodian, and the remaining fields depend on it; fields belonging to other backends are ignored.
Fields shared by every backend:
Consensus signing supports
ed25519, secp256k1eth, and mldsa65 on every backend, and secp256k1 on the AWS KMS backend only. The algorithm name mldsa65 has no underscores; the chain-side key type ml_dsa_65 does.
backend: file
A key read from disk into memory. Development and testing only; the key is held in plaintext.backend: pkcs11
A key on a PKCS#11 token or HSM. Signing happens on-device; the signer uses an existing key and never generates or imports one.backend: awskms
A key held in AWS KMS. Signing happens through the KMS Sign API; credentials resolve through the AWS default credential chain, and no secret material appears in the config.grpc
Optional. When present, the signer also serves the SignerService gRPC API alongside privval. Its usage documentation ships with the interoperability release; the fields are listed here for completeness.
Each
grpc.keys entry:
A
grpc.keys entry with backend: pkcs11 also takes the PKCS#11 fields, with the same rules and the same validation as a privval key. See backend: pkcs11 for module, token_label, slot, key_label, key_id, and the PIN sources.
Constraints checked at startup
- Every
validators[].chain_idand every entry inkeys[].chain_idsmust match a declaredchains[].id. - Each chain must be backed by exactly one key.
- PKCS#11 keys must select the token with exactly one of
token_labelorslot, select the key withkey_labelorkey_id, and supply exactly one PIN source. - A declared chain with no
validatorsentry is not rejected. The signer starts, binds nothing, and signs nothing, with no warning, so check that every chain has a validator entry. - Every chain’s sign-state file must exist and be non-empty. A missing or empty file fails closed with
sign-state file <path> is missing or empty; refusing to start at height 0, so the signer cannot re-sign a height it has no record of. See First start on a new chain.
config: and name the field at fault; errors raised later, when a backend or chain signer is opened, use their own prefixes such as app: or file:.
First start on a new chain
A key that has never signed on a chain has no sign-state file, so the checks above block its first start. Write the height-0 floor with:kms state init writes a floor too, but it loads and validates kms.yaml first, so it only works once the chain is declared and the config is complete. It also defaults --step to 3, which refuses everything at that height and round, where --allow-fresh-state writes step 0. Pass --step 0 to match. See Migrate from TMKMS for more details.
Next steps
- Task-shaped backend setup. See Configure a signing backend.
- First-time setup end to end. See Remote signing tutorial.