SSH 登录方案 —— 使用 systemd user unit 管理 ssh-agent
背景
传统方式下,ssh-agent 通常由桌面环境或 shell 启动,依赖 X 会话。离开图形环境(如纯 TTY、SSH 跳板机)时,agent 不会自动运行,需要手动处理。
从 OpenSSH 9.4p1-3 开始,openssh 包提供了原生的 ssh-agent.service 用户单元,由 systemd 接管生命周期,随用户登录启动,与 X 无关。
配置步骤
1. 启用 ssh-agent 用户服务
systemctl --user enable --now ssh-agent.service
2. 设置环境变量
将 SSH_AUTH_SOCK 指向 systemd 管理的 socket。
Shell 配置(添加到 ~/.bashrc 或 ~/.zshrc):
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
systemd 环境(确保 SSH_AUTH_SOCK 对 systemd user units 也可见):
mkdir -p ~/.config/environment.d
创建 ~/.config/environment.d/ssh-agent.conf:
SSH_AUTH_SOCK=${XDG_RUNTIME_DIR}/ssh-agent.socket
~/.config/environment.d/*.conf 中的变量由 systemd 在用户登录时自动导入,所有 systemd user 服务都能继承该环境变量,无需额外操作。
3. 自动添加密钥到 agent
编辑 ~/.ssh/config,全局启用自动添加:
Host *
AddKeysToAgent yes
这样,首次使用 SSH 连接时,私钥会自动加载到 agent,后续连接无需重复输入密码。
验证
# 检查 agent 是否运行
systemctl --user status ssh-agent.service
# 查看已加载的密钥
ssh-add -l
进阶方案 —— KeePassXC 代理 SSH Agent
KeePassXC 是一款跨平台开源密码管理器,原生支持与 SSH Agent 集成。私钥以附件形式加密存储在数据库中,解锁数据库时自动加载到 agent,锁定或关闭时自动移除,实现按需使用。
为什么用密码管理器管理 SSH 密钥
密钥文件默认存在 ~/.ssh/ 目录,一旦系统被入侵,私钥可能被窃取。即使设置了密码,每次使用都要手动输入,体验繁琐。
KeePassXC 将密钥对加密存储在 KDBX 数据库中,使用时通过主密码解锁,用完后锁定即卸载密钥。既免去了密钥文件管理、重复输入密码的麻烦,又提高了安全性。
保存私钥到 KeePassXC
创建 SSH 专用群组后,新建条目:
- 条目标签:标题/用户名可任意填写(仅用于备忘),密码填入创建密钥时设置的密码
- 高级标签:附件区域点击「添加文件-从磁盘加载」,将公钥和私钥都添加上
- SSH 代理标签:
- 勾选「在打开或解锁数据库时,向代理添加密钥」
- 勾选「数据库关闭或锁定时,从代理中删除密钥」
- 私钥区域选择附件中对应的私钥文件
- Windows 不要勾选「使用此密钥时请求用户确认」(不支持该特性)
保存后,密钥便安全地托管在 KeePassXC 中。
集成 SSH Agent
打开 KeePassXC 工具 → 设置 → SSH 代理:
- 勾选「启用 SSH 代理集成」
- 代理类型选择「使用 OpenSSH」(推荐,Pageant 仅 PuTTY 生态可用)
保存后返回该页面,若显示 SSH 代理连接工作正常 则表示集成成功。Windows 下若提示 代理未在运行,需先启动 ssh-agent 服务。
验证
锁定 KeePassXC,打开终端执行:
ssh-add -l
# 输出: The agent has no identities.
解锁 KeePassXC 后再次执行,将显示已加载的密钥指纹。
日常使用:SSH Config 配合公钥匹配
由于私钥不再保存在文件系统中,IdentityFile 需指向对应的公钥文件。SSH 会通过公钥指纹从 agent 中找到已加载的私钥。
Host github.com
HostName github.com
User git
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519_github.pub
Host myserver
HostName 192.168.1.100
User ubuntu
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519_server.pub