Files
command-center/agent/managed-skills/ssh-key-bootstrap-no-sshpass/SKILL.md
T
Frank 4b82f35354 Add blankpad-host auto-learn skills and memory store
Tracked the harness artifacts accumulated on blankpad (blank@), matching
the existing convention for the --home-dank-* memory stores and the 36
already-tracked managed-skills.

managed-skills (9): authentik-proxy-provider-app-link,
dankclaw-guard-chain-layer-diagnosis, e2e-arr-rawip-reachability-triage,
halogen-kv-pool-fit, lan-client-split-dns-fix, noctalia-reference,
rootless-quadlet-log-retrieval, ssh-key-bootstrap-no-sshpass,
swapfile-resize-safe-ordering.

memories (2 stores): --home-blank-.omp-- (dotfiles_git, handy_lifecycle,
input_permissions) and --home-blank-Projects-serverAppConfig--
(frank_large_quadlet).

Secret sweep before staging: no PEM blocks, no credential literals.
Content is fleet topology/IPs only, same class as the tracked dank stores.
2026-09-13 00:25:29 -07:00

2.5 KiB

name, description
name description
ssh-key-bootstrap-no-sshpass Bootstrap passwordless SSH from a dev box to fleet hosts when sshpass/expect are unavailable, using OpenSSH SSH_ASKPASS_REQUIRE=force so the password never touches disk.

Passwordless SSH bootstrap without sshpass/expect

Use when you must install your pubkey on remote hosts but sshpass and expect are not installed, and you only have a password. Modern OpenSSH (>= 8.4) can drive the password prompt from a helper program, so the password flows through the process env only — never a file.

Procedure

  1. Generate a key (if none):

    ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "host-deploy-$(date +%Y%m%d)"
    
  2. Create an askpass helper that echoes the password from an env var (the helper itself stores NO secret):

    printf '#!/bin/sh\necho "$DEPLOY_PW"\n' > /tmp/askpass.sh
    chmod 700 /tmp/askpass.sh
    
  3. Copy the pubkey, forcing the askpass path and detaching from the TTY with setsid (ssh only uses SSH_ASKPASS when there is no controlling TTY, unless SSH_ASKPASS_REQUIRE=force):

    env DEPLOY_PW='<password>' \
        SSH_ASKPASS=/tmp/askpass.sh \
        SSH_ASKPASS_REQUIRE=force \
        setsid ssh-copy-id -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 user@host
    

    Pass the password via the env argument (transient), never in a committed file or shell history.

  4. Add host aliases in ~/.ssh/config so deploy scripts resolve names:

    Host myhost
        HostName 10.0.0.5
        User deployuser
        IdentityFile ~/.ssh/id_ed25519
        IdentitiesOnly yes
    
  5. Verify key auth with no prompt:

    ssh -o BatchMode=yes myhost 'echo OK; hostname'
    

    BatchMode=yes fails fast if a password would be required — a clean success proves the key works.

Gotchas

  • Without SSH_ASKPASS_REQUIRE=force, ssh ignores SSH_ASKPASS when a TTY is present and just prompts interactively (hangs in a non-interactive tool).
  • setsid detaches the controlling terminal — required on older OpenSSH even with force, harmless otherwise.
  • The helper must be executable (chmod 700) and print ONLY the password.
  • IdentitiesOnly yes stops ssh offering other agent keys that could be rejected before yours, avoiding "Too many authentication failures".
  • Passwordless sudo on the target is a separate concern (NOPASSWD / FRANK_SUDO_PW); this skill only covers SSH key auth.