SSHKey
Forward a local private key into workstations as an ambient ssh-agent, so processes on the workstation can authenticate outbound.
An SSHKey makes one of your local private keys available inside selected
workstations, as a forwarded ssh-agent, never as a file on the workstation. It is how a
git clone from a private repo, a service, or an interactive shell running on the
workstation authenticates outbound using a key that stays on your machine.
apiVersion: workstations.ringleader.dev/v1
kind: SSHKeyNot the same as SSH access to the workstation
How it works
An SSHKey names a local private key path and an optional label selector. The
daemon forwards every matching key into the workstation as an in-process ssh-agent
keyring, exposed over its persistent connection at a canonical socket on the
workstation and wired into an ambient SSH_AUTH_SOCK. That variable is set by sshd
itself, before it execs your shell, so it reaches every SSH session whatever login
shell the workstation runs: an interactive rl shell, a non-interactive remote command,
a script, an on-box AI agent, and scp/rsync alike all see the same forwarded keys.
That last step is
best-effort: it needs the workstation to grant Ringleader’s delivery sudo rule and an
sshd whose configuration Includes /etc/ssh/sshd_config.d/, both of which hold on
every image Ringleader ships.
On a custom image, rl troubleshoot my-box reports it: an ambient agent line in the
controller view names the precondition that stopped the delivery. It is written only
when something is missing, so a workstation that got both files shows no such line. An
ssh-agent-env probe under system probes confirms the working case from inside the same
non-login session the failure appears in. See
rl shell for the full check.
The private keys live only in the daemon’s memory, or, for a key with
source: agent, in your own ssh-agent. They are never written to the workstation’s disk,
and the agent socket is live only while your daemon holds the connection.
Selection uses Kubernetes-style label matching: an SSHKey attaches to a
workstation when its selector.matchLabels are a subset of the workstation’s
labels, and an empty or absent selector matches every workstation (an
unconditional key).
Because keys are device-local, an SSHKey is a device-local kind: it never mirrors or routes to another origin, and it only ever forwards from the device that declares it.
Example
Forward your GitHub key into every tier: dev workstation:
apiVersion: workstations.ringleader.dev/v1
kind: SSHKey
metadata:
name: github
namespace: dev
spec:
path: ~/.ssh/id_ed25519
selector:
matchLabels:
tier: devAn unconditional key (forwarded into every workstation) simply omits the selector:
spec:
path: ~/.ssh/id_ed25519Keeping the key in your ssh-agent
By default the daemon reads the private key file and holds it itself, so the file must be
readable without a passphrase. To use a key protected by a passphrase, or one on a hardware
token, set source: agent. The key then stays in the ssh-agent on your machine, and the
daemon passes each signing request from the workstation to it.
With source: agent, path still names the private key. The daemon reads <path>.pub to
know which agent key to use. Keep <path>.pub next to the private key. The daemon skips
an agent key whose <path>.pub it cannot read.
spec:
path: ~/.ssh/id_ed25519_sk
source: agentOr from the command line:
rl sshkey create github --path ~/.ssh/id_ed25519_sk --source agentThe key has to be loaded in your agent (ssh-add) for a workstation to use it.
The daemon reaches your agent through the SSH_AUTH_SOCK it started with. A daemon
started without one cannot use a source: agent key. When that leaves a workstation with
no key, rl troubleshoot says so. Restart the daemon from a shell that has an agent, or
use source: file.
Spec fields
| Field | Type | Description |
|---|---|---|
path | string | Required. Path to the local private key on this device. A leading ~ expands to your home directory. With source: agent, the daemon reads <path>.pub instead. |
source | string | file (the default): the daemon reads the key file and holds the key. agent: the key stays in your ssh-agent, which signs each request. |
selector.matchLabels | map | Which workstations receive the forwarded key. Empty/absent matches every workstation. |
enabled | bool | Master on/off switch (default true; an absent field reads as enabled). When false, the key is not forwarded into any workstation, even one its selector matches. Selection still records the match, but forwarding is paused. |
Creating a key from the command line
rl sshkey create builds an SSHKey from flags and applies it:
rl sshkey create github --path ~/.ssh/id_ed25519
rl sshkey create github --path ~/.ssh/id_ed25519 --dry-run -o yaml # print, don't applyWith --source agent, it prints a note if it cannot read <path>.pub.
| Flag | Description |
|---|---|
--path <path> | Required. Path to the private key. With --source agent, the daemon reads <path>.pub. |
--source <source> | file (default) or agent. |
--dry-run | Print the generated object instead of applying it. |
-o, --output <format> | With --dry-run, output format (yaml). |
-n, --namespace <ns> | Namespace. |
--as <subject> | Impersonate a subject. |
--home <dir> | Data directory. |
Enabling and disabling a key
Flip the enabled toggle from the command line without editing the manifest, by
name, or across every matching key with a label selector:
rl sshkey enable github
rl sshkey disable github
rl sshkey disable -l tier=dev # every matching key| Flag | Description |
|---|---|
-l, --selector <selector> | Label selector (key=value[,key!=value,key in (a,b),key,!key]) instead of a name. |
-n, --namespace <ns> | Namespace. |
--as <subject> | Impersonate a subject. |
--home <dir> | Data directory. |
Status
None. An SSHKey has no status: it is a device-local selection rule the daemon
acts on directly.