1. 先聊清楚:GitLab到底是什么,为什么每个团队都在用
第一次接触GitLab的人,十有八九会把Git、GitHub和GitLab混成一锅粥。我当年也经历过这个阶段,对着终端里的git命令一脸懵,完全搞不清楚它和网页上那个代码仓库到底是什么关系。这里先用最直白的话把这三者的关系捋顺。
Git本身是一个分布式版本控制系统,它负责在你本地跟踪代码的每一次改动,记录谁在什么时候改了什么文件。它不依赖于任何服务器,你甚至可以在断网状态下用Git管理自己的项目。而GitLab和GitHub都是基于Git的代码托管平台,它们把本地的Git仓库同步到远程服务器上,提供网页端的代码浏览、分支管理、合并请求、问题跟踪等功能。如果拿拍照来类比,Git是相机本身,负责按下快门记录瞬间,而GitLab和GitHub是相册,让你把照片洗出来、分类归档、分享给别人看。
GitLab和GitHub最大的区别在于:GitHub是SaaS服务,代码托管在人家服务器上,私有仓库数量有限,而且很多企业级功能要付费;而GitLab是开源软件,你可以把它安装在自己的服务器上,数据完全由自己掌控。这就是为什么大量公司会选择在内部搭建一套GitLab,代码不出内网,安全可控,同时还能利用GitLab自带的CI/CD流水线能力实现自动化部署。
标题里提到的“ssh key生成及使用”是使用GitLab绕不开的第一步。很多新手在克隆代码时习惯了输入用户名密码的HTTPS方式,但一旦涉及自动化部署、频繁pull/push、或者公司强制要求安全认证,SSH Key就成了必经之路。这篇内容就围绕GitLab的基本使用方式展开,重点带你走通SSH Key的生成、配置、排查全流程,挨个把坑踩平。
2. 为什么强烈推荐用SSH Key连GitLab
2.1 HTTPS和SSH两种连接方式,到底差在哪
在你把一个远程仓库克隆到本地之前,Git需要确认“你确实是这个项目的成员”。GitLab支持两种认证方式:
第一种是HTTPS方式,链接长这样:https://gitlab.com/yourgroup/project.git。每次执行git push或者git pull的时候,Git都会弹出窗口让你输入GitLab的用户名和密码(实际是Token或个人访问令牌)。如果装了Git的凭据管理器,它能帮你把密码记住,不用每次手动输,但这种方式本质上还是“账号密码+服务器验证”。
第二种就是SSH方式,链接长这样:git@gitlab.com:yourgroup/project.git。它用的是公钥加密和私钥签名的认证机制,你只需要提前把公钥配置到GitLab账号里,之后的每一次连接都走密钥自动认证,不会再弹出任何密码输入框。
两种方式的体验差异,就好比一个是每次进小区都要在门卫那儿登记身份证,另一个是刷脸进门,一次录入,之后畅通无阻。
2.2 SSH Key的工作原理,用生活例子讲明白
SSH Key是一对非对称加密钥匙,包含一个私钥和一个公钥。私钥保存在你本地电脑上(默认在~/.ssh/id_ed25519),绝对绝对不能泄露;公钥则是一串明文文本,你可以大方地把它配置到GitLab上。
它的认证过程是这样的:当你向GitLab发起SSH连接时,服务器会生成一段随机数据发送给你,你的SSH客户端用私钥对这段数据进行签名,然后把签名结果发回给服务器。服务器用你预先配置的公钥验证这段签名,如果验证通过,说明“持私钥的人确实是公钥的主人”,于是认证成功。
这个机制和保险柜的原理很像:公钥是保险柜的锁,任何人都可以看到锁长什么样,但只有拿着正确钥匙(私钥)的人才能打开柜子。你不需要把钥匙交给别人,只需要让服务器记住“这把锁认哪把钥匙”,后续的身份验证就全部自动化了。
2.3 为什么说配置SSH Key是开发效率的分水岭
在实际开发中,SSH Key的优势体现在几个非常具体的场景里。
第一个场景是日常开发中的高频push操作。用HTTPS方式如果没配凭据管理器,每次都输Token不仅烦,还容易输错;配了凭据管理器,多账号切换又容易出错。SSH方式一劳永逸,绑定一次,以后无感操作。
第二个场景是CI/CD自动化。Jenkins、GitLab Runner这类自动化工具在拉取代码时,需要一个无人值守的认证方式。账号密码会过期、Token轮换需要改配置,而SSH Key只要不被吊销,就能一直稳定工作。很多团队最初的自动化构建跑不起来,排查到最后发现就是认证方式选错了。
第三个场景是安全合规。私钥不出本地机器,公钥才传给服务器,整个认证链条里没有明文密码在网络中传输,安全等级明显高于用户名密码。
3. SSH Key生成实操:从零到一
3.1 生成之前,先看看自己有没有“老钥匙”
在动手生成新Key之前,我强烈建议你先检查一下本地是否已经存在SSH Key。很多新手不查直接一路回车,生成了新的密钥对,然后把公钥配置到GitLab上,结果发现之前配的GitHub、服务器或者其他平台的连接全断了——因为新的密钥对覆盖了旧的。
打开终端,执行下面这个命令:
ls -al ~/.ssh这条命令会列出.ssh目录下的所有文件。如果你看到id_rsa、id_rsa.pub、id_ed25519、id_ed25519.pub这类文件,说明本地已经有一对密钥了。其中.pub后缀的是公钥,没有后缀的是私钥。
此时你有两个选择:
- 如果之前生成的Key还在正常使用,完全可以直接沿用,跳到下一节把公钥配置到GitLab即可。
- 如果确定这些Key已经废弃了,或者你就是想给GitLab单独生成一把独立的Key(强烈推荐,后面会讲原因),那可以跳过旧文件,用另一个名字生成新Key。
3.2 正式生成:选择合适的加密算法和管理口令
现代GitLab环境我推荐直接生成ED25519类型的密钥,命令如下:
ssh-keygen -t ed25519 -C "你的邮箱地址"-t ed25519指定密钥类型为Ed25519,这是一种比传统RSA更安全、性能更好、密钥长度更短的算法。-C后面的备注信息会写进公钥文件的末尾,方便你在GitLab服务器上识别这把Key是哪个设备、哪个用途的,比如-C "work-laptop"或者-C "root@ubuntu-server"。
执行命令后,终端会提示你输入保存密钥的文件路径:
Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519):这里我建议不要直接回车用默认文件名,而是给它一个能区分场景的名字,比如~/.ssh/id_ed25519_gitlab。原因在于,如果你同时使用GitHub、Gitee、公司GitLab等多个代码平台,每个平台用一把独立的Key,后续通过配置文件来分流,会省去很多管理上的麻烦。这个方案我下面会详细展开。
接着系统会询问是否设置passphrase:
Enter passphrase (empty for no passphrase): Enter same passphrase again:passphrase是给私钥再加一层密码保护。即使有人拷贝了你的私钥文件,没有passphrase也无法使用。但代价是每次使用SSH Key时都要输一次密码,体验稍打折扣。
我的建议是:个人开发机可以留空,方便快捷;公司配发的电脑或者有高安全要求的服务器,务必设置passphrase。还有一个折中方案是用ssh-agent把解锁过的私钥加载到内存里,设置一个较长的存活时间,既安全又不用反复输密码。
生成完成后,再次查看.ssh目录,你会看到两个新文件:
id_ed25519_gitlab # 私钥,留在本地 id_ed25519_gitlab.pub # 公钥,可以给别人千万记住:私钥文件权限应该是600,公钥文件权限是644。如果你发现权限不对,可以执行chmod 600 ~/.ssh/id_ed25519_gitlab修正。Linux和macOS对密钥文件权限很敏感,权限太开放直接拒绝使用。
3.3 查看公钥内容的正确姿势
公钥文件就是一段纯文本,你可以用任何文本编辑器打开。终端里查看最方便:
cat ~/.ssh/id_ed25519_gitlab.pub输出内容长这样:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINxxxxxxxxxxxxxxxxxxxxx work-laptop从ssh-ed25519开头,到最后的备注信息结束,这一整行都是公钥。复制的时候要完整复制,不能漏掉任何字符,尤其不能漏掉开头的算法标识和结尾的注释部分。很多人在这一步翻车,复制的时候只复制了一部分,导致配置到GitLab上之后一直认证失败。
4. 把公钥配置到GitLab:3分钟搞定
4.1 在GitLab网页上添加公钥
登录GitLab后,点击右上角的头像,在下拉菜单中选择“Preferences”(偏好设置),这是旧版GitLab的入口。新版GitLab中,这个菜单可能叫“Edit Profile”或者直接显示你的用户名。
在偏好设置页面左侧菜单中找到“SSH Keys”选项(中文界面叫“SSH密钥”)。点击进入后,你会看到一个表单,包含三个字段:
- Key:粘贴你刚才复制的完整公钥内容
- Title:给这把Key起个名字,方便识别,建议格式是“设备名-用途”,例如
office-pc-main、home-macbook、ci-runner - Expiration date:过期日期,可选。如果不填就永不过期。出于安全考虑,公司服务器或者CI Runner这类长期使用的Key建议设置一个定期轮换的过期时间,比如一年
填写完成后点击“Add key”绿色按钮,页面刷新后,你的公钥就出现在密钥列表中了。
4.2 验证SSH连接是否正常
配置完公钥后,别急着克隆代码,先验证一下连接是否打通:
ssh -T git@gitlab.com如果你是连接自己公司内网搭建的GitLab,域名换成对应的内网地址,比如:
ssh -T git@gitlab.yourcompany.com第一次连接时,系统会提示确认远程主机的指纹信息:
The authenticity of host 'gitlab.com (xxx.xxx.xxx.xxx)' can't be established. ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxx. Are you sure you want to continue connecting (yes/no)?这里输入yes并回车,之后系统才会输出连接结果。如果一切正常,你会看到类似这样的欢迎信息:
Welcome to GitLab, @yourusername!看到这行字,就说明SSH认证已经全部打通,接下来就能愉快地克隆和推送代码了。
4.3 一次配置,管理多个平台密钥的进阶方案
很多开发者的实际情况是:GitHub有自己的项目,公司GitLab有业务代码,可能还有一台自己买的云服务器。每个平台需要用不同的SSH Key,以免一个私钥泄露导致所有平台全部沦陷。
这时候就需要在~/.ssh/config文件里做分流配置。如果.ssh目录下没有这个文件,手动创建一个即可。配置内容示例:
# GitHub Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github # 公司GitLab Host gitlab.yourcompany.com HostName gitlab.yourcompany.com User git IdentityFile ~/.ssh/id_ed25519_gitlab # 个人云服务器 Host myserver HostName 203.0.113.10 User root IdentityFile ~/.ssh/id_ed25519_server配置完成后,SSH客户端会根据你连接的主机名自动匹配对应的私钥,互不干扰。这也是我前面强调要为不同平台生成独立Key的原因。
5. SSH Key配置完成后,日常开发的核心操作
5.1 克隆代码:SSH链接和HTTPS链接的区分
在GitLab项目主页点击“Clone”按钮,会弹出两个Tab:Clone with HTTPS和Clone with SSH。如果你完成了上面的SSH配置,就直接复制SSH链接。
举个例子,HTTPS链接长这样:
https://gitlab.com/yourgroup/project.gitSSH链接长这样:
git@gitlab.com:yourgroup/project.git克隆命令完全一样:
git clone git@gitlab.com:yourgroup/project.git区别在哪?HTTPS克隆下来之后,每次git push可能都要验证身份;SSH克隆下来之后,push操作全程静默完成,不需要手动输入任何凭据。这个差异在日常使用中感知非常明显。
5.2 一次完整的代码提交流程
配合SSH Key,一次标准的代码提交推送流程非常顺畅。假设你已经克隆了项目,并且创建了一个新功能分支:
# 1. 查看当前状态 git status # 2. 添加所有改动到暂存区 git add . # 3. 提交到本地仓库,附带清晰的提交信息 git commit -m "feat: 添加用户登录功能" # 4. 推送本地分支到远程仓库 git push origin feature-login推送完成后,你去GitLab网页上刷新项目页面,就能看到远程分支已经更新。之后通常是在网页上发起一个Merge Request(合并请求),邀请同事评审代码,评审通过后合并到主分支。
5.3 分支管理:创建、切换、合并、删除
在实际团队协作中,分支操作频率很高。日常常用的命令如下:
创建并切换到一个新分支:
git checkout -b feature-xxx切回主分支:
git checkout main把功能分支合并到当前分支:
git merge feature-xxx推送本地分支到远程并设置上游跟踪:
git push -u origin feature-xxx删除本地分支:
git branch -d feature-xxx删除远程分支:
git push origin --delete feature-xxx这些命令和是否配置SSH Key没有直接关系,但SSH连接让整个流程更顺畅,特别是频繁push、pull切换分支的时候,不用反复验证身份,体验上的提升非常明显。
5.4 解决日常开发里最让人头疼的合并冲突
冲突是多人协作里完全绕不开的问题。两个人都改了同一个文件的同一段代码,Git无法自动合并,只能让人工介入。
假设你在feature-login分支上修改了Login.java,同事在主分支上也改了同一个文件的同一个方法,合并时就会出现冲突。
解决方案是:先把远程主分支的最新代码拉取下来,然后在本地解决冲突。
# 1. 切到主分支,拉取最新代码 git checkout main git pull origin main # 2. 切回功能分支 git checkout feature-login # 3. 把主分支合并到功能分支,此时可能产生冲突 git merge main如果冲突产生了,Git会在冲突文件中用<<<<<<< HEAD和>>>>>>> main这样的标记把两边的内容标识出来。这时候用VS Code或者其他编辑器打开文件,逐处确认保留哪一边的代码、还是两边都保留并手动整合。解决完所有冲突后:
git add . git commit -m "merge: 解决与主分支的冲突" git push origin feature-login这几十行命令覆盖了本地日常开发中最核心的操作流程,足够应付绝大多数场景。
6. 踩坑经验:SSH Key使用中高频出现的几个问题
6.1 Permission denied (publickey)
这是最经典的报错,出现频率堪称SSH问题之王。它表示服务器验证公钥失败,可能性很多:
- 公钥粘贴的时候漏了字符,或者用截图OCR识别导致乱码
- 私钥路径配置错误,SSH客户端根本找不到对应的私钥
- 本地
.ssh目录下有多个私钥,但第一个加载的私钥不是GitLab对应的那把 - GitLab上的公钥被管理员删除了或者过期了
排查思路是先用ssh -T git@gitlab.com查看详细错误信息,再用ls -al ~/.ssh确认密钥文件是否存在。如果用多个私钥,优先推荐配置~/.ssh/config文件指定IdentityFile。
6.2 Host key verification failed
这个报错在网络环境变化或服务器重建后经常出现。原因是本地的~/.ssh/known_hosts文件里还保存着旧的主机指纹,而服务器端的指纹已经变了,SSH发现两者对不上,就拒绝继续连接。
解决方案很简单,用命令删除旧指纹:
ssh-keygen -R gitlab.com然后重新连接,按提示接受新的指纹即可。如果你连接的自建GitLab端口不是22,记得额外指定端口:
ssh -T -p 2222 git@gitlab.yourcompany.com在克隆代码时,非标准端口写法也不同:
git clone ssh://git@gitlab.yourcompany.com:2222/yourgroup/project.git6.3 同一个仓库,为什么push还是提示输密码
这种情况往往是因为克隆的时候用了HTTPS链接,而不是SSH链接。你手上的SSH Key就算配置得再完美,HTTPS连接也完全不会使用它。
检查方式是命令:
git remote -v如果输出里remote地址以https://开头,说明当前仓库用的是HTTPS方式。改成SSH方式:
git remote set-url origin git@gitlab.com:yourgroup/project.git之后再push,就会走SSH认证,不会再输密码。
6.4 换新电脑后,原来的SSH Key怎么办
这是一个高频但很多人操作错误的场景。有人直接把旧电脑的私钥文件拷贝到新电脑,这个做法可行但有风险。更规范的做法是:
- 旧电脑上如果可能,把旧Key从GitLab上删掉,防止私钥泄露后被人利用
- 在新电脑上生成全新的Key,把新公钥再添加回GitLab
如果你的工作同时涉及GitHub和GitLab,记得每个平台都用独立的Key,不要图省事共用一把,这样即使某个平台被打穿,其他平台的代码仓库还是安全的。
6.5 常见问题速查表
我把高频问题和对应解法整理成一张表,方便收藏备查:
| 问题现象 | 可能原因 | 快速解法 |
|---|---|---|
| Permission denied (publickey) | 公钥未配置或私钥路径不对 | 重新添加公钥,检查IdentityFile配置 |
| Host key verification failed | 服务器指纹变更 | ssh-keygen -R gitlab.com后重连 |
| push仍提示输密码 | 仓库用的是HTTPS地址 | git remote set-url origin改SSH地址 |
| 多个Key对不上号 | 没有配置~/.ssh/config | 按Host指定各自的IdentityFile |
| 连接超时或卡住 | 网络不通或端口被防火墙拦截 | 检查22端口连通性,或改用443端口 |
| GitLab提示Key已过期 | Key设置了Expiration date | 在GitLab上更新Key并重新配置 |
6.6 几个独家避坑小技巧
第一,~/.ssh目录的权限一定要正确。私钥文件权限如果是664或777,SSH会直接拒绝使用,并提示Permissions 0664 for 'id_ed25519' are too open。新生成的文件默认权限是对的,但如果从别人那儿拷贝了密钥文件过来,这个坑特别容易踩。
第二,CI/CD环境里使用SSH Key时,不要把私钥直接硬编码到gitlab-ci.yml文件里,而应该使用GitLab的CI/CD变量(Settings -> CI/CD -> Variables)来存储私钥内容,流水线里用echo "$SSH_PRIVATE_KEY"注入到环境变量中,避免密钥泄露到代码仓库。
第三,GitLab管理员在后台能看到每个账号加载了哪些Key,建议定期梳理账号下的密钥列表,及时删掉已经不再使用的设备Key。我给公司的建议是每半年做一次密钥巡检,宁可让同事重新配置一遍,也不能留下无人认领的“僵尸Key”。
7. 从SSH Key往后走:GitLab的更多可能性
7.1 当SSH Key遇到CI/CD自动化
很多团队用GitLab不只是为了管代码,还会借助GitLab CI/CD实现自动构建和部署。流水线里Runner在拉取代码的时候,用的就是SSH认证。
简单说下流程:GitLab Runner是一个独立服务,它可以从GitLab服务器接收构建任务。Runner执行任务时,需要把代码仓库拉取到执行机,这时候Runner机器上就要配置能访问对应项目的SSH Key。
踩过的坑是:Runner的SSH Key不能和个人开发机的Key共用,应该单独生成一把独立的Key,并且把公钥添加到一个专门为CI创建的GitLab账号上,或者用Deploy Key的方式只授权某个特定的仓库。否则一旦Runner的执行机被入侵,你的个人GitLab账号也会跟着遭殃。
7.2 用Deploy Key实现仓库级别的访问控制
GitLab提供了一种叫Deploy Key的功能,它绑定的是仓库而不是个人账号。也就是说,你可以为某一个特定仓库单独生成一对Key,公钥配置到仓库的Settings -> Repository -> Deploy Keys中。这样CI Runner或者某台服务器只能访问这一个仓库,即使密钥泄露,攻击者也进不了你的个人账号和其他项目。
这是我在实践中最推荐的CI认证方案,安全边界非常清晰。
7.3 本地多账号场景的最终解法
如果你手里同时维护着GitHub、公司GitLab、个人GitLab等多个代码平台,前面提到的~/.ssh/config方案是目前最优雅的解法之一。我再给出一个常见配置片段:
Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitlab.company.com HostName gitlab.company.com User git IdentityFile ~/.ssh/id_ed25519_company Host gitlab.com HostName gitlab.com User git IdentityFile ~/.ssh/id_ed25519_personal配置完成后,无论你连接哪个平台,SSH都会自动选择对应的私钥,完全无感切换。这个方案配合SSH Key使用,基本可以覆盖开发者日常工作中的绝大多数认证场景。
8. 关于SSH Key安全,最后想多说几句
SSH Key是本地机器和GitLab之间的唯一身份凭证,私钥一旦泄露,别人就能登录你的GitLab账号,拉取你所有的私有仓库,甚至以你的名义推送恶意代码。这个后果非常严重,因为代码仓库是公司最核心的资产之一。
几个安全习惯强烈建议养成:
私钥不要通过即时通讯工具、邮件或网盘传输。如果需要在新电脑上配置,请在新电脑上现场生成新Key,不要跨机器拷贝私钥文件。
定期检查GitLab账号里的Key列表,删除不再使用的设备Key。特别是离职员工的设备,管理员要及时清除。
可以给Key设置Expiration date。虽然到期续期稍微麻烦一点,但这个麻烦是值得的,它能保证即使密钥被泄露,也只是一个短期有效的泄漏。
执行重要操作之前,先确认一下自己当前用的是哪把Key。命令行可以快速查看:
ssh -T git@gitlab.com如果输出里的用户名不是你以为的那个人,那就要立刻停下来排查,千万别继续操作。
我在实际维护公司GitLab的过程中,遇到过太多因为SSH Key配置不当引发的生产事故:有开发者的私钥泄露到公开仓库导致代码被爬走,有CI Runner因为Key过期导致整条流水线崩溃,还有同事把多个平台的Key混用导致权限混乱。这些问题一旦发生,排查起来往往比直接配置还要费时。所以,宁可在一开始多花十分钟把Key管理好,也别等出了问题再回头补救。SSH Key这个东西,配置一次,受益几年,但前提是你真的把它当回事儿来对待。