资讯动态

Git SSH密钥配置完全指南:原理、跨平台操作与故障排查

发布时间:2026/9/19 12:02:48 来源:尧图企业网站定制
换一台新电脑、换一个操作系统或者第一次从 HTTPS 方式切到 SSH 方式时几乎每个用 Git 的人都会被 SSH 密钥配置这关卡一下。我之前帮同事排查过几次git push权限报错发现大多数问题不是命令记不住而是对“公钥和私钥的工作原理”没有一个清晰的画面密钥生成完不知道该把哪一半交给 GitHub、哪一半锁在本地Windows、macOS、Linux 三套系统的配置路径又各有差异一步错就一路错。这篇就把 Git 配置 SSH 密钥这件事从头到尾拆开讲一遍。内容覆盖跨平台完整实操先讲明白非对称加密下公钥私钥到底怎么工作再分别给出 Windows、macOS、Linux 下从环境准备、密钥生成、托管平台配置、ssh-agent 多密钥管理到最后报错排查的完整链路。无论你是刚接触 Git 的小白还是从 HTTPS 迁移到 SSH 的老手都可以按图索骥跟着操作。1. SSH 密钥的原理与为何比 HTTPS 更值得配置1.1 HTTPS 和 SSH 两种 remote 方式的本质区别Git 连接远程仓库有两种常见协议HTTPS 和 SSH。HTTPS 的方式最直观clone 的时候直接用https://github.com/xxx/repo.gitpush 的时候输入用户名和密码或 token就能用。但问题也藏在“直观”里每次都输入凭据不说很多平台已经不再接受密码必须去生成 Personal Access Token然后把这串很长的 token 复制到剪贴板再粘贴到命令行。偶尔一次还能忍天天 push 就非常烦。SSH 方式则走的是“密钥对”的认证思路。你本地生成一对密钥一把公钥、一把私钥。公钥上传到 GitHub/Gitee/GitLab 等托管平台私钥留在本地绝不公开。之后每次git push、git pullGit 都会自动基于这对密钥完成身份认证不需要你再输入任何密码。配置一次长期免密这也是几乎所有开发者的最终选择。这里有一个很多人踩过的误区不小心用了 HTTPS clone却以为配置好 SSH 密钥后 push 会自动走 SSH。实际上 remote 地址是什么协议Git 就走什么协议。你要么一开始就用 SSH 地址 clone要么之后手动把 remote 改成 SSH 地址否则密钥配得再正确也白搭。1.2 对称加密和非对称加密先搞清楚这两个概念要理解 SSH 密钥得先分清两类加密方式。对称加密就像你用同一把钥匙锁门和开门加密和解密用的是同一把密钥。它的优点是快缺点是这把钥匙怎么安全地交给对方如果通过网络传中途被截获整条链路就废了。生活中常见的 AES 就是对称加密算法。非对称加密则是一对钥匙公钥和私钥。你可以把公钥当成一把谁都能看的挂锁私钥是只有你有的开锁工具。公钥加密的数据只有私钥能解密反过来私钥签名的数据别人用你的公钥就能验证这个签名确实出自你手。SSH 密钥认证正是建立在非对称加密的签名机制上。服务器并不需要知道你私钥的任何信息只需要保存你的公钥。你连接时服务器生成一段随机挑战数据发给你你的客户端用私钥给它签名服务器再用公钥验证签名是否有效。验证通过就认定你是私钥的合法持有者。整个过程私钥从未离开你的电脑这就是它安全的根本原因。1.3 “公钥放平台、私钥锁本地”是铁律在理解公钥私钥的工作原理之后有一个原则必须刻在脑子里公钥可以随便分发私钥必须像银行卡密码一样保护。公钥传到 GitHub、Gitee、GitLab、内网 GitLab甚至公开贴到网上都不怕它本来就是给别人看的。但私钥一旦泄露等于别人拿到了一把能冒充你身份的工具可以以你的名义向代码仓库提交代码、拉取私有仓库内容。我见过有人图省事把.ssh目录整个打包发到聊天工具里或者把私钥贴到 GitHub Gist 上这是非常危险的。保存私钥的~/.ssh/id_ed25519或id_rsa文件在 Linux/macOS 上务必设置成600权限在 Windows 上也要保证只有当前用户能访问。2. 环境准备确认 Git 和 OpenSSH 客户端各就各位2.1 三平台通用的检查命令配置 SSH 密钥之前先确认基础环境Git 已安装并且系统里有ssh-keygen命令可用。ssh-keygen是 OpenSSH 套件里的密钥生成工具一般随系统自带或随 Git 一起安装。检查方法是在终端里分别输入git --version ssh-keygen第一条能正常输出类似git version 2.40.1的版本号说明 Git 已装好。第二条如果提示命令找不到说明缺少 OpenSSH 客户端。不同平台处理方式不一样往下看。2.2 WindowsGit for Windows 是一站式方案Windows 上最容易踩的坑是环境变量 PATH 没配好。强烈建议直接安装 Git for Windows它自带 Git Bash、OpenSSH 客户端以及整套 Unix 风格命令行工具。安装时注意一个选项选择 “Use Git from the Windows Command Prompt” 或 “Use Git and optional Unix tools from the Command Prompt”这样git和ssh-keygen才能直接在 CMD 和 PowerShell 里被找到。也用 winget 一条命令装winget install --id Git.Git -e --source winget装完最好重启一次终端再验证git --version。很多人装完 Git 不重开终端环境变量没有刷新然后就跑去问为什么命令找不到这个细节值得留意。Windows 下的 OpenSSH 客户端其实系统也自带在“可选功能”里可以启用 Windows OpenSSH Client。但既然已经装了 Git for Windows直接用它的ssh-keygen就行没必要再折腾系统组件逻辑上更统一。2.3 macOSCommandLineTools 足够macOS 通常自带git和ssh-keygen。如果输入git --version提示需要安装命令行开发者工具会弹窗引导你安装 CommandLineTools也可以手动执行xcode-select --install装完后git、ssh-keygen、ssh-agent全部可用。如果你习惯用 Homebrew 管理工具链也可以brew install git但对 SSH 密钥这件事来说没什么必要。2.4 Linux根据发行版选择包管理器Linux 下如果是 Debian/Ubuntu 系sudo apt update sudo apt install git openssh-client -yFedora / RHEL 系sudo dnf install git openssh-clients -y装完同样验证git --version。Ubuntu 服务器最常遇到的ssh 无法连接问题一部分是服务端没装 openssh-server另一部分是密钥没配对好这在后面的排查章节会详细展开。2.5 顺手把 Git 全局身份和基础行为配好SSH 密钥负责认证“你是谁”但 Git 提交记录里也要留下“你是谁”。这两者不冲突但建议一起配好git config --global user.name Your Name git config --global user.email youexample.com在 Windows 上我还建议多做两个配置。一个是处理中文文件名转义git config --global core.quotepath false不然git status会显示\346\226\207\344\273\266这种八进制转义序列中文路径全变乱码。另一个是换行符处理如果团队统一用 LF可以执行git config --global core.autocrlf input这些配置不直接影响 SSH 密钥但属于 Git 环境初始化的一部分配好之后后续操作顺滑很多。3. 跨平台密钥生成算法选型、命令细节与私钥保护3.1 选 ED25519 还是 RSA 4096ssh-keygen支持多种算法现在最主流的选择是 ED25519 和 RSA。两者对比对比项ED25519RSA 4096密钥长度固定约 256 位可指定常用 4096 位性能快密钥短相对慢密钥长安全性现代密码学足够安全经典方案兼容性好兼容性需要较新的 OpenSSH 和托管平台支持兼容最广包括老服务器适用场景推荐的新项目首选需要兼容旧系统的场景现在 GitHub、Gitee、GitLab 都支持 ED25519所以我的建议非常简单新配置一律用 ED25519。除非你要连接一台内核很旧的服务器或者一些历史遗留的内部 Git 服务才考虑 RSA。3.2 ssh-keygen 命令逐项拆解打开终端执行ssh-keygen -t ed25519 -C your_emailexample.com参数含义-t ed25519指定密钥算法。-C your_emailexample.com给密钥加一个注释通常写你的邮箱方便在托管平台上识别这把密钥是哪台机器的。执行后会有三次交互第一行要求输入保存路径默认是~/.ssh/id_ed25519。如果你想用默认路径直接回车。第二行要求输入 passphrase口令。这是一个额外保护层可以留空直接回车也可以设置一段口令。第三行是再输入一遍确认。生成完成后.ssh目录下会出现两个文件id_ed25519私钥永远不要泄露。id_ed25519.pub公钥等下要复制到托管平台上。3.3 passphrase 到底要不要设passphrase 就像是给私钥加了一层密码保护。即使别人偷走了你的私钥文件不知道 passphrase 也用不了。但这里有个体验上的矛盾如果你设置了 passphrase每次 SSH 连接时理论上都要输入它一次这感觉又回到了输密码的老路。解决办法是配合 SSH Agent 缓存私钥只在开机后第一次使用输一次 passphrase之后自动完成认证。我的建议是设置 passphrase并且让 ssh-agent 帮你记住它。如果完全不设私钥文件一旦泄露就等于城门大开。尤其笔记本容易丢没有 passphrase 的私钥落到别人手里对方可以直接拿去访问你的代码仓库。3.4 Windows、macOS、Linux 生成密钥的差异细节命令本身三个平台通用但有些细节不同Windows 上如果用的是 Git Bash交互体验和 Linux 完全一致。如果你习惯用 PowerShell同样可以运行ssh-keygen但路径显示会是C:\Users\你的用户名\.ssh\id_ed25519。注意 PowerShell 里默认路径中的~也能正常解析。macOS 上生成密钥后很多人的习惯是把公钥直接放进剪贴板cat ~/.ssh/id_ed25519.pub | pbcopyLinux 桌面环境没有 pbcopy老老实实用cat输出再手动复制cat ~/.ssh/id_ed25519.pubWindows 上可以用type %USERPROFILE%\.ssh\id_ed25519.pub或者clip %USERPROFILE%\.ssh\id_ed25519.pubclip命令会把输出内容放到剪贴板很方便。但要注意.ssh目录里如果存在config文件且格式有问题ssh-keygen或ssh命令可能会抱怨bad owner or permissions on C:\Users\...\.ssh\config这在后面的排查章节会专门讲。3.5 私钥文件的权限保护Linux/macOS 上执行chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519.ssh目录的权限别开太大700表示只有你本人能进入目录。私钥文件600表示只有你本人能读写。如果权限设置过宽OpenSSH 会直接拒绝使用这把私钥提示权限不安全。Windows 上无法用chmod达到同样效果需要保证私钥文件不能有Everyone等用户的访问权限。最简单的判断方法是如果 SSH 连接时出现UNPROTECTED PRIVATE KEY FILE的报错就说明文件权限有问题需要调整 ACL。4. 把公钥交给托管平台从 GitHub 到 Gitee、GitLab4.1 GitHub 添加 SSH Key 的操作路径登录 GitHub进入Settings左侧菜单选SSH and GPG keys点击New SSH key。Title 栏写这台机器或这个密钥的用途建议写成ThinkPad-Windows、MacBook-Pro这种你能认出来源的名字。Key type 选Authentication Key新版界面有区分签名密钥和认证密钥认证密钥用于 Git 的 push/pull选 Authentication 就对了。然后把你复制的公钥内容粘贴到 Key 栏。Linux/macOS 上手动复制公钥内容cat ~/.ssh/id_ed25519.pub输出是一整行以ssh-ed25519开头以你的邮箱注释结尾的文本全部复制不要漏行。4.2 Gitee 的公钥配置入口Gitee 是国内常用的代码托管平台入口在右上角头像 →设置→安全设置→SSH 公钥。和 GitHub 的逻辑一致把公钥粘贴到输入框并保存。Gitee 早期某些服务对 ED25519 支持不完善现在基本都兼容了。如果你在 Gitee 用 ED25519 测试连接不通过可以临时生成一把 RSA 密钥试试但在大多数新场景下 ED25519 都没有问题。4.3 GitLab 的配置入口公司内部自建 GitLab 或使用 gitlab.com 的入口在头像 →Preferences偏好设置→ 左侧SSH Keys。粘贴公钥后GitLab 会实时显示这把密钥的指纹信息用于后面对照。同样Key 名称建议写清楚来源。4.4 把本地远程地址从 HTTPS 改成 SSH这一步非常关键。如果你之前是用 HTTPS 地址 clone 的仓库现在配置好 SSH 密钥还得改 remote 地址。在仓库目录下先查看当前地址git remote -v如果输出形如origin https://github.com/yourname/your-repo.git (fetch) origin https://github.com/yourname/your-repo.git (push)说明你还在用 HTTPS需要改成 SSH 地址git remote set-url origin gitgithub.com:yourname/your-repo.gitGitee 对应改成gitgitee.com:yourname/your-repo.gitGitLab 改成gitgitlab.com:yourname/your-repo.git。改完后再次git remote -v确认接下来 push 和 pull 就会走 SSH 协议了。4.5 测试连接每个平台的验证命令配置好公钥并修改 remote 地址后可以单独测试 SSH 认证是否成功GitHubssh -T gitgithub.com第一次连接时会出现The authenticity of host github.com (IP) cant be established. ED25519 key fingerprint is SHA256:DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU. Are you sure you want to continue connecting (yes/no/[fingerprint])?输入yes回车。这个提示的意思是这台主机首次连接OpenSSH 要确认它记录的指纹是否可信。回车后主机指纹会被记录到~/.ssh/known_hosts下次不会再问。连接成功的返回Hi yourname! Youve successfully authenticated, but GitHub does not provide shell access.Gitee 则返回Hello yourname! Youve connected to Gitee.com by SSH successfully!GitLab 返回Welcome to GitLab, yourname!看到类似信息说明 SSH 密钥链路已经通了。如果这一步失败直接跳到第 6 章排查。5. ssh-agent 与多密钥管理一台电脑管多平台账号5.1 ssh-agent 解决什么问题如果你设置了 passphrase每次 SSH 连接都要输入一次显然不可接受。ssh-agent 就是一个帮你保存已解锁私钥的后台进程你先把私钥“加入”它并输入一次 passphrase之后 agent 一直替你持有这把已解锁的私钥后续连接不再要求输入。在配置多个账号时ssh-agent 还有一个隐藏作用当你改动 Git remote 指向不同平台时agent 会提供不同的私钥去尝试认证。为了避免密钥太多导致服务器端“认证次数超限”直接拒绝推荐配合.ssh/config指定每个平台用哪把密钥。5.2 三平台启用 ssh-agent 的差异Windows 的 Git Basheval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519这里有个体验差异每次新开一个 Git Bash 窗口agent 进程都会重新启动私钥需要重新ssh-add。觉得麻烦的话可以在~/.bashrc里加一行eval $(ssh-agent -s)然后让系统每次启动时自动运行一次ssh-add。但这又涉及把 passphrase 自动化的问题比较复杂。macOS 上比较顺手因为 macOS 提供了 Keychain 集成ssh-add --apple-use-keychain ~/.ssh/id_ed25519把私钥加入 Agent 并存在系统钥匙串里之后重启也不用重复输入 passphrase。Linux 桌面环境通常自带 ssh-agent 进程多数桌面登录后就已经在运行。检查是否在运行echo $SSH_AUTH_SOCK如果输出空手动启动eval $(ssh-agent -s)5.3 多密钥场景下的 config 文件写法很多开发者的实际场景是一个 GitHub 账号一个 Gitee 账号可能还有公司内网 GitLab。如果所有平台都用同一对密钥当然没问题但如果你想分开管理就要用到~/.ssh/config。例如本地有两对密钥~/.ssh/id_ed25519_github和~/.ssh/id_ed25519_gitee。编辑~/.ssh/configWindows 下是C:\Users\你的用户名\.ssh\configHost github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github IdentitiesOnly yes Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee IdentitiesOnly yes几个参数的含义Host你在 SSH 命令或 Git remote 里使用的别名。这里直接写github.com就可以匹配gitgithub.com:xxx/yyy.git这种地址。HostName实际连接的主机名一般和 Host 一致。UserSSH 登录用户名Git 托管平台固定为git。IdentityFile指定使用哪把私钥。IdentitiesOnly yes这条很重要。它告诉 SSH 只使用这里指定的私钥不要拿 ssh-agent 里所有私钥轮番尝试能避免不少认证问题。配置完成后后续git push会根据 remote 地址自动找到对应的私钥。5.4 多密钥配置中的常见迷思有人配置了 config发现ssh -T gitgithub.com测试成功但git remote -v明明显示的是gitgithub.compush 时依然报Permission denied (publickey)。这种多半是 config 文件里IdentityFile路径写错了或者私钥文件的权限不对。还有人把Host写成了自己的别名比如Host mygithub然后 remote 地址也改成了gitmygithub:user/repo.git。这也能工作但很多人测试ssh -T gitgithub.com时发现没有走别名规则误以为配置失败。实际上ssh -T gitmygithub才会走该规则注意这个区别。6. 连接报错排查清单从 Permission denied 到 known_hosts6.1 典型报错速查表以下是我在实际排查中遇到最多的几种报错把症状、原因和解决办法整理成了表格报错信息可能原因处理方式Permission denied (publickey)公钥没添加到托管平台或本地私钥路径不对检查公钥是否已添加用ssh -vT gitgithub.com看详细日志Host key verification failedknown_hosts 里记录的主机指纹和服务器实际指纹不一致用ssh-keygen -R github.com清除旧记录后重连Bad owner or permissions on C:\Users\...\.ssh\configWindows 下 config 文件权限设置了过多用户用 icacls 或 GUI 修正权限只保留当前用户完全控制gitgithub.com: Permission denied且-vT显示no mutual signature algorithm服务器或客户端不支持 RSA/SHA-1 老算法换 ED25519 密钥或临时启用ssh-rsa兼容ssh: connect to host github.com port 22: Operation timed out网络策略封了 22 端口换 GitHub 的 443 端口的 SSH 服务或换 HTTPS 方式6.2 Windows 上 Bad owner or permissions 的完整修复流程这个报错在 Windows 上非常经典。报错长这样bad owner or permissions on c:\users\你的用户名\.ssh\config问题出在.ssh目录通常是config文件的访问权限被设置得过于开放OpenSSH 为了安全直接拒绝读取。修复流程需要打开文件属性面板或用 icacls 命令。先说命令行方式以管理员身份打开 PowerShellicacls C:\Users\你的用户名\.ssh\config /inheritance:r icacls C:\Users\你的用户名\.ssh\config /grant:r $($env:USERNAME):F第一条命令移除继承的所有权限第二条命令只给当前用户完全控制权。执行完重新测试 SSH 连接通常就恢复正常。如果不想用命令打开资源管理器找到.ssh下的config文件右键 → 属性 → 安全 → 高级先改所有者为自己然后禁用继承再添加自己并授予完全控制权限移除其他所有用户条目。这个坑的本质是 Windows 文件系统 ACL 权限模型和 Unix 的chmod 600完全不同所以很多从 mac/Linux 切到 Windows 的开发者会一头雾水。知道原因后就不慌了。6.3 Linux/Ubuntu 上 SSH 无法连接的排查思路热词里“ubuntu ssh无法连接”也是高频问题。如果本地密钥配置没问题但连接 Linux 服务器报错排查思路应该是先确认服务端 SSH 服务是否在运行sudo systemctl status ssh没运行就启动并设成开机自启sudo systemctl enable --now ssh再检查端口是否被防火墙拦截sudo ufw status通常需要放行 22 端口sudo ufw allow OpenSSH然后确认服务端~/.ssh/authorized_keys文件里有没有写入你的公钥。文件权限必须是chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keysauthorized_keys权限过宽是服务端拒绝公钥登录的常见原因。修改后重启 SSH 服务sudo systemctl restart ssh如果还是不行打开服务端 SSH 调试日志看sudo journalctl -u ssh或/var/log/auth.log多半能在日志里看到明确原因。6.4 老系统兼容性RSA、SHA-1 与 known_hosts 清理有些老服务器生成的是 RSA 密钥而新版本 OpenSSH 默认关闭了ssh-rsa这种基于 SHA-1 的签名算法于是连接时报no mutual signature algorithm。临时解法是在.ssh/config对应 Host 下加两行Host old-server HostName 192.168.1.10 User root HostKeyAlgorithms ssh-rsa PubkeyAcceptedAlgorithms ssh-rsa但这只是兼容旧机器的过渡手段新环境建议还是用 ED25519。known_hosts 文件是 OpenSSH 用来记录服务器指纹的。如果你重装过服务器系统或服务器换了主机密钥再连接时就会报Host key verification failed。这时候不用慌也不是被中间人攻击绝大多数情况就是服务器指纹变了。清除旧记录ssh-keygen -R github.com或者指定清除某端口ssh-keygen -R [github.com]:443清理后重新连接按提示输入yes就能继续。6.5 网络端口被限制时怎么办某些办公网络会屏蔽 22 端口导致 SSH 连接超时。GitHub 官方提供了 443 端口的 SSH 服务配置方法是在~/.ssh/config中Host github.com HostName ssh.github.com Port 443 User git然后测试ssh -T gitgithub.com只要 443 端口可访问就能正常走 SSH 认证。这是纯技术层面的替代方案适用于所有标准 SSH 场景。7. 配置完成不等于万事大吉几个值得养成的习惯密钥配置好之后有些细节值得在日常使用中注意。第一如果你在使用多台电脑每一台机器上都要单独生成一对密钥然后把公钥分别添加到托管平台。不要试图把所有机器的私钥统一成一把那样一旦某台机器丢了你必须第一时间到托管平台删除对应公钥否则风险极大。每台机器维护独立的密钥对发现哪台机器出问题就单独吊销哪一把控制风险面。第二.ssh目录里最好放一个README或者至少用文件名来区分每把密钥属于哪台机器。VSCode 连接 SSH 远程服务器、批量登录多台服务器这类场景密钥多了之后如果不做区分很容易拿错私钥连错机器浪费时间。第三定期检查托管平台上的 SSH Keys 列表及时删掉已经不再使用的机器。换电脑是家常便饭但很多人换完电脑就把旧机器的公钥留在平台上一辈子这些“僵尸公钥”其实是不小的安全隐患。最后分享一个小技巧如果平时习惯用 VSCode 远程开发SSH 密钥配置好后Remote-SSH扩展可以直接使用本机的~/.ssh/config你为 Git 配置的多密钥规则同样适用于远程开发连接。也就是说同一套配置既管 Git 代码推送又管远程服务器登录一劳永逸。这也是我为什么一直强调密钥统一管理的原因——配一次长期受益值得认真对待。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价