ssh install needs rework #10

Open
opened 2026-09-08 04:49:25 +02:00 by sneak · 3 comments
Owner

ssh install can't expect to run code on the host. it needs to download the authorized keys file, alter it, and re-upload it. (to a sidecar file alongside then an atomic rename!)

ssh install can't expect to run code on the host. it needs to download the authorized keys file, alter it, and re-upload it. (to a sidecar file alongside then an atomic rename!)
clawbot was assigned by sneak 2026-09-08 04:49:25 +02:00
Collaborator

Implementer's brief.

keyfunc ssh install runs no command on the host. It uses the system sftp client (the user's normal ssh setup applies, as for ssh to) in batch mode:

  1. Read: -get .ssh/authorized_keys into a private temporary directory; a missing file reads as empty.
  2. Alter locally: if the pub line is already present as an identical line, print already present and stop, connecting no further; otherwise append it, adding a newline first if the file lacks one.
  3. Write, in one session: -mkdir .ssh, chmod 700 .ssh, put the new content to .ssh/authorized_keys.keyfunc-<random>, chmod 600 on it, then rename it over .ssh/authorized_keys, which is the atomic step (the client uses the server's posix-rename extension when it has one). Print added.

If any step fails the tool prints sftp's error, names the sidecar file if it was uploaded, deletes nothing, and exits 1. Anything after -- is passed to sftp unchanged (so -P is the port). The command connects twice when a line is added; the README says so.

Tests: the merge step (absent, present, missing trailing newline, empty file) and the batch commands sent, using a fake sftp on PATH that records its batch and serves get/put from local files. README.md's ssh install section is rewritten to match. Branch off next, PR base next.

Model: fable-5-1

Implementer's brief. `keyfunc ssh install` runs no command on the host. It uses the system `sftp` client (the user's normal ssh setup applies, as for `ssh to`) in batch mode: 1. Read: `-get .ssh/authorized_keys` into a private temporary directory; a missing file reads as empty. 2. Alter locally: if the `pub` line is already present as an identical line, print `already present` and stop, connecting no further; otherwise append it, adding a newline first if the file lacks one. 3. Write, in one session: `-mkdir .ssh`, `chmod 700 .ssh`, `put` the new content to `.ssh/authorized_keys.keyfunc-<random>`, `chmod 600` on it, then `rename` it over `.ssh/authorized_keys`, which is the atomic step (the client uses the server's posix-rename extension when it has one). Print `added`. If any step fails the tool prints `sftp`'s error, names the sidecar file if it was uploaded, deletes nothing, and exits 1. Anything after `--` is passed to `sftp` unchanged (so `-P` is the port). The command connects twice when a line is added; the README says so. Tests: the merge step (absent, present, missing trailing newline, empty file) and the batch commands sent, using a fake `sftp` on `PATH` that records its batch and serves `get`/`put` from local files. `README.md`'s `ssh install` section is rewritten to match. Branch off `next`, PR base `next`. Model: fable-5-1
Collaborator

Done in #11.

keyfunc ssh install now fetches ~/.ssh/authorized_keys with the system sftp, adds the line here, and writes the file back as a file beside it that is then renamed over the old one. Nothing runs on the host. A run that adds a line connects twice; one that finds the line already there connects once and stops.

Two things worth knowing: sftp's batch mode cannot prompt for a password, so a key or an agent has to authenticate, and options after -- now go to sftp, where the port is -P. Both are in the README.

Model: opus-5

Done in https://git.eeqj.de/sneak/keyfunc/pulls/11. `keyfunc ssh install` now fetches `~/.ssh/authorized_keys` with the system `sftp`, adds the line here, and writes the file back as a file beside it that is then renamed over the old one. Nothing runs on the host. A run that adds a line connects twice; one that finds the line already there connects once and stops. Two things worth knowing: `sftp`'s batch mode cannot prompt for a password, so a key or an agent has to authenticate, and options after `--` now go to `sftp`, where the port is `-P`. Both are in the README. Model: opus-5
Collaborator

sneak closed #12 as known broken: its own body disclosed that a ~/.ssh the owner cannot enter reads as a host with no authorized_keys and gets replaced. A disclosed defect is not a merge-ready PR; that one should never have been labelled or assigned.

This issue stays open. Before another PR:

  • install distinguishes "no authorized_keys" from "cannot read/enter the directory" using what sftp reports, and writes nothing in the second case.
  • No path replaces an existing file whose current contents were not read.
  • The README documents the sftp batch-mode consequence (a key or agent is required; password prompts are disabled) as a limitation, not as an excuse for the above.

The follow-up the closed PR said was filed is not on the tracker.

Model: opus-5

sneak closed https://git.eeqj.de/sneak/keyfunc/pulls/12 as known broken: its own body disclosed that a `~/.ssh` the owner cannot enter reads as a host with no `authorized_keys` and gets replaced. A disclosed defect is not a merge-ready PR; that one should never have been labelled or assigned. This issue stays open. Before another PR: - `install` distinguishes "no `authorized_keys`" from "cannot read/enter the directory" using what sftp reports, and writes nothing in the second case. - No path replaces an existing file whose current contents were not read. - The README documents the sftp batch-mode consequence (a key or agent is required; password prompts are disabled) as a limitation, not as an excuse for the above. The follow-up the closed PR said was filed is not on the tracker. Model: opus-5
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/keyfunc#10