# 07 · SSH provider smoke

Tests the provider abstraction directly: run a script on a remote host
through Lakeshore's SSH launcher, without involving a daemon.

## Exercises

- `lakeshore ssh upload` (or `providers add --launcher SSH`) — provider
  config write.
- `lakeshore providers test` — the provider invocation path, SSH
  transport, and remote command execution. SSH providers dispatch
  `direct` by default, so the CLI drives the connection from your
  machine.
- Secret resolution at launch time, when the key was uploaded with
  `--with-key`.

## Requires

- An SSH-reachable host: `ssh <alias>` already works from your laptop,
  and the alias is a `Host` entry in `~/.ssh/config`.
- Python 3 on that host — the built-in smoke script is a Python file.

## Run

Register the host as a provider. The ergonomic path reads
`~/.ssh/config` for you:

```bash
lakeshore ssh discover                       # confirm the alias is parsed
lakeshore ssh upload my-box --with-key       # provider name defaults to the alias
```

`--with-key` uploads the parsed `IdentityFile` as an `ssh_key` secret
(named `ssh-<alias>` unless you pass `--key-secret`) and references it
from the provider. Without it, the provider records the local pem path
instead and only works from this machine.

By hand, if the host isn't in `~/.ssh/config`:

```bash
lakeshore secrets add my-key --kind ssh_key --from-file ~/.ssh/id_ed25519

lakeshore providers add my-box \
  --launcher SSH \
  --kwarg ip=<hostname-or-ip> \
  --kwarg username=<username> \
  --kwarg port=22 \
  --kwarg 'ssh_key.$secret=my-key'
```

Confirm it landed, then smoke-test it:

```bash
lakeshore providers show my-box
lakeshore providers test my-box
```

## Expected output

`providers test` with no `--script` runs the bundled stdlib-only
`hello.py`, so the remote stdout looks like:

```text
hostname: my-box
python: 3.12.3
platform: Linux-6.8.0-x86_64-with-glibc2.39
gpu: (torch not installed)
ok
```

The command exits non-zero on failure. Swap in your own script with
`--script`, and raise `--timeout` (default 600 seconds) for anything
slow.

## If it fails

| Symptom | Likely cause |
| ------- | ------------ |
| `ssh: connect to host … port 22: Connection refused` | Wrong host or port. Run `ssh -v <alias>` first to verify. |
| `Permission denied (publickey)` | Wrong key secret, or the key isn't authorized on the host. |
| `no host '<alias>' in ~/.ssh/config` | `ssh upload` / `ssh probe` only know aliases from that file — use `providers add` by hand instead. |
| `python3: command not found` | The smoke payload is Python. Install Python 3 on the host or pass a `--script` that isn't Python-dependent. |
| Hangs with no output | The host accepted the SSH but the command stalled — often a prompt (sudo, host-key confirmation). `lakeshore ssh probe <alias>` isolates the connection step. |

## Status

Manual.

## Next

→ [08 · Bootstrap a daemon on a remote host](/admin/happy-paths/08-bootstrap-daemon-remote.md)
