给一个小团队搭GitLab服务器这件事,我前后折腾了快三年。第一次装的时候,跟着官方文档一步步走,结果卡在内存优化上,2GB的小机器跑起来跟蜗牛似的,登录页转半天,气得我差点把机器砸了。后来换了配置、调了参数,又陆陆续续给身边几家公司装了几台,才慢慢摸出门道来。
如果你也正打算在自建的gitlab服务器上托管代码,或者已经装好了但总觉得跑得不对劲,这篇文章应该能帮你省掉不少弯路。我会从选机器、装系统、装GitLab、配HTTPS、做备份,一直到日常的故障排查和性能优化,把整个流程掰开揉碎讲清楚,包括一些官方文档不会细说的坑。内容面向有一定Linux基础、但没怎么碰过GitLab的开发者,也适合刚接手公司GitLab维护的运维新手。
1. 为什么最终选了自己搭:先把账算明白
1.1 托管服务和自建的差异在哪
很多团队开始都用第三方的代码托管平台,最开始是公开仓库免费,等团队变大了、代码不想公开了,就开始买私有仓库的套餐。人数少的时候一个月几块钱无所谓,但人一多,费用就上去了,而且你永远受制于平台的限制:单个仓库大小有限制、上传下载速度不稳定、代码仓库的权限模型不够细。
自建GitLab最大的好处是私有化。代码全部留在自己的服务器上,数据不出内网,权限想怎么设怎么设,无论是给客户演示、做二次开发,还是对接内部的LDAP账号体系,都非常方便。另外一个关键是CI/CD,GitLab内置了CI/CD能力,你可以在服务器上直接配Runner,提交代码自动跑测试、自动构建镜像、自动部署,一套流程串起来。托管平台虽然也有类似功能,但并行任务数、构建时长都会受到套餐限制,自己搭就自由很多。
1.2 成本算下来并不比托管贵
有一阵子我专门算了笔账:一个十人左右的技术团队,在托管平台上买私有仓库加CI的套餐,一年的费用足够租一台性能还不错的云服务器了。自建GitLab用的Omnibus集成包是开源的,社区版功能对于绝大多数团队完全够用。需要花钱的只有服务器和域名,域名一年几十块,服务器根据自己的规模选,一台4GB内存的机器就能跑得很舒服。
当然,自建也有隐性成本。你得有人维护,得处理备份、升级、故障恢复这些问题。但只要把流程规范好,这些其实花不了太多时间。我个人给几家小公司搭完以后,后续基本每个月看一眼状态就行。
1.3 什么情况下不建议自建
说实话,也不是所有团队都适合自建。如果你们就一两个人,代码量也不大,用托管平台的免费额度就够了,没必要折腾一台服务器。如果团队没有懂Linux的人,那我也建议慎重,因为GitLab是很吃系统资源的应用,出了问题如果没人能扛,反而耽误事。
如果只是想要一个能放代码的地方,也可以考虑Gitea或者Gogs这种更轻量的解决方案。但如果你想要的是完整的DevOps平台——代码仓库、Issue管理、Merge Request评审、CI/CD一整套——那GitLab就是最合适的选择。
2. 服务器选型与系统初始化:哪些配置是底线
2.1 内存和CPU怎么选
GitLab官方推荐的生产环境最低配置是4GB内存,这个我很赞同。很多人觉得2GB也能跑,确实能跑,但只是“能跑”而已:安装完成后,PostgreSQL、Redis、Sidekiq、Puma这几个服务一启动,内存直接吃满,系统就会开始疯狂使用Swap,页面打开要好几秒。
我实际测过的几种配置如下:
| 内存 | CPU | 体验 |
|---|---|---|
| 1GB | 1核 | 装都装不上,跑起来直接OOM,不推荐 |
| 2GB | 2核 | 勉强能用,最好再加4GB Swap,日常小团队还行 |
| 4GB | 2核 | 官方推荐底线,10人以下团队足够 |
| 8GB | 4核 | 50人团队加CI Runner,基本舒适 |
磁盘方面,系统盘最少30GB,但我建议直接上50GB以上。因为除了代码仓库本身,还有GitLab的数据库、日志、CI构建的产物,都会慢慢把磁盘占满。我见过一台机器因为磁盘满了导致GitLab直接拒绝写入,所有开发者的push都失败,紧急扩容才救回来。所以磁盘宁可大一点,也不要在上面省。
2.2 系统发行版怎么选
如果你问我的意见,Ubuntu 22.04 LTS 或者 Debian 12 是首选。这两个系的包管理方式对GitLab支持最友好,官方文档里的安装步骤也是围绕apt展开的。CentOS 7虽然也支持,但那边已经停止维护了,新机器别再用。CentOS Stream或者AlmaLinux也可以,但能用Debian系就用Debian系,省心。
系统装好以后,先做三件事:更新软件源、确认sshd在运行、配置好主机名。
sudo apt update && sudo apt upgrade -y sudo hostnamectl set-hostname git.example.com2.3 域名规划和防火墙
域名这事容易被忽略。GitLab安装好以后,external_url就是它的门户地址。如果你直接用IP访问,后面配HTTPS、配CI变量会麻烦很多。我建议提前准备一个二级域名,比如git.example.com,解析到你的服务器IP上。
如果是云服务器,还要注意安全组和系统防火墙。GitLab要开80和443端口,如果要用SSH方式访问仓库,还得保证22端口能连。很多云平台默认的安全组规则只开放了少数端口,装好了GitLab却死活访问不了,十有八九是防火墙没放行。
sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw status3. Omnibus安装与登录:从apt源到浏览器出现登录页
3.1 用Omnibus包而不是源码编译
GitLab的安装方式有好几种:源码安装、Docker安装、Omnibus包安装。如果你是第一次装,我强烈建议选Omnibus,也就是官方打包的一体化安装包。它会自动把GitLab所需的各个组件(数据库、缓存、Web服务器等)全部装好,并且提供了统一的命令行管理工具gitlab-ctl,日常运维基本上都在这个命令上。
源码安装这种路子,除非你有非常特殊的定制需求,或者想深入理解GitLab内部原理,否则不要碰。你自己折腾编译的往往跟不上官方更新,安全补丁没法及时打。
3.2 一条命令加入GitLab软件源
以下操作以Ubuntu 22.04为例:
sudo apt-get install -y curl openssh-server ca-certificates curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash sudo apt-get install gitlab-ce安装过程中会自动装上PostgreSQL、Redis这些依赖组件。这里有个小提醒:如果你的机器内存比较小,安装时间会比较长,耐心等待就好,不要中途去kill进程,否则很容易留下残缺的包。
如果你需要的是企业版,把上面命令里的gitlab-ce换成gitlab-ee即可。社区版和企业版在基础功能上差别不大,官方提供在线对比页面,你可以按需选择。
3.3 修改external_url并执行reconfigure
包装好以后,GitLab还处于未配置状态。你需要编辑主配置文件:
sudo vim /etc/gitlab/gitlab.rb找到这一行:
external_url 'https://git.example.com'注意这里可以直接写HTTPS地址,GitLab会自动帮你配置SSL证书相关的选项。如果你暂时没有证书,可以先用HTTP,后面再加配置。
改完以后执行:
sudo gitlab-ctl reconfigure这一步是GitLab整个安装过程中最关键的环节。它会根据gitlab.rb里的配置,重新生成所有组件的配置文件、初始化数据库、启动所有服务。整个过程大概几分钟,日志会逐行滚动。碰到红色报错信息别慌,多数情况下是因为依赖包没装全或者磁盘空间不足。
3.4 第一次登录与root密码
reconfigure成功以后,打开浏览器访问你的域名。第一次访问会让你设置root用户的初始密码。这里我提醒两点:
第一,密码不要设得太简单,因为root是管理员账号,一旦被攻破,整个代码仓库都暴露了。第二,至少设置8位以上且包含大小写和数字的密码。
登录进去以后,你会看到GitLab的欢迎页。这时候建议你第一时间去创建一个普通用户,日常开发不要用root操作,root只用来做管理。在用户管理里可以设置权限、改成管理员或普通成员,整个权限体系在第一次建项目之前想清楚,后面会省很多事。
4. 项目上线前的必须动作:HTTPS、备份、权限与Runner
4.1 白嫖HTTPS证书:内置Let's Encrypt
现在的Web应用没有HTTPS说不过去,尤其代码仓库这种敏感数据。GitLab很贴心,配置里直接集成了Let's Encrypt的支持,只需要在/etc/gitlab/gitlab.rb里改两行:
letsencrypt['enable'] = true letsencrypt['contact_emails'] = ['admin@example.com']然后再次执行sudo gitlab-ctl reconfigure。前提是域名已经解析到这台服务器,且80端口对外开放。Let's Encrypt在签发证书前会访问你的HTTP端口做验证,如果验证不通过,证书就签不下来。我第一次配置的时候忘了开安全组80端口,折腾了半天才反应过来。
证书签好以后是自动续期的,GitLab会定时检查证书有效期,快到期了自动续签。你基本不需要管它。
4.2 备份策略与恢复演练
如果你只记住一条运维指令,那一定是备份。
GitLab的备份命令很简单:
sudo gitlab-backup create它会备份数据库、仓库、附件、CI产物等几乎全部数据,默认备份到/var/opt/gitlab/backups目录。除了数据备份,配置文件也要单独备份,因为gitlab.rb和管理密码都写在里面。这个可以用另一个命令:
sudo gitlab-ctl backup-etc备份出来的文件是一份加密的tar包。
恢复的时候,先把备份文件拷贝到/var/opt/gitlab/backups目录,然后执行:
sudo gitlab-ctl stop unicorn sudo gitlab-ctl stop sidekiq sudo gitlab-backup restore BACKUP=备份文件的时间戳 sudo gitlab-ctl start这里我必须强调:备份是装了就一定要配的,但配了不演练等于没配。我见过有人定时跑了半年备份,真出事时发现备份文件是坏的。所以建议每月至少做一次恢复演练,把备份恢复到一台临时机器上,验证数据能不能用。整个过程不复杂,但关键时刻能救命。
4.3 用户权限和群组权限设计
GitLab的权限模型核心是三个层级:群组(Group)、项目(Project)、成员(Member)。你可以把群组理解为一个部门或者一个产品线,项目放在群组下面,成员加到群组里,分配不同角色。
| 角色 | 权限 |
|---|---|
| Guest | 只能看Issue和讨论,不能看代码 |
| Reporter | 可以看代码、创建Issue、拉取项目 |
| Developer | 可以push代码、管理Merge Request |
| Maintainer | 可以管理项目设置、成员、分支保护 |
| Owner | 群组或项目的完全控制权 |
我的建议是每个组设一个Owner,项目设一个Maintainer,开发者统一给Developer,不要给所有人Maintainer。分支保护也建议打开,main或者master分支默认是受保护的,只有Maintainer能直接push,其他人都得走Merge Request,这样代码Review才能形成习惯。
4.4 注册Runner让CI/CD跑起来
GitLab自带CI/CD是它的一个巨大优势。安装完GitLab之后,接下来通常就是配Runner。Runner可以理解为专门跑CI任务的执行器,它和GitLab服务器是分离的,可以装在同一台机器上,也可以单独用一台。
安装Runner的命令,以Linux为例(这里以通用安装脚本为例):
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash sudo apt-get install gitlab-runner然后在某个项目里找到Settings -> CI/CD -> Runners,里面会给你一个注册token:
sudo gitlab-runner register按照提示填上GitLab服务器的URL和token,选择执行器类型(shell、docker、ssh都可以)。新手建议先用shell执行器,这样不用折腾Docker,等CI流程稳定了再考虑用docker执行器做环境隔离。
5. 内存紧张时的急救指南:关掉非必要服务
5.1 为什么4GB内存也会卡
很多人装了GitLab以后发现,明明内存已经4GB了,为什么还是感觉不流畅?因为GitLab默认会把Prometheus监控、Grafana图表这些辅助服务全都打开。在内存就是一切的云服务器上,这些服务非常奢侈。
如果你不需要监控面板,可以关掉这些服务,在/etc/gitlab/gitlab.rb里加上:
prometheus_monitoring['enable'] = false grafana['enable'] = false然后重新reconfigure。我实测过,光是关掉Prometheus和Grafana,就能省出将近1GB内存。
5.2 调低Web服务并发数
GitLab的Web服务进程可以看作前台接待人员,接待人员越多,并发处理能力越强,但每个接待人员都要占内存。在小内存机器上,我们要的是够用就好。
在/etc/gitlab/gitlab.rb里可以调整:
puma['worker_processes'] = 2 puma['min_threads'] = 1 puma['max_threads'] = 4如果你装的老版本用的是Unicorn,类似这样:
unicorn['worker_processes'] = 2这个值通常按CPU核数的一半设置就行。2核机器设2个worker,4核设4个,不要贪多。
5.3 限制Sidekiq并发和数据库缓存
Sidekiq是GitLab的后台任务队列处理器,负责发邮件、跑文档索引、清理临时文件等等。它的默认并发数也比较激进,可以调低:
sidekiq['max_concurrency'] = 5 sidekiq['min_concurrency'] = 5PostgreSQL的共享缓存也可以缩减一点。默认情况下Omnibus会自动配置得比较大方,在小内存机器上我一般手动设成:
postgresql['shared_buffers'] = "256MB"这一套组合拳打完以后,再执行一次sudo gitlab-ctl reconfigure,重启完成后用free -h看看内存占用,你会明显看到降下来不少。
6. 日常运维里最常遇到的三个问题:502、大版本升级、磁盘膨胀
6.1 502 Bad Gateway的排查思路
用过GitLab的人,基本都见过502页面。这个页面看着吓人,其实本质上是Nginx和后端服务之间没对上暗号。常见的排查步骤我给你列一下:
先看服务有没有挂:
sudo gitlab-ctl status如果某个服务显示down,用gitlab-ctl restart把它拉起来。如果服务状态正常但还是502,多半是磁盘满了:
df -h磁盘占满会让GitLab无法写入临时文件和数据,进而导致服务假死。清理日志和备份文件的时候,注意别删正在被使用的文件。还有一种情况是Puma或者Unicorn启动失败,这个看日志最直接:
sudo gitlab-ctl tail puma sudo gitlab-ctl tail postgresql日志里会精确告诉你哪个地方出了问题,比如端口被占用、数据库连接数不够,照着提示处理就好。排查的过程中不要慌,502基本都能在几分钟内定位出来。
6.2 大版本升级时的一次教训
GitLab的升级有一个很关键的规则:不能跨大版本跳级升级。比如从13.x直接跳到15.x,这会带来数据结构不兼容的风险,升级到一半出错,服务直接起不来。
正确的做法是逐级升级:13.x -> 14.x -> 15.x。每次升级前做好备份,读完对应版本的升级文档。我自己的习惯是:
sudo apt update sudo apt install gitlab-ce在跑这个命令之前,先执行一次sudo gitlab-backup create,再执行sudo gitlab-ctl backup-etc备份配置文件。升级完成后过个半小时,确认一切正常再让团队恢复提交代码。
另外,升级过程中GitLab会停服一段时间,最好提前和团队打好招呼,避免有人在升级期间push代码。
6.3 磁盘膨胀的日常清理
GitLab跑久了,磁盘悄悄地就满了。主要来源有三个:CI构建产物、日志文件、数据库膨胀。
CI产物可以通过项目的Settings -> CI/CD -> Job artifacts去设置过期时间,比如保留7天或30天。
日志方面,/var/log/gitlab目录下的文件会越攒越多。GitLab自带的日志默认是保留几份压缩包的,如果你的磁盘压力大,可以在/etc/gitlab/gitlab.rb里调整保留的日志份数。
有些临时文件和CI缓存存放在/var/opt/gitlab/git-data目录下,你可以定期检查builds目录的大小,该清就清。
注意:清理操作之前务必确认备份是好的。清理CI产物没问题,但如果你去手动删除数据库文件,那就等于自掘坟墓。宁可磁盘临时告急,也不要去动数据库底层文件。
7. 最后再分享几个让我省心的小习惯
现在给团队装GitLab服务器,对我来说已经是轻车熟路了,但回头一想,真正让我少踩坑的,还是几个看起来不起眼的习惯。
第一,备份脚本一定要写成定时任务。sudo crontab -e里加一行,每天凌晨跑一次gitlab-backup create,加一个SKIP=artifacts参数跳过大的CI产物,可以省不少空间。每隔一段时间再全量备份一次。配上云平台的对象存储,把备份文件自动上传一份到异地,这样即使整台服务器没了,数据也还在。
第二,重要配置文件的改动记录要留痕。我每次改/etc/gitlab/gitlab.rb都习惯在文件开头写一行注释说明改动原因和时间,这个习惯看起来没什么技术含量,但在半年后回头排查问题的时候非常好用。
第三,给团队培养一个意识:不要什么代码都往GitLab上推。大文件、构建产物、依赖包,这些应该走对象存储或者制品库,而不是堆在Git仓库里。仓库越大,GitLab跑得越慢,备份恢复也越慢。在.gitignore里把该忽略的都忽略掉,能从源头上避免很多麻烦。
一台GitLab服务器从零搭起来,到现在稳定运行,不复杂,但也绝不像装个普通软件那样点两下就完事。希望这篇分享能让你少踩一些我踩过的坑,把更多精力放在真正有意思的事情上。