结论先行:SSH 密钥登录三步搞定基础安全——生成 ed25519 密钥、上传公钥、禁掉密码登录。进阶用 ~/.ssh/config 管多服务器、SSH Agent 免密 passphrase、不同账号用不同密钥。配不好要么进不去、要么被爆破,这是 VPS 安全的地基,务必先配密钥、测通能登录、再禁密码(顺序反了会把自己锁外面)。

上篇讲了 VPS 初始化,这篇专门深入 SSH 密钥。如果你管着几台 VPS、几个 GitHub 账号,迟早会遇到密钥对不上的情况——这篇把常见场景一次讲清,配好一次,长期受用。

我的 VPS 推荐:我管理 8 台 VPS,分别在 Vultr、DigitalOcean、AWS 上。如果你还没选 VPS,我推荐这几家性价比高的(Vultr · DigitalOcean)。

1、期望目标

上篇文章我们讲了VPS到手后的初始化,其中SSH密钥登录是核心。但实际使用中,你会遇到更复杂的场景:

  • 多服务器管理:手头有3-5台VPS,每台服务器用不同密钥
  • 多账号隔离:GitHub个人账号+公司账号、GitLab多个账号
  • SSH Agent免密:私钥设置了passphrase,不想每次都输入
  • 跨平台使用:Mac日常开发、Windows临时管理、手机应急登录
  • 故障排查:密钥登录失败、权限问题、连接被拒绝

这篇文章的目标是让你在任何SSH场景下都能从容应对。

新手必读路径(30 分钟搞定):

  1. 生成密钥(3.1)
  2. 上传公钥(3.2)
  3. 配置 SSH Config(3.3)
  4. 配置 SSH Agent(3.4)

进阶按需查阅

  • 多账号管理 → 3.6
  • 故障排查 → 第 5 节
  • Windows 特殊配置 → 3.4/3.5

2、计划思考

为什么需要单独讲SSH密钥?

上篇文章讲了基础的密钥登录配置,但实际出海开发者的环境更复杂:

场景 挑战 解决方案
多台VPS 每台服务器密钥不同,容易搞混 SSH Config统一管理
多平台账号 GitHub个人+工作、GitLab、Gitee 为每个平台生成独立密钥
私钥设置了passphrase 每次连接都要输密码,烦死 SSH Agent + Keychain
不同操作系统 Mac/Windows/手机各有各的坑 统一流程+针对性配置
密钥泄露应急 某台电脑丢了,所有服务器都要换密钥 密钥分层+快速轮换

整体架构

你的电脑 ~/.ssh/ ├── id_ed25519 ├── github_key └── work_key SSH Config Host vps1 IdentityFile ~/.ssh/id_ed25519 Host github.com IdentityFile ~/.ssh/github_key SSH Agent 缓存已解密密钥 自动提供认证 无需重复输入 VPS 1 生产环境 VPS 2 测试环境 GitHub 代码托管

这个架构让你能:

  • 用不同密钥访问不同服务器(单点故障隔离)
  • 一个命令连接任何服务器(省心)
  • 私钥passphrase只输一次(省事)
  • 电脑丢了,撤回特定密钥就行(安全)

3、操作步骤

3.1 生成密钥对

ed25519 vs RSA:怎么选?

算法 密钥长度 性能 兼容性 推荐场景
ed25519 短(32字节) 新系统 首选,现代服务器
RSA 4096 长(4KB) 所有系统 老旧系统、特殊兼容需求

现在的选择:新密钥全部用 ed25519。主流 VPS 商(Vultr · DigitalOcean · Linode · AWS 等)2020 年后的系统都支持 ed25519,放心用。只有当你要连 2017 年前的老系统时,才考虑 RSA 4096。

为不同用途生成不同密钥

尽量一把密钥对应一个用途,方便出问题时单独撤回。为每个场景生成独立密钥:

1
2
3
4
5
6
7
8
9
10
11
# 1. 默认密钥(用于大部分VPS)
ssh-keygen -t ed25519 -C "yourname@vps-default"

# 2. GitHub个人账号
ssh-keygen -t ed25519 -f ~/.ssh/github_personal -C "yourname@github"

# 3. GitHub工作账号
ssh-keygen -t ed25519 -f ~/.ssh/github_work -C "work@github"

# 4. 生产环境专用
ssh-keygen -t ed25519 -f ~/.ssh/prod_key -C "prod@company"

参数说明

  • -t ed25519:使用ed25519算法
  • -f filename:指定密钥文件名(不用默认的id_ed25519)
  • -C comment:添加注释,方便识别(可以是你邮箱、用途描述)

设置passphrase

passphrase 就是"加密密码",保护你的私钥文件。私钥丢了但有 passphrase,别人也用不了。

生成密钥时会提示:

1
Enter passphrase (empty for no passphrase):

强烈建议设置passphrase! 这是私钥的最后一道防线,电脑丢了还能保护你的服务器。

好的passphrase:

  • 长度≥12个字符
  • 混合大小写、数字、符号
  • 可以是一句话(空格分隔的多个单词)

💡 passphrase vs 密码

passphrase通常是一句话,比传统密码更长、更容易记,安全性和用户体验都更好。


3.2 上传公钥到服务器

方法A:ssh-copy-id(推荐)

这是最简单的方式,Mac/Linux自带:

1
2
3
4
5
6
7
8
# 上传默认密钥
ssh-copy-id [email protected]

# 上传指定密钥
ssh-copy-id -i ~/.ssh/github_work.pub [email protected]

# 指定端口(SSH没改端口可以忽略)
ssh-copy-id -i ~/.ssh/mykey.pub -p 22000 [email protected]

输入一次密码,公钥就自动配置好了。

参数说明

  • -i identity_file:指定要上传的公钥文件
  • -p port:指定 SSH 端口(很老的 ssh-copy-id 不支持 -p,改用 -o "Port=22000"

方法B:手动复制

Windows用户或ssh-copy-id不可用时:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 查看公钥内容
cat ~/.ssh/github_work.pub

# 2. 复制输出的一整行(ssh-ed25519 AAAA...)

# 3. 登录服务器(user 是服务器用户名如 root/ubuntu,server 是服务器 IP 或域名)
ssh user@server

# 4. 在服务器上执行(将第 2 步看到的公钥内容完整粘贴到下面,ssh-ed25519 开头的一整行)
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA... yourname@github" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

方法C:Windows PowerShell

Windows 10/11自带OpenSSH,可以这样:

1
2
3
4
5
6
7
8
# 生成密钥
ssh-keygen -t ed25519 -C "yourname@windows"

# 上传公钥(需要手动复制内容)
type $env:USERPROFILE\.ssh\id_ed25519.pub

# 或者用这个一键命令(需要密码登录)
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

验证配置

1
2
3
4
5
# 测试密钥登录(应该不需要输密码)
ssh -i ~/.ssh/github_work [email protected]

# 如果成功,会看到Welcome信息
# Hi username! You've successfully authenticated...

⚠️ 常见坑

  • 权限不对:.ssh必须是700,authorized_keys必须是600
  • 公钥复制错了:确保是一整行,没有换行或空格
  • 用户搞错了:~/.ssh在服务器上是目标用户的home目录

3.3 SSH Config管理多服务器

这是 SSH 管理的核心——配好后你不用记 IP、端口、用户名。

配置文件位置

你的本地电脑上编辑(用任意编辑器 nano/vim/VSCode):

1
2
3
4
5
6
7
8
# 方法1:用 nano(简单,文件不存在会自动创建)
nano ~/.ssh/config

# 方法2:用 vim
vim ~/.ssh/config

# 方法3:用 VSCode
code ~/.ssh/config

基本配置模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 全局设置(应用于所有连接)
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes

# VPS 生产环境
Host vps-prod
HostName 192.168.1.100
User deploy
Port 22000
IdentityFile ~/.ssh/prod_key

# VPS 测试环境
Host vps-test
HostName 192.168.1.101
User test
Port 22000
IdentityFile ~/.ssh/id_ed25519

# GitHub 个人账号
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
IdentitiesOnly yes

# GitHub 工作账号(用别名区分)
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
IdentitiesOnly yes

参数说明

  • Host:别名,你用这个名字连接
  • HostName:真实域名或IP
  • User:登录用户名
  • Port:SSH端口
  • IdentityFile:私钥文件路径
  • IdentitiesOnly yes:只用指定密钥,避免 SSH 傻傻试遍所有密钥导致服务器拒绝连接(报错 Too many authentication failures)
  • AddKeysToAgent yes:自动把密钥加到ssh-agent

使用方法

配置好后,连接只用别名:

1
2
3
4
5
6
7
8
# 以前要这样
ssh -p 22000 -i ~/.ssh/prod_key [email protected]

# 现在只需要这样
ssh vps-prod

# Git push也自动用对密钥
git push github-work main

高级技巧

通配符匹配

1
2
3
4
5
6
7
8
9
10
# 所有AWS服务器都用同一个密钥
Host aws-*
IdentityFile ~/.ssh/aws_key
User admin

Host aws-prod
HostName ec2-xxx.compute.amazonaws.com

Host aws-staging
HostName ec2-yyy.compute.amazonaws.com

include子配置文件

1
2
3
4
5
6
7
# ~/.ssh/config
Host *
AddKeysToAgent yes

Include config/github
Include config/work
Include config/vps

这样可以把不同用途的配置分开管理,适合复杂环境。


3.4 SSH Agent配置

如果你的私钥设置了passphrase,每次连接都要输入很烦。SSH Agent帮你缓存解密后的私钥,passphrase只输一次。

Mac/Linux配置

启动ssh-agent

1
2
3
4
5
6
7
8
9
# 启动agent
eval "$(ssh-agent -s)"

# 添加私钥(会提示输入passphrase)
ssh-add ~/.ssh/github_personal
ssh-add ~/.ssh/github_work

# 查看已添加的密钥
ssh-add -l

自动启动(推荐)

~/.bashrc~/.zshrc 添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 打开配置文件(Mac 用 nano ~/.zshrc,Linux 用 nano ~/.bashrc)
nano ~/.zshrc

# 2. 在文件末尾粘贴以下内容
# 启动ssh-agent
if [ -z "$SSH_AUTH_SOCK" ]; then
eval "$(ssh-agent -s)"
fi

# 自动添加所有密钥
# macOS Monterey (12.0) 及以后
ssh-add --apple-use-keychain 2>/dev/null || ssh-add
# 老版本 macOS 去掉 --apple-use-keychain

# 3. Ctrl+O 保存、Ctrl+X 退出

# 4. 使配置生效
source ~/.zshrc

Mac Keychain集成

Mac可以把passphrase存到系统钥匙串,以后自动解锁:

1
2
3
4
5
6
7
# 添加密钥时存到keychain(macOS Monterey 12.0 及以后)
ssh-add --apple-use-keychain ~/.ssh/github_personal
# 老版本 macOS:ssh-add ~/.ssh/github_personal

# 或者在SSH config中设置
echo "AddKeysToAgent yes" >> ~/.ssh/config
echo "IdentityFile ~/.ssh/github_personal" >> ~/.ssh/config

Windows配置

Windows 10/11的OpenSSH自带ssh-agent服务:

启用服务

1
2
3
4
5
6
7
8
9
10
# 以管理员身份运行PowerShell
# 启动ssh-agent服务
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent

# 添加密钥
ssh-add $env:USERPROFILE\.ssh\id_ed25519

# 查看已添加密钥
ssh-add -l

Git Bash配置

~/.bashrc~/.bash_profile 添加:

1
2
3
4
5
# 启动ssh-agent
eval $(ssh-agent -s)

# 添加密钥
ssh-add ~/.ssh/id_ed25519

验证Agent工作

1
2
3
4
5
6
7
8
9
10
11
# 查看agent中的密钥
ssh-add -l

# 删除某个密钥
ssh-add -d ~/.ssh/github_work

# 清空所有密钥
ssh-add -D

# 测试连接(应该不需要输入passphrase)
ssh vps-prod

SSH Agent 工作流程

1. 首次连接 输入passphrase 2. 私钥解密 加入Agent缓存 3. 后续连接 自动使用缓存 SSH Agent 内存中缓存 已解密的私钥 自动提供认证 默认超时 Agent重启 或系统重启

3.5 不同客户端配置

VSCode Remote SSH

很多出海开发者用VSCode直接连服务器开发,配置SSH密钥后超级方便:

安装插件

  1. VSCode 左侧点击扩展图标(或按 Cmd+Shift+X Mac / Ctrl+Shift+X Windows)
  2. 搜索 “Remote - SSH”
  3. 点击 Install 安装

配置连接
Cmd+Shift+P(Mac)或 Ctrl+Shift+P(Windows),输入 Remote-SSH: Connect to Host,选择你在 ~/.ssh/config 中配置的别名。

指定密钥

如果VSCode找不到密钥,在SSH config中明确指定:

1
2
3
4
Host vps-dev
HostName 192.168.1.100
User dev
IdentityFile ~/.ssh/my_dev_key

Termius / MobaXterm 等第三方工具

这些工具有图形界面,密钥配置方式:

Termius我用这个,跨设备同步密钥很方便):

  1. Preferences → Keys → Import Key
  2. 选择你的私钥文件
  3. 新建Host时,在Key field选择导入的密钥

MobaXterm免费版够用):

  1. Tools → MobaKeyGen 生成或导入密钥
  2. Session配置 → SSH settings → Use private key
  3. 选择你保存的 .ppk 文件

💡 格式转换

某些Windows工具需要PuTTY格式的 .ppk 文件,用PuTTYgen转换:

  1. 打开PuTTYgen
  2. Load → 选择你的OpenSSH私钥
  3. Save private key → 保存为 .ppk

手机端应急

Termius (iOS/Android)

  • 支持SSH密钥,可以从电脑同步或手动导入
  • 设置好之后,手机也能应急管理服务器

JuiceSSH (Android)

  • 支持密钥认证
  • 可以生成新密钥或导入现有密钥

3.6 多账号场景(GitHub/GitLab等)

出海开发者通常有多个GitHub账号:个人项目、公司项目、为客户管理的账号。

为每个平台生成独立密钥

1
2
3
4
5
6
7
8
9
10
11
# GitHub 个人账号
ssh-keygen -t ed25519 -f ~/.ssh/github_personal -C "personal@github"

# GitHub 工作账号
ssh-keygen -t ed25519 -f ~/.ssh/github_work -C "work@github"

# GitLab
ssh-keygen -t ed25519 -f ~/.ssh/gitlab -C "yourname@gitlab"

# Gitee(国内项目)
ssh-keygen -t ed25519 -f ~/.ssh/gitee -C "yourname@gitee"

SSH Config配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# GitHub 个人
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
IdentitiesOnly yes

# GitHub 工作(用别名区分)
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
IdentitiesOnly yes

# GitLab
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab
IdentitiesOnly yes

# Gitee
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/gitee
IdentitiesOnly yes

添加公钥到各平台

GitHub

  1. Settings → SSH and GPG keys → New SSH key
  2. 粘贴 ~/.ssh/github_personal.pub 的内容
  3. Title设置为 “MacBook Pro” 或其他设备名

GitLab

  1. Preferences → SSH Keys
  2. 粘贴公钥内容
  3. Add key

Git仓库配置

对于不同的GitHub账号,在仓库中设置不同的user(不同账号需要提交不同的作者信息,否则 commit 会显示错误的账号;这是仓库级配置,只对当前仓库生效):

1
2
3
4
5
6
7
8
9
# 个人仓库
cd ~/projects/personal/myproject
git config user.name "Your Name"
git config user.email "[email protected]"

# 工作仓库
cd ~/projects/work/companyproject
git config user.name "Your Name"
git config user.email "[email protected]"

测试连接

1
2
3
4
5
6
7
8
9
10
11
# 测试GitHub个人账号
ssh -T [email protected]
# Hi personalname! You've successfully authenticated...

# 测试GitHub工作账号
ssh -T git@github-work
# Hi workname! You've successfully authenticated...

# 测试GitLab
ssh -T [email protected]
# Welcome to GitLab, @yourname!

💡 为什么要 IdentitiesOnly yes?

SSH默认会尝试所有找到的密钥,服务器会拒绝太多认证尝试。加上这个参数,SSH只尝试指定的密钥,更快更可靠。


3.7 禁用密码登录(最后一步,别急着做)

⚠️ 顺序铁律:先开一个新终端用密钥测通能登录,再禁密码。顺序反了会把自己锁在服务器外面。

密钥配好、测通后,把密码登录关掉,全网的爆破脚本就彻底没戏了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 先开一个新终端,用密钥测登录(原终端保持开着,留作回退)
ssh -i ~/.ssh/id_ed25519 user@server

# 2. 确认能登进后,改 sshd 配置
sudo nano /etc/ssh/sshd_config
# 找到或新增这两行:
# PasswordAuthentication no
# PubkeyAuthentication yes

# 3. 重载 sshd(不断当前连接)
sudo systemctl reload sshd

# 4. 再开一个新终端验证:密钥能登、密码登不上
ssh user@server # 应该直接进去(密钥)
ssh -o PubkeyAuthentication=no user@server # 应该被拒(密码已关)

万一密钥登不上:原终端还开着,把 PasswordAuthentication 改回 yes、再 reload sshd 即可回退,不会把自己锁死。这一步是 SSH 安全的地基,但一定放在最后——前面所有密钥配置都是为了它能安全落地。


4、总结

关键要点回顾

主题 关键命令/配置 为什么要这么做
生成密钥 ssh-keygen -t ed25519 -C "注释" 不同用途用不同密钥,方便隔离和轮换
上传公钥 ssh-copy-id -i key.pub user@host 最简单的方式,自动配置权限
SSH Config ~/.ssh/config 配置文件 一个命令管理所有服务器,不用记IP端口用户名
多账号 用Host别名区分(github-work、github) 同一平台多个账号,各自独立
SSH Agent ssh-add + AddKeysToAgent yes Passphrase只输一次,省时省力
权限检查 chmod 700 ~/.ssh && chmod 600 authorized_keys SSH对权限要求严格,错了会拒绝密钥登录
测试连接 ssh -v user@host -v 查详细日志,排查问题

配置文件位置速查

1
2
3
4
5
6
7
8
9
本地电脑:
~/.ssh/config # SSH客户端配置
~/.ssh/id_ed25519 # 默认私钥
~/.ssh/id_ed25519.pub # 默认公钥
~/.ssh/github_personal # GitHub个人私钥

服务器:
~/.ssh/authorized_keys # 允许登录的公钥列表
/etc/ssh/sshd_config # SSH服务端配置

安全建议

  1. 密钥分层:生产环境、测试环境、个人账号用不同密钥
  2. 定期轮换:每半年到一年换一次密钥(特别是私钥没设passphrase的)
  3. 备份密钥:私钥加密备份到安全的地方(U盘、密码管理器)
  4. 监控登录:定期用 last 命令查看登录记录
  5. 撤回密钥:电脑丢了,立即从服务器删除 ~/.ssh/authorized_keys 中的对应公钥

常用命令速查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 生成密钥
ssh-keygen -t ed25519 -C "注释"

# 上传公钥
ssh-copy-id -i key.pub user@host

# 测试连接
ssh -v user@host

# 查看已添加密钥
ssh-add -l

# 查看指纹(验证密钥)
ssh-keygen -lf ~/.ssh/id_ed25519.pub

# 修改passphrase
ssh-keygen -p -f ~/.ssh/id_ed25519

# 从私钥提取公钥
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub

5、异常记录

Q1:还是提示输入密码?

诊断

1
2
# 用详细模式查看SSH在用什么认证方式
ssh -v user@host

常见原因

  1. 服务器上密钥没配置对

    1
    2
    3
    # 在服务器上检查
    cat ~/.ssh/authorized_keys
    # 确认你的公钥在里面,是一整行,没有换行
  2. 权限问题(最常见)

    1
    2
    3
    4
    # 在服务器上修复
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    chown -R youruser:youruser ~/.ssh
  3. SSH配置禁用了密钥认证

    1
    2
    3
    # 在服务器上检查
    grep PubkeyAuthentication /etc/ssh/sshd_config
    # 应该是:PubkeyAuthentication yes
  4. 用错了私钥

    1
    2
    # 明确指定私钥
    ssh -i ~/.ssh/correct_key user@host

Q2:权限太开放(Permissions are too open)?

错误信息:

1
Permissions 0644 for '/home/user/.ssh/id_ed25519' are too open.

解决

1
2
3
4
5
# 修复私钥权限(必须600)
chmod 600 ~/.ssh/id_ed25519

# 修复私钥目录权限(必须700)
chmod 700 ~/.ssh

💡 为什么SSH这么在意权限?

如果私钥文件能被其他用户读取,安全就没意义了。SSH严格检查权限,避免你无意中暴露私钥。

Q3:Windows上没有ssh-copy-id?

方法A:用PowerShell

1
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

方法B:手动复制

  1. cat ~/.ssh/id_ed25519.pub
  2. 复制输出
  3. SSH登录服务器,手动粘贴到 ~/.ssh/authorized_keys

方法C:用第三方工具

Termius、MobaXterm等图形化工具都有密钥管理功能,比命令行更直观。

Q4:SSH Agent不工作?

检查agent是否运行

1
2
3
4
5
6
# Mac/Linux
echo $SSH_AUTH_SOCK
# 如果是空的,说明agent没启动

# 启动agent
eval "$(ssh-agent -s)"

检查密钥是否已添加

1
2
3
4
ssh-add -l
# 应该列出已添加的密钥
# 如果是 "The agent has no identities",需要添加密钥
ssh-add ~/.ssh/your_key

Windows服务没启动

1
2
3
4
5
# 以管理员身份运行
Get-Service ssh-agent
# 如果Status是Stopped,启动它
Start-Service ssh-agent
Set-Service ssh-agent -StartupType Automatic

Q5:多个密钥SSH都试但都不对?

症状

1
Too many authentication failures

原因:SSH默认会尝试所有找到的密钥,服务器拒绝太多尝试。

解决:在SSH config中加上 IdentitiesOnly yes

1
2
3
4
5
Host myserver
HostName 192.168.1.100
User myuser
IdentityFile ~/.ssh/my_key
IdentitiesOnly yes # 关键:只尝试指定的密钥

Q6:想换掉旧密钥?

步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 生成新密钥
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "rotated@2026"

# 2. 上传新公钥到服务器
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@host

# 3. 测试新密钥登录
ssh -i ~/.ssh/id_ed25519_new user@host

# 4. 用新密钥登录(保持用新密钥,别用默认/旧密钥),从服务器删除旧公钥
ssh -i ~/.ssh/id_ed25519_new user@host
vim ~/.ssh/authorized_keys # 手动删除旧公钥那一行
# ⚠️ 删公钥前先备份,误删会把自己关在服务器外!

# 5. 更新SSH config(如果用了自定义文件名)
# 6. 删除旧私钥
rm ~/.ssh/id_ed25519_old

Q7:密钥指纹不匹配?

首次连接会看到:

1
2
The authenticity of host 'xxx' can't be established.
ED25519 key fingerprint is SHA256:...

验证指纹

1
2
3
4
# 从服务器获取指纹
ssh-keyscan -t ed25519 host 2>/dev/null | ssh-keygen -lf -

# 或者让服务商提供指纹(VPS控制台通常会显示)

指纹不匹配怎么办?

立即停止连接!可能是中间人攻击。联系服务商确认。

Q8:Git push提示权限拒绝?

问题

1
ERROR: Permission to username/repo.git denied to deploykey

原因:密钥没对,或者SSH config没配置好。

解决

1
2
3
4
5
6
7
8
9
10
11
# 1. 测试SSH连接
ssh -T [email protected]

# 2. 检查用到的密钥
ssh -vT [email protected]
# 在输出中找 "Offering public key"

# 3. 在SSH config中明确指定密钥
Host github.com
IdentityFile ~/.ssh/correct_github_key
IdentitiesOnly yes

6、进阶技巧

一键添加多个密钥到Agent

~/.bashrc~/.zshrc 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 自动添加所有密钥到ssh-agent
add_ssh_keys() {
local keys=(
~/.ssh/id_ed25519
~/.ssh/github_personal
~/.ssh/github_work
~/.ssh/prod_key
)

for key in "${keys[@]}"; do
if [ -f "$key" ]; then
ssh-add --apple-use-keychain "$key" 2>/dev/null || ssh-add "$key" 2>/dev/null
fi
done
}

# 启动agent并添加密钥
if [ -z "$SSH_AUTH_SOCK" ]; then
eval "$(ssh-agent -s)"
add_ssh_keys
fi

密钥过期提醒

创建一个定期任务检查密钥年龄:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# check_ssh_keys.sh

for key in ~/.ssh/*.pub; do
if [ -f "$key" ]; then
# macOS 用 stat -f %m;Linux 改成 stat -c %Y
mtime=$(stat -f %m "$key" 2>/dev/null || stat -c %Y "$key")
age=$(( ($(date +%s) - mtime) / 86400 ))
if [ $age -gt 365 ]; then
echo "⚠️ 密钥 $(basename $key) 已经 $age 天没换了,考虑轮换"
fi
fi
done

密钥轮换脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
# rotate_ssh_key.sh
set -e

KEY_NAME="$1"
NEW_KEY="${KEY_NAME}_new_$(date +%Y%m%d)"

echo "=== SSH密钥轮换脚本 ==="
echo "目标密钥:$KEY_NAME"
echo "新密钥名:$NEW_KEY"
echo ""

# 1. 生成新密钥
echo "[1/5] 生成新密钥..."
ssh-keygen -t ed25519 -f ~/.ssh/"$NEW_KEY" -C "rotated@$(date +%Y-%m-%d)"

# 2. 显示公钥,提示上传
echo ""
echo "[2/5] 请将以下公钥上传到服务器:"
cat ~/.ssh/"${NEW_KEY}".pub
echo ""
read -p "上传完成后按回车继续..."

# 3. 测试新密钥
echo "[3/5] 测试新密钥..."
read -p "输入服务器地址(user@host): " server
ssh -i ~/.ssh/"$NEW_KEY" "$server" "echo '新密钥测试成功'"

# 4. 备份旧密钥
echo "[4/5] 备份旧密钥..."
mv ~/.ssh/"$KEY_NAME" ~/.ssh/"${KEY_NAME}_backup_$(date +%Y%m%d)"

# 5. 重命名新密钥
echo "[5/5] 重命名新密钥..."
mv ~/.ssh/"$NEW_KEY" ~/.ssh/"$KEY_NAME"
mv ~/.ssh/"${NEW_KEY}.pub" ~/.ssh/"${KEY_NAME}.pub"

echo "✅ 密钥轮换完成!旧密钥已备份。"

7、FAQ(SSH 密钥最常问)

Q:ed25519 和 RSA 选哪个?
新装一律 ed25519——密钥短、握手快、抗碰撞强度高。老的 RSA 2048 还能用但没必要新生成;RSA 1024 必须立刻换。

Q:私钥 passphrase 忘了怎么办?
找不回,只能重新生成密钥对、重新上传公钥。所以 passphrase 存密码管理器(1Password/Bitwarden),别靠脑子记。

Q:一台电脑能放多把密钥吗?
能。~/.ssh/ 下放多把,用 ~/.ssh/config 的 IdentityFile 给每个 Host 指定对应密钥。别一把密钥走天下(一台泄露全沦陷)。

Q:换电脑怎么迁移密钥?
把 ~/.ssh/ 整个目录(含 .pub 和 config)拷过去,注意私钥权限 600。更稳的做法:新电脑新生成密钥,把旧公钥在服务器撤销。

Q:禁了密码登录会把自己锁外面吗?
会,所以顺序是:先配好密钥 → 开新终端用密钥测能登录 → 再禁密码。千万别先禁密码再配密钥。

下一篇预告

密钥配好、禁了密码,SSH 的地基就稳了。如果还没 VPS 练手,我推荐 Vultr · DigitalOcean。下一篇讲 SSH Config 进阶:Include 子配置、跳板机(ProxyJump)、连接复用,把多服务器管理再往前推一步。


这是「独立开发者工具箱」第 8 篇,系列持续更新中,帮你少踩坑多出海。

Sources: