Skip to main content
The signer reads one file, <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. The backend 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.
The gRPC server performs no caller authentication or authorization. Any client that can reach the listener can use every configured key. Restrict access with TLS and network controls.

Constraints checked at startup

  • Every validators[].chain_id and every entry in keys[].chain_ids must match a declared chains[].id.
  • Each chain must be backed by exactly one key.
  • PKCS#11 keys must select the token with exactly one of token_label or slot, select the key with key_label or key_id, and supply exactly one PIN source.
  • A declared chain with no validators entry 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.
This list is not exhaustive. Config-level rejections are prefixed 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.
Pass --allow-fresh-state only for a chain the key has genuinely never signed on. It will not overwrite an existing floor, but a service definition that carries it permanently removes the protection: a deleted or truncated state file resets the double-sign floor to zero instead of stopping the signer.

Next steps