很多人一开始接触GitLab都有个误区:以为装好了GitLab就等于装好了Git,或者说Git自带在这套服务里。实际完全不是这么回事。Git是一个分布式的版本控制工具,跑在你本地或者任意一台服务器上的命令行工具;GitLab是一个围绕Git搭建的Web协作平台,提供仓库管理、合并请求、CI/CD这些能力。这两者一个是发动机,一个是整车,互相配合但不能互相替代。
这篇文章我会围绕Linux环境下Git和GitLab的完整安装过程,把每一步为什么要这样做、背后是什么逻辑、哪些坑我踩过,全部摊开来讲。文中所有命令我都基于Ubuntu 22.04 LTS实测过,CentOS / Rocky Linux的差异点我会单独标注。无论你是刚入行的后端开发者,还是要给团队搭一套内部代码管理平台的运维,这篇都能给你一个可以照着抄的作业。
1. 先搞懂几个核心概念,免得装完一脸懵
1.1 Git和GitLab到底什么关系
Git是一个命令行工具,职责只有一个:管理代码的版本历史。你在本地仓库里执行git init、git add、git commit,所有操作都发生在本机,不需要任何服务端。GitLab则是把Git仓库托管到一台中央服务器上,让团队多个人可以拉取、推送、协作,同时提供图形化界面、权限控制、代码审查流程。
用个生活化的类比:Git是你家里的个人账本,GitLab是银行柜台。你可以在自家账本上记账,账本不会消失,但别人看不到;你存进银行,别人就能通过合规流程存取,还有交易流水、对账单这些增值服务。所以安装顺序一定是先装Git,再装GitLab——虽然GitLab安装包会自带一个精简的Git运行时用于内部操作,但你在服务器上直接操作仓库时,系统环境里的Git版本才是关键。
1.2 版本选择:GitLab CE vs EE,以及安装方式
GitLab有两个版本:Community Edition(社区版,CE)和Enterprise Edition(企业版,EE)。CE免费,功能上已经覆盖绝大多数中小团队需求,像分支保护、合并请求审批、基础的CI/CD都有。EE多了LDAP高级映射、审计事件、多个K8s集群集成这类偏企业管理的能力,普通团队基本用不上。
安装方式主要有三种:
- Omnibus包安装:官方推荐的打包方式,把Ruby、PostgreSQL、Redis、Nginx等所有组件打包成一个安装包,一条命令装完,运维最简单。
- 源码安装:理论上灵活,实际是噩梦。依赖几十个组件,版本还互相打架,我试过一次就放弃了,除非你有极强的定制需求,否则别碰。
- Docker安装:省事,但数据卷映射、网络模式、升级时的数据迁移都有额外复杂度,而且单机直接装Omnibus的性能更好。
这篇教程选择的是Omnibus包安装,这也是官方文档里最主推、社区案例最多的方案。后面涉及的所有路径、命令、配置文件格式都基于此。
2. 环境准备:装之前花10分钟,省得后面折腾一天
2.1 我推荐的服务器配置选型
很多教程跳过环境规划直接给命令,这是最坑人的。GitLab是全家桶服务,PostgreSQL、Redis、Sidekiq、Puma这些进程全部常驻内存。我见过有人在1核1G的云服务器上硬装GitLab,结果装完界面都打不开,后台报OOM(内存溢出)错误,查了半天不知道怎么回事。
如果只是自己练手或个人使用,建议至少2核4G内存。团队使用(10人以上),建议4核8G起步。Swap也建议开一下,哪怕手动建一个4G的swap文件,关键时刻能救命。磁盘方面,SSD是硬性要求,GitLab对IOPS很敏感,机械盘在写仓库时会卡到怀疑人生。
先检查系统信息:
free -h nproc cat /etc/os-release df -h2.2 系统镜像源更新与基础依赖
安装任何东西之前,先把系统的软件源更新到最新。腾讯云、阿里云这些国内服务器通常自带内部镜像源,直接用就行。如果在海外服务器或者纯内网环境,保持官方源也可以。
sudo apt update && sudo apt upgrade -yUbuntu系统下,安装必要的基础工具链:
sudo apt install -y curl wget git vim ca-certificates perl openssl这些包里面最重要的是ca-certificates,没有它后续访问HTTPS下载源会报证书错误,这个坑我踩过不止一次。
2.3 配置主机名与hosts解析
GitLab安装时会以主机名作为默认访问地址。建议提前规划好对外访问的域名,比如git.example.com。如果没有域名,也可以直接用服务器的IP地址,但后面配置HTTPS证书时会麻烦很多。
修改主机名:
sudo hostnamectl set-hostname gitlab-server echo "gitlab-server" | sudo tee /etc/hostname同时确认/etc/hosts里有一条本机解析记录,不然有些组件在启动时会因为解析不到主机名报错。
echo "127.0.0.1 gitlab-server" | sudo tee -a /etc/hosts这一步看起来不起眼,实际价值很大:GitLab内部的Gitaly、Puma等组件之间通信时都会走主机名解析,如果hosts配置不对,启动日志里会出现一堆“Connection refused”或者“Cannot resolve host”。
3. 安装Git:两种方式,一个推荐一个备用
3.1 方式一:apt直接安装(推荐大多数人用)
Ubuntu 22.04自带的软件源里Git版本大概是2.34,对于绝大多数场景完全够用。安装命令:
sudo apt update sudo apt install -y git验证版本:
git --version git config --global init.defaultBranch main git config --global user.name "你的名字" git config --global user.email "you@example.com"这里特别提一下init.defaultBranch这个配置。Git默认的初始分支名是master,但GitHub和GitLab新建仓库时普遍用main。改这个配置不是为了跟风,而是为了少踩一个坑:如果本地仓库默认分支是master,而GitLab上新建项目默认分支是main,第一次推送时就会出现“远端没有匹配分支”或需要手工设置上游的麻烦。提前统一分支名,省掉这些沟通成本。
3.2 方式二:源码编译安装(老版本系统的解决方案)
如果你的系统是CentOS 7或者更老的Ubuntu,系统自带的Git版本可能停留在1.8或者2.0,有些GitLab功能需要更高版本的Git客户端才能正常操作(比如部分合并请求的底层命令依赖新版filter-branch)。这时候建议自己编译安装最新版。
先下载源码包,以2.45.2为例(实际版本可以到Git官网查当前最新版):
cd /tmp wget https://github.com/git/git/archive/refs/tags/v2.45.2.tar.gz tar -zxvf v2.45.2.tar.gz cd git-2.45.2编译前安装依赖:
sudo apt install -y make gcc libcurl4-openssl-dev libexpat1-dev gettext zlib1g-dev libssl-dev然后编译安装:
make prefix=/usr/local all sudo make prefix=/usr/local install验证是否生效:
hash -r git --version这里要留意一个细节:源码编译安装的Git默认会装到/usr/local/bin,而系统自带的旧版在/usr/bin。如果git --version显示还是老版本,说明PATH里/usr/bin排在/usr/local/bin前面,执行which git查看路径,必要时把export PATH=/usr/local/bin:$PATH写进/etc/profile。
3.3 安装后立刻要做的三件事
很多教程装完Git就急着装GitLab,我建议先花两分钟把Git的全局配置弄利索,尤其是如果你在服务器上不止一次地要把代码推到远端仓库的话,这些配置能避免大量重复劳动。
第一,配置SSH密钥:
ssh-keygen -t ed25519 -C "you@example.com"一路回车生成默认密钥。然后把公钥加到GitLab的用户设置里(后面装完GitLab会用到)。
第二,配置autoCRLF相关的换行符行为。跨平台协作的项目里,Windows和Linux的换行符差异一直很讨厌:
git config --global core.autocrlf input第三,配置push默认行为:
git config --global push.default simple这个配置让git push只会推送当前分支到同名的远端分支,避免误推所有分支。
4. 安装GitLab CE:一步一步走到能打开页面
4.1 下载并配置GitLab软件源
GitLab官方提供的是安装脚本,但更可控的做法是自己添加软件源然后手动安装。以Ubuntu 22.04为例:
cd /tmp curl -LO https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh sudo bash script.deb.sh这个脚本做了两件事:把GitLab的GPG公钥导入系统、在/etc/apt/sources.list.d/下创建gitlab_gitlab-ce.list文件。国内服务器如果下载慢,可以把源地址里的packages.gitlab.com替换成国内镜像站的地址,再把deb路径对应用上。
软件源配置好之后,更新索引并安装:
sudo apt update sudo apt install -y gitlab-ce安装包比较大,大概600MB左右,需要一点耐心。安装完成后会提示你下一步需要执行sudo gitlab-ctl reconfigure。
4.2 修改external_url配置
这一步是整个安装过程最关键的一步。GitLab安装完成后默认的访问地址是http://gitlab-server,这个地址是准备阶段主机名的产物。如果要改成自己的域名或者服务器IP,需要修改主配置文件:
sudo vim /etc/gitlab/gitlab.rb找到这行:
external_url 'http://gitlab.example.com'改成你自己的地址:
external_url 'http://gitlab.example.com'这里的协议头决定了GitLab内部Nginx是走HTTP还是HTTPS。如果你要配HTTPS,这里直接写成https://gitlab.example.com,然后再配证书,GitLab会自动处理内部的TLS终止。
修改完后执行重配置:
sudo gitlab-ctl reconfigurereconfigure这个过程会做很多事:生成所有组件的配置文件、初始化数据库、启动所有服务。第一次跑需要3到5分钟,后面每次改配置再跑就快多了。
4.3 首次登录:干掉默认的root密码
GitLab首次启动时会为root用户生成一个临时密码,存放位置:
sudo cat /etc/gitlab/initial_root_password如果这个文件不存在,说明你的GitLab版本较新,临时密码不会持久化写入文件,需要通过另一个方式重置:
sudo gitlab-rails runner "user = User.find_by(username: 'root'); user.password = '新密码'; user.password_confirmation = '新密码'; user.save!"用浏览器访问配置好的external_url地址,用root用户登录,系统会强制要求修改密码。建议一登录就改,因为GitLab的root账号等同于整个平台的管理员权限,默认密码留在文件里总归不踏实。
4.4 验证核心服务状态
GitLab装好之后,用这个命令查看所有组件状态:
sudo gitlab-ctl status正常情况下列表里会有run: postgresql、run: redis、run: gitaly、run: puma、run: sidekiq、run: nginx这些关键条目。如果某个组件显示down,先看日志:
sudo gitlab-ctl tail这个命令会实时输出所有组件的日志,排查问题时的第一利器。另外也建议顺手看看端口监听情况:
sudo ss -lntp | grep -E '80|443|8080|5432'GitLab的Nginx默认监听80/443;PostgreSQL监听5432(仅限本机);Puma监听8080(Unicorn的默认端口,新版用Puma,目录不同但端口逻辑一样)。
5. 必做的安全加固与访问配置
5.1 给GitLab配上HTTPS
HTTP明文传输的密码简直就是裸奔。GitLab自带Nginx,配HTTPS只需要三步。第一步,把证书和私钥文件放到/etc/gitlab/ssl/目录下:
sudo mkdir -p /etc/gitlab/ssl sudo chmod 700 /etc/gitlab/ssl然后把证书文件命名为gitlab.example.com.crt,私钥命名为gitlab.example.com.key。第二步,修改/etc/gitlab/gitlab.rb:
external_url 'https://gitlab.example.com' nginx['enable'] = true nginx['redirect_http_to_https'] = true第三步,重新reconfigure:
sudo gitlab-ctl reconfigure这里我要特别提醒:如果用的是自签名证书,GitLab部分组件之间的内部通信也会校验证书,可能需要在配置里额外设置letsencrypt['enable'] = false或者在客户端信任该证书。从生产角度,建议直接用自动化平台签发的免费证书,避免一堆自签名的“信任问题”。
5.2 配置Nginx反向代理(可选场景)
如果你的服务器上已经有一个Nginx在提供服务,不想让GitLab独占80/443端口,可以把GitLab的Nginx禁用,用外部Nginx做反向代理。修改gitlab.rb:
nginx['enable'] = false然后在外部Nginx的配置文件里加上一段代理规则:
server { listen 80; server_name gitlab.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name gitlab.example.com; ssl_certificate /etc/ssl/gitlab.example.com.crt; ssl_certificate_key /etc/ssl/gitlab.example.com.key; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }这个方案适合泛域名、多服务共存的架构。要注意的是GitLab的WebSocket(用于实时日志和终端)也需要相同的代理配置,缺失会导致实时功能异常。
5.3 邮件通知配置
GitLab要有邮件通知功能,注册验证、密码找回、合并请求提醒都靠它。以常见的SMTP服务为例,修改gitlab.rb:
gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "smtp.example.com" gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = "gitlab@example.com" gitlab_rails['smtp_password'] = "你的SMTP授权码" gitlab_rails['smtp_authentication'] = "login" gitlab_rails['smtp_tls'] = true这里强调一下“授权码”而非登录密码。现在主流的邮件服务商都要求用专用授权码登录SMTP,用明文登录密码大概率报535错误。配置完成后用这个命令测试:
sudo gitlab-rails console在Rails控制台里执行:
Notify.test_email('receiver@example.com', 'Test Subject', 'Test Body').deliver_now能收到邮件就说明配置生效了。
6. 日常运维:备份、升级与迁移,一次讲透
6.1 用自带命令做备份
GitLab的备份机制设计得比较完善,备份内容包括:数据库数据、Git仓库数据、附件文件、CI/CD配置。执行备份:
sudo gitlab-backup create备份文件默认存放在/var/opt/gitlab/backups/,文件名类似1720000000_2024_07_07_16.8.0_gitlab_backup.tar。建议把/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json这两个配置文件单独备份,缺了它们,备份文件即使恢复了也用不了。这个坑我亲身经历过:备份文件完好,但secrets文件丢了,所有仓库能恢复但Web端登录不了,最后只能重置所有加密密钥,等于重装。
可以写一个cron任务定期备份:
0 2 * * * /usr/bin/gitlab-backup create >> /var/log/gitlab-backup.log 2>&16.2 升级GitLab的完整流程
GitLab升级有个铁律:不能跨大版本直接跳,只能逐版本升级。比如从16.0升到16.11,再升到17.0。每升一次,都要跑一次reconfigure和migrate:
sudo apt update sudo apt install gitlab-ce sudo gitlab-ctl reconfigure sudo gitlab-ctl migrate升级前必须做一次备份,备份后还要在测试环境先验证一遍恢复流程。生产环境升级前建议先停掉GitLab的写入:
sudo gitlab-ctl deploy-page up这条命令会展示一个维护页面,防止用户在升级过程中提交数据。升级完成后取消维护页:
sudo gitlab-ctl deploy-page down还有一点:升级GitLab CE版本时,如果跨了大版本,Gem和Node.js依赖可能不兼容,表现为升级后页面白屏或500错误。此时到gitlab.rb里检查所有非默认配置,多半是某个配置项已经废弃导致的。
6.3 迁移到新服务器
迁移场景在团队换了服务器或者云平台时很常见。迁移的核心思路是“版本完全一致+配置文件完整迁移”,步骤梳理如下:
在新服务器上安装相同版本的GitLab,然后停掉新服务器的服务(除了PostgreSQL和redis,先停Nginx和Puma,避免端口冲突):
sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq sudo gitlab-ctl stop nginx把旧服务器的备份文件和两个配置文件复制到新服务器对应目录:
scp /path/to/backup.tar user@new-server:/var/opt/gitlab/backups/ scp /etc/gitlab/gitlab.rb user@new-server:/etc/gitlab/ scp /etc/gitlab/gitlab-secrets.json user@new-server:/etc/gitlab/在新服务器上恢复备份:
sudo chmod 777 /var/opt/gitlab/backups/备份文件.tar sudo gitlab-backup restore BACKUP=备份文件名(不含.tar扩展名)恢复完成后,重新配置并启动所有服务:
sudo gitlab-ctl reconfigure sudo gitlab-ctl restart这里有个细节:备份文件只有GitLab进程本身能读取,手动恢复时需要调整文件权限为777,恢复完再改回来,否则可能出现“Permission denied”。
7. 常见问题速查与实战解决
以下问题都是我在不同服务器上真实遇到过的,整理成速查表方便你排查时快速定位。
| 现象 | 可能原因 | 排查命令与解决办法 |
|---|---|---|
| 访问页面502 | Puma还没启动完成或内存不足 | sudo gitlab-ctl status、sudo gitlab-ctl tail puma,等几分钟再刷新;内存不足则加swap或升级配置 |
| 页面503 | Nginx配置错误或reconfigure未执行 | 检查/var/log/gitlab/nginx/error.log,重新sudo gitlab-ctl reconfigure |
| git push时报403 | SSH密钥未添加到用户配置或IP白名单 | 检查GitLab用户Settings里的SSH Keys,本地用ssh -T git@gitlab.example.com测试 |
| git clone时报Permission denied | 公钥不匹配或本地用的是HTTP方式但密码错 | 确认本地公钥是否已添加,改用git@开头地址克隆 |
| 执行gitlab-rails时报Gem错误 | 版本升级导致的依赖残留 | sudo gitlab-rake cache:clear,必要时执行sudo gitlab-ctl clean |
| 数据库连接失败 | PostgreSQL未启动或数据目录损坏 | sudo gitlab-ctl status postgresql,查看/var/log/gitlab/postgresql/日志 |
| 修改external_url后页面商品图裂 | 图片存储在别的主机名路径下 | 修改配置后必须reconfigure,如果之前域名变过,需要迁移仓库路径 |
| 定时备份文件越来越大 | 备份没有清理机制 | 在cron里加find /var/opt/gitlab/backups -mtime +7 -name '*.tar' -delete |
除了表格里的这些,还有一个很隐蔽的问题:服务器的系统时间不准会导致GitLab部分功能异常,比如sidekiq里的定时任务不执行。排查时可以用date -R看一眼当前时间,偏差超过几分钟就该配置NTP校正。
8. 安装完成后,把这些配置也顺手做了
8.1 创建第一个项目并验证全链路
安装配置全部完成后,真正麻烦的是验证整条链路是否打通。新建一个项目,从本机克隆、修改、推送、创建合并请求,完整走一遍流程。
新建项目后的HTTP克隆地址通常长这样:
http://gitlab.example.com/root/demo-project.git按GitLab提示的示例命令执行第一次推送:
git init git remote add origin http://gitlab.example.com/root/demo-project.git git add . git commit -m "Initial commit" git push -u origin main如果是SSH克隆地址,则形如git@gitlab.example.com:root/demo-project.git。我第一次配完GitLab后,HTTP方式推送中文文件名总是报编码警告,后来发现是核心配置里core.quotepath默认关闭,中文文件名在日志里显示成八进制转义。不耽误操作,但看起来别扭,可以改回来:
git config --global core.quotepath false8.2 给团队设置的用户管理策略
GitLab装好只是开始,团队真正用起来之后,用户管理才是日常重点。推荐的做法是:在Admin Area里关闭用户自助注册(如果你只需要内部成员),开启管理员审核新用户,同时设置项目默认分支保护规则。
在Admin Area → Settings → General,把Sign-up restrictions里的Sign-up enabled关掉。这样可以避免服务器地址暴露后被人随便注册账号。项目层面的分支保护,我习惯默认设置:main分支禁止任何人直接推送,所有代码必须通过Merge Request合入,且至少需要一个人审批。
这步做完,团队里那种"直接在main上改然后强推"的坏习惯可以彻底杜绝。
8.3 调整CI Runner(如果有持续集成需求)
GitLab内置了强大的CI/CD功能,但默认没有Runner,流水线会一直卡在pending状态。安装Runner有两种路径:一种是直接在服务器上装gitlab-runner二进制文件,另一种是用Docker方式启动。单机上最省事的还是直接装Runner:
curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 chmod +x /usr/local/bin/gitlab-runner sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash sudo gitlab-runner install --user=gitlab-runner sudo gitlab-runner start注册Runner时需要的token在GitLab项目页面里找:Settings → CI/CD → Runners。Runner注册时需要指定executor,新手最容易踩的坑是选了shell executor后,构建环境里什么都没装,流水线第一步就报错。这个完全正常,需要自己在Runner所在的服务器装好项目的构建依赖。
9. 最后再分享几点实操体会
GitLab这东西,装一遍记忆深刻,装三遍你就会发现大部分所谓“疑难杂症”其实都是同一个原因:配置改完之后没有正确reconfigure,或者升级时的顺序颠倒了。这是我踩过最多次的坑,所以你在看任何教程时,都要习惯把“reconfigure之后发生了什么”作为重点。
我还有一个个人习惯:每次修改gitlab.rb之前,先cp一份备份到同目录再加时间戳后缀。比如cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.bak.20240707。别小看这个动作,GitLab的配置文件里几百行Ruby语法,一个引号写错就可能导致整个服务起不来,有备份就随时能回退,没有就只能靠记忆把改过的行一点点改回去。
工具链路从Git到GitLab,中间还牵扯到SSH、Nginx、PostgreSQL、Redis这些基础设施,每一样单独拿出来都能写一篇长文。这篇教程最想帮你解决的问题,是把“装起来”和“用好”之间那段谁都说不清的模糊地带趟平。如果你照着走完一遍,本地能clone能push,Web端能看到提交记录,那这个平台就已经算正式跑起来了。后面的CI/CD流水线、代码质量检查、权限模型细化,都可以在这个基础上慢慢加。版本管理工具永远是越用越理解,而不是越学越会。