Playbook: bms-4 claude-runner SSH client config (Status: DRAFT)

Origin: #6032, discovered 2026-08-09 during a supervised W3_APP_MONGODB_PASSWORD rotation — scripts/rotate/w3_app_mongodb_password.sh’s pre-flight SSH check from bms-4 to bms-1 failed with Permission denied (publickey) even though a dedicated key (id_bms1) already existed.

The gap

cross-server-ssh-key-standard.md covers which public keys are authorized on which servers (authorized_keys, server-side). It does not cover the client side: which private key the claude-runner account on bms-4 should offer when it connects to a specific host. Without a ~/.ssh/config entry, ssh root@<host> only tries the default identity files (~/.ssh/id_rsa, ~/.ssh/id_ed25519, etc.) — a purpose-created key like id_bms1 sitting in the same ~/.ssh/ directory is never offered automatically, and the connection fails silently unless the caller passes -i explicitly every time (most scripts, including scripts/rotate/*.sh, don’t).

Fix

Add a Host block to /home/claude-runner/.ssh/config on bms-4 (create the file if absent — purely additive, does not touch authorized_keys on any host, cannot cause a lockout):

Host 94.23.26.113 bms-1
    User root
    IdentityFile /home/claude-runner/.ssh/id_bms1
    StrictHostKeyChecking no
    BatchMode yes

Apply as the claude-runner user (never as root writing into another user’s home):

ssh <bms-4> "sudo -u claude-runner bash -c 'umask 077; cat >> /home/claude-runner/.ssh/config' " <<'EOF' # PLAYBOOK: bms4-claude-runner-ssh-client-config.md
Host 94.23.26.113 bms-1
    User root
    IdentityFile /home/claude-runner/.ssh/id_bms1
    StrictHostKeyChecking no
    BatchMode yes
EOF

Verify

ssh <bms-4> "sudo -u claude-runner ssh -o BatchMode=yes -o ConnectTimeout=15 94.23.26.113 'echo ssh_config_ok'" # PLAYBOOK: bms4-claude-runner-ssh-client-config.md

Expect ssh_config_ok with no -i flag needed. Also re-run the rotation script’s own pre-flight step (or any read-only bms-1 command) as claude-runner without an explicit -i to confirm.

Prevention / follow-up

  • Check whether other purpose-created keys on bms-4 (any account) have the same gap — ls ~/.ssh/id_* for every service account and confirm each has a matching Host entry, not just the default identity.
  • If a future incident provisions another per-host key, wire the ~/.ssh/config entry in the same step — don’t leave it as a follow-up.

Escalation

If ssh_config_ok still fails after this change: the key itself may not be authorized on bms-1’s authorized_keys (check via cross-server-ssh-key-standard.md), not a client-config problem.