Summary
Pasting/sending an image from the iOS app fails with "cannot connect: private key not found", even though the normal terminal/SSH session works perfectly. The image upload (SCP, per /docs/image-paste) opens its own SSH connection that targets the host's local hostname (.local / link-local) and offers an old, revoked key from a previous Easy-Pair pairing — not the active connection's key. The image never leaves the phone.
Environment
- Moshi iOS app: v3.5.0
- moshi-hook: 0.2.26 (Homebrew tap
rjyo/moshi)
- Host: macOS (Apple Silicon), Remote Login (sshd) enabled
- Transport: Tailscale. Host reachable at
<machine>.tailXXXX.ts.net / 100.x.x.x. Terminal/SSH works flawlessly over Tailscale.
What happens
The host was re-paired over time; only the newest pairing is active (moshi-hook host list):
| Pairing |
Host it points at |
Key fingerprint |
State |
| A (first) |
<machine>.local |
SHA256:p/1PZs3t… |
revoked (removed from authorized_keys) |
| B |
<machine>.ts.net |
SHA256:HjKecodm… |
revoked |
| C (current) |
<machine>.ts.net |
SHA256:AYs+pwuq… |
active (only key in authorized_keys) |
macOS unified log (log show … process CONTAINS "sshd"), captured in the same minute as one image send:
Accepted publickey for <user> from 100.x.x.x port … ssh2: ED25519 SHA256:AYs+pwuq… ← terminal: OK (Tailscale)
Connection closed by fe80::…%enX port … [preauth] ← image upload: link-local
Connection closed by 169.254.x.x port … [preauth] ← image upload: rejected
The terminal leg authenticates over Tailscale (100.x) with the active key C. The image-upload leg instead hits the link-local / .local address and is rejected at preauth because it offers the revoked pairing-A key (p/1PZs3t…), not the active key C.
Repro
- Easy-Pair a host → pairing A, hostname
<machine>.local.
- Re-pair to a Tailscale address → pairing C (
<machine>.ts.net); moshi-hook host revoke the old pairing A.
- Open the terminal → works over Tailscale (
Accepted publickey … key C).
- Paste/send an image → "cannot connect: private key not found".
Expected
Image upload should use the currently selected/active connection (its host and key) — i.e., the same Tailscale connection the terminal uses — not a stale/revoked pairing or the auto-detected local hostname.
Notes
- The phone keeps using pairing A for the upload path even after (a) deleting the old connection from the visible list (only the Tailscale connection is shown), (b) re-pairing the agent (
moshi-hook pair), and (c) restarting the daemon. Nothing short of deleting + reinstalling the app appears to change which pairing the upload uses.
/docs/image-paste says the upload is SCP to the host, while the marketing copy says "a fetchable URL — no scp". The SCP-to-local-hostname behavior also means image paste only works on the same LAN as the host, never remotely. Routing the upload over the active connection's configured host would make it work over Tailscale too.
(Filed against moshi-skill as the active public repo — happy to move this if there's a better place for iOS-app bugs.)
Summary
Pasting/sending an image from the iOS app fails with "cannot connect: private key not found", even though the normal terminal/SSH session works perfectly. The image upload (SCP, per
/docs/image-paste) opens its own SSH connection that targets the host's local hostname (.local/ link-local) and offers an old, revoked key from a previous Easy-Pair pairing — not the active connection's key. The image never leaves the phone.Environment
rjyo/moshi)<machine>.tailXXXX.ts.net/100.x.x.x. Terminal/SSH works flawlessly over Tailscale.What happens
The host was re-paired over time; only the newest pairing is active (
moshi-hook host list):<machine>.localSHA256:p/1PZs3t…<machine>.ts.netSHA256:HjKecodm…<machine>.ts.netSHA256:AYs+pwuq…macOS unified log (
log show … process CONTAINS "sshd"), captured in the same minute as one image send:The terminal leg authenticates over Tailscale (100.x) with the active key C. The image-upload leg instead hits the link-local /
.localaddress and is rejected at preauth because it offers the revoked pairing-A key (p/1PZs3t…), not the active key C.Repro
<machine>.local.<machine>.ts.net);moshi-hook host revokethe old pairing A.Accepted publickey … key C).Expected
Image upload should use the currently selected/active connection (its host and key) — i.e., the same Tailscale connection the terminal uses — not a stale/revoked pairing or the auto-detected local hostname.
Notes
moshi-hook pair), and (c) restarting the daemon. Nothing short of deleting + reinstalling the app appears to change which pairing the upload uses./docs/image-pastesays the upload is SCP to the host, while the marketing copy says "a fetchable URL — no scp". The SCP-to-local-hostname behavior also means image paste only works on the same LAN as the host, never remotely. Routing the upload over the active connection's configured host would make it work over Tailscale too.(Filed against
moshi-skillas the active public repo — happy to move this if there's a better place for iOS-app bugs.)