好久没写博客了,先记一下现在用的 SSH 配置。
我在 Mac 上连接博客服务器,用的是 1Password 自带的 SSH Agent。密钥由 1Password 管理,连接时按提示授权,平时还是一句 ssh blog,不用换客户端,也不用把私钥导出来交给终端。
这篇按实际配置的顺序写:准备密钥、开启 Agent、连接服务器,再顺手接上 GitHub。最后留几个排错方法,下次连不上时也方便自己回来翻。
本文以 macOS + 1Password 桌面端 + OpenSSH 为例。示例中的域名、用户名和文件名都需要换成自己的;其他系统的 Agent 路径不同,不要整段照搬。
先弄清楚:私钥到底放在哪里
最开始容易混淆的是:既然私钥在 1Password 里,为什么 ~/.ssh/config 还要填一个文件路径?
因为这里填的是公钥。它用来告诉 SSH「这台服务器要用哪把密钥」,实际签名由 1Password Agent 完成。服务器收到签名后,用已保存的公钥验证身份。下面这张图只画认证关系,省略了 SSH 握手细节:
| 放在哪里 | 保存什么 | 用途 |
|---|---|---|
| 1Password | SSH Key 项目,包含私钥 | Agent 使用私钥完成签名 |
Mac 的 ~/.ssh/server.pub | 公钥 | 为这个 Host 选定密钥 |
服务器的 ~/.ssh/authorized_keys | 允许登录的公钥 | 验证客户端身份 |
这套流程不需要在 ~/.ssh 中额外放一份明文私钥,也不需要用 ssh-add 把私钥导入 1Password Agent。导入旧密钥后,原来的私钥文件不会因此自动消失,是否保留要另外处理。Agent 的授权与安全说明
1. 准备一把 SSH 密钥
打开 1Password,新建一个 SSH Key 项目:
- 已有密钥:在
Add Private Key中选择Import a Key File,导入原来的私钥。有口令就按提示输入,别选成.pub文件。 - 新建密钥:选择
Generate New Key。常见的新环境用Ed25519即可,旧系统有兼容要求再单独确认。
给项目起一个看得懂的名字,例如 Blog Server,以后授权时容易认出来。生成和导入支持的格式可以查密钥管理文档。
服务器上放公钥
如果导入的就是原来能登录的那把密钥,服务器通常不需要调整。如果生成了新密钥,就要把新公钥追加到目标用户的 ~/.ssh/authorized_keys。
先保留一条能登录的旧连接。在服务器上,以之后准备登录的用户执行:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
然后编辑 ~/.ssh/authorized_keys,另起一行粘贴 1Password 中的完整公钥。一把公钥占一行,不要覆盖已有内容,也不要把私钥粘进去。
比如公钥写在 ubuntu 用户的目录里,后面就用 ubuntu 登录。用 sudo 创建文件时还要检查归属,避免文件留在了错误用户的目录下。
新连接验证成功之前,先别关旧终端,也别急着删掉原来的密钥。
2. 开启 1Password SSH Agent
在 1Password 的 Settings → Developer 中开启 Use the SSH Agent。客户端需要保持运行;也可以按自己的习惯开启菜单栏驻留和登录启动。
配置了 Touch ID 的 Mac 可以用指纹批准请求。是否每次都弹窗,取决于授权设置、客户端会话和锁定状态,不是每条 ssh 命令都一定再确认一次。官方设置步骤
3. 给博客服务器配一个 Host
下面回到 Mac 本机。先准备 SSH 配置文件:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
从 1Password 的 SSH Key 项目中下载 Public key,保存为 ~/.ssh/server.pub,再向 ~/.ssh/config 添加:
Host blog
HostName server.example.com
User ubuntu
Port 22
IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
IdentityFile ~/.ssh/server.pub
IdentitiesOnly yes
这里有几个需要对应上的地方:
| 配置项 | 填什么 |
|---|---|
Host | 自己起的别名,之后执行 ssh blog |
HostName | 服务器真实 IP 或域名 |
User / Port | 登录用户和 SSH 端口 |
IdentityAgent | 1Password Agent 的本机 socket 路径 |
IdentityFile | 与 1Password 中那把私钥配对的 .pub 文件 |
IdentitiesOnly yes | 限定使用配置指定的身份,避免遍历 Agent 中其他密钥 |
IdentityAgent 路径中有空格,引号别漏。已经有 Host blog 的话,修改原来的配置块,不要重复追加。
IdentityFile 用公钥不是笔误。 OpenSSH 支持用它选择 Agent 中对应的密钥;一些其他 SSH 客户端未必支持。配上 IdentitiesOnly yes,也能避免密钥太多时出现 Too many authentication failures。为主机指定密钥
试一次连接
ssh blog
第一次连到这台服务器,可能先遇到主机指纹确认。通过云控制台或其他可信渠道核对后再接受;它是在确认「对面是不是我的服务器」。1Password 的授权提示则是在确认「是否允许这个客户端使用我的密钥」,两者不是一回事。
下面是 1Password 官方文档中的授权弹窗示例。图里是 iTerm2 执行 git pull 时请求使用 SSH 密钥,连接服务器时也是同一类授权。

1Password SSH 授权弹窗:确认请求应用、SSH 密钥,并使用 Touch ID 授权
图片来源:1Password 官方文档。界面会随版本和系统有所不同。
弹窗里先核对请求的应用和要使用的密钥,再按提示用 Touch ID 或其他可用方式授权。没有开启显示密钥名称时,可能显示的是公钥指纹。普通连接保留 Approve for all applications 不勾选即可,无需为了登录一次放宽到所有应用。
授权通过并进入远程 Shell 后,这段配置就通了。以后 scp、sftp 也可以使用同一个主机别名。
4. 顺便接上 GitHub
GitHub 可以另用一把密钥,和服务器用途分开。把公钥添加到 GitHub 的 Settings → SSH and GPG keys → New SSH key,类型选 Authentication Key;再把同一份公钥保存为本机的 ~/.ssh/github.pub。
向 ~/.ssh/config 添加:
Host github.com
HostName github.com
User git
IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
IdentityFile ~/.ssh/github.pub
IdentitiesOnly yes
注意这里的 User 固定是 git,不是自己的 GitHub 用户名。然后测试:
ssh -T [email protected]
核对首次连接的主机指纹并完成授权后,GitHub 会提示认证成功,同时说明不提供 Shell。这是正常结果;这条测试命令成功认证时也可能以状态码 1 退出,不要只看退出码就判断失败。GitHub 测试说明
接下来确认仓库使用的是 SSH 地址:
git remote -v
如果 origin 仍是 HTTPS 地址,在仓库目录中将它改为自己的 SSH 地址:
git remote set-url origin [email protected]:YOUR_NAME/YOUR_REPO.git
这只处理 Git 的 SSH 认证,和 commit 签名是两件事。想让提交显示签名验证标记,还需要另外配置。
连不上时,按这个顺序看
先看最终生效的配置和连接日志,比来回改文件更容易定位:
# 看 Host、用户、端口、Agent 和密钥路径等最终配置
ssh -G blog
# 看连接、选钥和认证过程
ssh -v blog
Agent 签名失败
这次整理博客时就遇到过:
sign_and_send_pubkey: signing failed ... from agent: communication with agent failed
Permission denied (publickey).
先看前一行,不要一看到最后的 Permission denied 就去服务器换公钥。这里已经有本机 Agent 通信失败的线索。
确认 1Password 正在运行、SSH Agent 已开启,按提示解锁并授权,检查配置中的 socket 路径,再重试。必要时重新打开 1Password。后续重连成功了,但当时没有进一步定位到唯一原因,所以也不能把这个报错一概归结为「忘了解锁」。
试了太多密钥
报 Too many authentication failures 时,检查 IdentityFile 和 IdentitiesOnly yes。还要留意其他匹配的 Host 配置是否追加了身份,最后以 ssh -G blog 的结果为准。
只有公钥认证被拒绝
如果日志没有明显的 Agent 错误,再核对这些对应关系:
- 登录用户是不是公钥所在的那个用户。
- 本机
.pub、1Password 密钥和服务器公钥是不是同一把。 - 服务器
.ssh目录与authorized_keys的权限、归属是否正确。 - 1Password 中这把密钥是否对 Agent 可用,授权是否被取消。
可以在 Mac 上查看公钥指纹,再和 1Password 中显示的指纹比较:
ssh-keygen -lf ~/.ssh/server.pub
SSH 能连,ssh-add 却说没有密钥
ssh-add 使用的是 SSH_AUTH_SOCK,不会读取 Host blog 中的 IdentityAgent。临时指定 1Password 的 socket,再列出 Agent 提供的密钥指纹:
SSH_AUTH_SOCK="$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" ssh-add -l
注意这里是 Shell 命令,引号内用 $HOME。不要写成 "~/Library/...",Shell 不会展开双引号里的波浪号;前面的 sshconfig 则由 SSH 解析。
终端能用,其他客户端不能用
检查客户端是否支持 IdentityAgent 和公钥形式的 IdentityFile,部分软件需要另外设置 SSH_AUTH_SOCK。如果密钥保存在自定义或共享保险库,还要检查 Agent 的密钥可用范围。
这两种情况分别参考客户端兼容性和 Agent 配置,不用先把私钥导出来试。
配好之后
日常用法没有变:连服务器还是 ssh blog,拉代码还是 git pull。只是需要签名的时候,由 1Password 接手。
以后加服务器,先在目标用户下登记公钥,再补一段 Host,把地址、用户名和公钥路径对上就行。换电脑时也记得把 SSH 配置和公钥准备好,单有 1Password 中的密钥还不够。
暂时先记这些。下次遇到新的报错,再回来补。