nixos-anywhere 上传密钥时报 Too many authentication failures
nixos-anywhere 在上传安装密钥前尝试多把 agent 身份,耗尽连接认证次数。核对上传分支的 SSH 参数,用单次环境或 IdentityAgent 限制 agent,并区分连接测试与会覆盖磁盘的安装命令。
安装停在 Uploading install SSH keys,还没进入磁盘操作,SSH 就断开了:
Received disconnect from 192.0.2.10 port 22:2: Too many authentication failures
这条报错不一定是密码输错了很多次。SSH 可以在询问密码之前尝试 agent 提供的多把密钥,每次未被接受的认证尝试都会消耗这次连接的额度。达到服务端限制后,连接会被关闭,密码认证也就没有机会继续。
本文处理的是 nixos-anywhere 使用密码引导新机器、上传临时安装密钥时,被额外 agent 身份耗尽认证尝试的情况。不是所有 SSH 认证失败都属于这一原因;如果连接根本未建立,或只尝试一个身份便被拒绝,应按对应日志继续排查。
从日志确认断开前尝试了什么
调试日志如果显示 agent 连续提供多把无关公钥,并在进入密码认证之前收到断开消息,说明应检查这些身份是否耗尽了连接内的认证尝试。单独 SSH 登录成功不能排除安装工具使用了不同选项。
在运行安装命令的同一终端查看 agent 和目标配置。地址、用户和端口按实际替换:
ssh-add -l
ssh -G -p 22 nixos@192.0.2.10
ssh-add -l 只列出 agent 里的身份指纹;数量多只是线索,不能单凭它下结论。ssh -G 展开目标的配置后退出,不建立远程连接。关注 identityagent、identitiesonly、各条 identityfile,以及实际用户、主机和端口。安装命令使用主机别名时,这里也使用那个别名。
从失败命令已有的调试日志比较 Will attempt key、Offering public key 与最后的断开位置。确认无关身份是否在密码认证前连续被提供并拒绝。不要为了凑齐日志反复重跑完整安装,尤其是前一次已经越过认证阶段时。
OpenSSH 的 MaxAuthTries限制每个连接里的认证尝试数,默认值为 6,但服务器可以改过。因此,不应把“第六把失败”推广为所有服务器的固定规则,也不应据此认定账号被永久锁定。外部封禁、账号策略和连接内的次数限制需要分别判断。
全局设了 IdentitiesOnly,上传阶段仍可能允许额外密钥
单独执行 ssh 成功,并不保证安装工具采用同一组选项。nixos-anywhere 修订 4270e9aae9790d18188d667b40b05cfd9746141a 的普通交互式上传分支调用 ssh-copy-id 时,显式将 IdentitiesOnly=no 放在后续 SSH 参数之前:
ssh-copy-id -o IdentitiesOnly=no ... -o IdentitiesOnly=yes ...
这样安排是为了覆盖后面的 IdentitiesOnly=yes;同一命令行选项以先取得的值为准。这个分支也与使用 --env-password 的分支不同。只在 ~/.ssh/config 里增加 IdentitiesOnly yes,或在工具参数后面再次加同样设置,未必改变上传阶段的行为。
这项行为限于上述修订的普通上传分支,其他版本和认证路线需另查。处理前对照所运行版本的实际命令和日志,不假定升级到某个版本就会修复。Identity file ... not accessible 如果也出现,另查那条路径与发生阶段,不能把缺失文件直接归因为 agent 密钥过多。
先用普通 SSH 验证不依赖 agent 的登录
如果安装器账号已经允许密码登录,且这次连接不依赖仅存在于 agent 中的私钥,可以先做一次只执行 true 的登录检查:
SSH_AUTH_SOCK= ssh -v -p 22 nixos@192.0.2.10 true
空值仅对这一条命令及其子进程生效,不会删除 agent 中的密钥,也不会停掉其他终端的 agent。正常情况下,客户端无法再通过这个环境变量找到 agent socket。首次连接仍应按可信的控制台或已有记录核对主机指纹,不能为排错跳过它。
如果仍然提供大量 agent 密钥,检查有没有显式配置 IdentityAgent。这项设置会覆盖 SSH_AUTH_SOCK;将它设为 none 才会禁用该客户端的 agent。可以先对单次 SSH 验证:
ssh -v -o IdentityAgent=none -p 22 nixos@192.0.2.10 true
禁用 agent 不会阻止本地身份文件被尝试,也不会让错误的用户、密码或私钥获得授权。如果使用密码管理器、硬件密钥或跳板机,认证可能正依赖 agent;不要在不了解这条链路时照搬禁用设置。
将同一限制带到安装命令
普通 SSH 在不使用 agent 时能够完成所需认证后,再把单次环境设置带到原安装命令。下面的 newvm、用户和地址都是占位值,必须替换成已经核对的配置和目标:
SSH_AUTH_SOCK= nix run github:nix-community/nixos-anywhere -- \
--flake .#newvm \
--target-host nixos@192.0.2.10
这是一条远程安装命令,不是连接测试。nixos-anywhere 后续可能分区、格式化并覆盖目标磁盘。目标必须是新机器,或重要数据已经迁出的待重装机器;不要把已有生产服务器作为这个示例的目标。运行前确认目标身份、安装配置和数据备份,连接恢复后不能把后续磁盘操作当成无害的重试。
如果需要显式覆盖 IdentityAgent,工具支持的 --ssh-option可以传递这项 SSH 设置:
nix run github:nix-community/nixos-anywhere -- \
--flake .#newvm \
--target-host nixos@192.0.2.10 \
--ssh-option IdentityAgent=none
这条命令同样需要前面的安装前提。它限制工具所调用 SSH 的 agent 使用,当前 shell 的 socket 环境仍保留。如果 flake 获取或其他子流程依赖 agent,整条命令前的 SSH_AUTH_SOCK= 可能影响那些流程,应先确认依赖,而不是把新认证失败归为同一个问题。
验收上传阶段,保留其他连接的身份
恢复这一故障的证据是:上传阶段不再因无关 agent 身份耗尽次数而断开,预期认证完成,工具能继续到下一阶段。后续 Nix 构建、权限、网络或磁盘错误有各自原因;上传通过不代表整次安装完成。
AddKeysToAgent yes 可以把从文件加载的密钥加入运行中的 agent,多次安装运行产生的临时密钥也可能留在其中。是否发生这种情况,要结合实际设置和 agent 中的身份核对。
不要把 ssh-add -D 作为固定修复,它会删除 agent 的全部身份,影响其他需要这些身份的连接。需要清理时,按 ssh-add -l 的指纹确认对象,并使用针对单个公钥文件的 ssh-add -d;相关文件已消失或身份归属不明时,先保留这些身份,用单次禁用 agent 的方式缩小影响范围。
以上两个限制都写在单次命令里,下一次不带它们就恢复原调用方式。若另行修改了 SSH 配置,应保留修改前的副本,回退只恢复本次改动。认证问题不需要先调高服务端 MaxAuthTries,也不需要为了试一次安装而清空所有密钥。


