Skip to main content
A remote signing setup is a set of trust decisions: where the signer runs, how the connection is secured, and which keys are protected to what degree. This page states the recommended defaults and the reasoning, so a setup can be defended in a security review rather than inherited by accident.

Place the signer in its own trust domain

Run the signer on a separate host, in a separate network segment, with network ACLs between it and the validator. The validator node is the exposed machine: it peers with the public network and sees frequent maintenance. The signing host should do exactly one job, accept no inbound connections, and be reachable by as few people and systems as possible. The signer dials out to the validator, so this layout costs nothing: the signing host needs no open ports at all. The validator’s privval listener is the only listening side; bind it to a private interface and firewall it so only the signing host can reach it. The alternative is running the signer on the validator host itself, with the key in a cloud KMS. The key still never touches disk, but the signer process and its credentials live on the exposed machine.

Prefer the Noise transport

Two transports secure the privval connection; the address scheme in kms.yaml selects between them. The default tcp:// uses CometBFT’s SecretConnection: the signer authenticates itself to the validator with its identity key. The validator’s listener uses an ephemeral key, so the signer cannot verify it is talking to the right validator. The noise:// transport closes that gap with mutual pinning. Each side asserts a stable peer ID: the signer’s derives from its identity key, the validator’s from its node key. Each side refuses a connection from any unexpected peer. Exchange the two peer IDs out of band and pin them:
Use noise:// for any deployment where the signer and validator cross a network you do not fully control.

Protect keys according to their power

The consensus key is the asset; keep it in the HSM or cloud KMS and never in a file on production hosts. The signer’s identity key (identity.json) only authenticates the connection: it signs no consensus messages, and losing it means re-pinning a new peer ID, not a compromise. The two keys do not need the same protection level. Treating the identity key as low value keeps operational friction down.

Run exactly one signer per validator

Double-sign protection lives in the signer’s per-chain state file, which records the highest height, round, and step ever signed. That protection assumes one writer. Two signer instances holding the same consensus key with separate or missing state files can each sign the same height, which is a double sign.
Never run two signer instances against the same validator key. High availability by running a second signer is not redundancy; it is a double-sign generator. If availability matters more than custody, that is Horcrux’s problem to solve, not a second signer’s.

Keep the gRPC listener off consensus paths

The optional gRPC SignerService performs no caller authentication or authorization: any client that reaches the listener can use every configured key. If the service is enabled, front it with TLS, restrict it with network policy, and give it only the keys it exists to serve. Consensus keys belong to the privval side only; the gRPC service is for IBC signing and is documented with the interoperability release.

Next steps