SSH Provider
[ dev ] — you can register an SSH provider and drive it from the CLI, but
no server-side launch route accepts one, so a queue cannot
grow workers on it. See Providers for what the marker
means.
--launcher SSH means "connect to a host that is already running."
Nothing is provisioned. The default dispatch is direct: the CLI opens
an SSH session per call and runs the script. Use it for lab boxes, dev
machines, and any server you keep around by hand.
| Phase | What happens |
|---|---|
| Provision | Nothing. The host is expected to be up and reachable. |
| Launch | An ssh session runs the script. |
| Default dispatch | direct |
SSH providers are the one launcher the CLI drives itself — the control
plane's /providers/:name/launch routes support only EC2, GCE, and
Kube, and answer 422 for an SSH provider. lakeshore providers test
and lakeshore providers instances both shell out to the local ssh
binary.
Kwargs
These are the keys the CLI's SSH paths actually read:
| Field | Type | Default | Meaning |
|---|---|---|---|
ip (or host) | string | — | Required. Host IP or DNS name. |
username (or user) | string | ubuntu | SSH user. |
port | int | 22 | SSH port. |
pem | string | — | Path to a private key on the local machine. ~ is expanded. |
lakeshore ssh upload writes a few more keys that survive on the row and
are handed to whatever consumes them later: proxy_jump,
proxy_command, ssh_options (a bag of leftover ssh_config
directives), and _meta.sshFingerprint.
Kwargs are an open bag, so any other key you set round-trips untouched — but only the four above change how the CLI dials the host today.
lakeshore ssh upload --with-key stores the private key as an ssh_key
Secret and writes ssh_key: { "$secret": "<name>" } into the kwargs. The
CLI's own ssh invocation reads only pem — a local file path — so a
provider whose key lives in a Secret has no key for providers test to
pass to ssh -i. Keep a local pem path as well if you want the direct
path to work.
RunConfig fields
None. An SSH host is fixed, so there is no per-machine choice to make at call time and a mode pointing at an SSH provider adds no launcher-shaped fields.
Hardware on an SSH box is not declarative either. A daemon on the host detects CPU / GPU / kernel / distro at registration and advertises them as capabilities and tags; match on those from a mode if you want to target specific boxes in a pool.
Example
CLI tab: --field values that start with [, {, or " are parsed as JSON;
true / false / null and anything number-shaped are converted;
everything else is a verbatim string. Dotted keys nest into objects, so
build lists with JSON rather than an index.
.dreamrc tab: The same shape in a local .dreamrc:
lakeshore secrets add my-dev-key --kind ssh_key --from-file ~/.ssh/id_ed25519
lakeshore providers add my-dev-box --launcher SSH \
--kwarg ip=192.168.1.42 \
--kwarg username=gyang \
--kwarg pem=~/.ssh/id_ed25519
lakeshore modes add dev \
--field provider=my-dev-box \
--field runner=process \
--field tags='["dev"]'providers:
my-dev-box: !providers.SSH
ip: 192.168.1.42
username: gyang
pem: ~/.ssh/id_ed25519
modes:
dev:
provider: my-dev-box
runner: process
tags: [dev]Smoke test
providers test accepts --timeout <seconds> (default 600) and
--dreamrc <path>. providers instances pings the host with a fast
ssh … echo ok and reports running on success, unknown otherwise;
its --timeout defaults to 10 and is clamped to at most 5 seconds for
the ping itself.
If a test hangs, take Lakeshore out of the picture first:
Enroll a host
Host enrollment and daemon bootstrap documentation now lives under Hosts:
- Enroll a host — planned names, SSH transport, JSON configuration, and readiness.
Importing from ~/.ssh/config
You probably already have the hosts. lakeshore ssh discover reads
~/.ssh/config and shows which aliases exist locally and which are
already Providers; lakeshore ssh upload registers the ones you pick.
ssh discover
Rows print ALIAS, TARGET, KEY, TAGS. Two tags appear in the
TAGS column:
| Tag | Meaning |
|---|---|
#stripped | The entry carries local-only directives that will be dropped on upload. |
#exists | The alias is already a Provider on the control plane. |
A footer explains whichever tags actually appeared. Any bad --filter
value exits 2.
Entries that resolve to the same target collapse into one row. The
dedup fingerprint is a short hash of (host, user, port, expanded key path, ProxyJump, ProxyCommand) — so two aliases differing only in
comment or RemoteCommand are one entry.
ssh upload
--all wins and never prompts (CI-friendly). Otherwise --interactive
or a missing alias opens a checkbox picker; Space toggles, Enter
confirms. Overrides for a single upload: --name (provider name,
defaults to the alias), --user, --host, --port, --pem, and
--dispatch (silently ignored unless it is exactly direct or
daemon).
--with-key reads the IdentityFile and uploads its bytes as an
ssh_key Secret named ssh-<alias> (override with
--key-secret <name>), then references it from the provider. The
default records the local path instead and leaves the key on disk —
uploading a private key crosses a real trust boundary, so it is opt-in.
Stripped directives
These exist for the local user's interactive convenience and mean nothing to a different machine dialing the same host, so they are dropped before the kwargs reach the server:
It is a denylist: anything not on it survives — ProxyJump,
ProxyCommand, hostname / port / user / IdentityFile, and any other
option, which lands in the ssh_options bag. Over-sending beats silently
dropping something the server needed.
Probing and status
probe attempts a connection and records the outcome in a local cache
(~/.config/dreamlake/ssh-status.json unless DREAMLAKE_STATE_DIR says
otherwise); status prints the last few results per alias.