Saphan StudioDocs
Security

Machines: enrollment and authentication

A machine cannot enrol itself; it is admitted by the owner, and every connection to it is authenticated by a pinned host key.

There is no registration endpoint

A machine cannot enrol itself, and there is no registration token that would let anything holding it become a runner.

  1. On the machine, saphan machine csr generates a P-256 key pair locally and produces a certificate signing request. The private key never leaves the machine.
  2. The owner admits it with saphan machine admit, which issues a short-lived certificate from the intermediate (24 hours by default). Admission is an owner act: the owner types back a one-time code shown on their terminal. A one-command local path, --mint-device-key, does both steps on the machine being admitted.

Admission checks, each refusing by name:

checkwhat it proves
the request's signature validates (on the --csr path)the requester holds the private key
the certificate is inside its validity windowan expired certificate is reported as expired
the certificate's Common Name equals the machine identifier exactlythe cryptographic identity is bound to the name you see
transport, SSH host and SSH key are well formedthe record can be connected to
a live SSH login with the recorded key succeedsthe machine is reachable as recorded. --force-unverified skips this and marks the record

Re-running an identical admission reports "unchanged". A retired machine can be admitted again as a new record.

On success a record signed by the root — or by the identity-signing key the root granted at the ceremony — is appended to the signed identity log. Certificates are renewed with saphan machine renew (using machine csr --reuse-key on the machine); a superseded certificate stays valid for a grace period, 24 hours by default (trust.rotation_grace).

What is recorded

Machine identifier, host, transport (local or SSH), key suite, execution slot count, admitting actor, admission time and connection parameters — with any key referenced by path, never by value. Identity and transport are separate: how a machine is reached can change without re-establishing who it is.

Transport and host authentication

Over SSH, the control machine always opens the connection; runners do not dial it or poll it. If you enable the gateway's mutual-TLS listener (gateway.mtls_listen), machines use their certificates to fetch from it and to upload evidence. The product opens no network-reachable port on a runner; at most, a run may carry a forwarded port bound to the runner's loopback address for the length of the run.

settingvaluewhy
Clientthe system SSH binary, not an embedded libraryavoids a known class of host-verification defects in language-level SSH clients
StrictHostKeyCheckingyes, unconditionally, including for machines that accept rotationthe pinned host key authenticates every connection
BatchModeyesno interactive prompt can be what lets a connection through
ConnectTimeout15 seconds by default; configurable from 1 second to 1 hour, installation-wide or per machinebounded failure
SendEnvnegated for all variablesno environment is forwarded to a runner
Client environmentonly PATH and HOME on the run paththe control machine's environment is not inherited by the agent's connection
Configuration filegenerated from the machine registry, regenerableyour own SSH configuration is never modified

Host key rotation is handled by policy, not by hand. Some machines legitimately regenerate host keys — some on every boot. The alternative to a policy is a person editing a trust file whenever it happens, which is exactly the habit that makes a genuine key substitution invisible.

Each machine carries a policy from a closed set, validated when configuration loads:

tiereffect
refuse (default)a changed host key aborts the connection
accept_rotationthe pin may be updated automatically before an agent run; the rotation is printed in the run's output. It does not disable strict checking.

First contact with an unknown host is never treated as a rotation. At admission or renewal, a host's key is taken from the installation's own known-hosts file, then from yours, and only if neither has it from a live scan of the host. ⚠ That scan applies to every SSH machine in the registry that has no pin — verify each host's key yourself before you admit.

The topology trade, stated plainly

In your favour: a compromised runner holds no credential to the control machine over SSH, cannot reach its peers through it, and has no identity assertion to forge.

Against you: the control machine holds the means to reach every machine, which makes it the asset to protect — and each runner must be reachable from it. Documented limits states what a compromised control machine can and cannot currently be prevented from doing.

On this page