想在公司内部搭一套自己的代码托管平台,多数人绕不开GitLab CE社区版。这篇东西写给第一次在CentOS 7上用Omnibus方式安装GitLab CE的人,也顺带记录一下我装过几次之后沉淀下来的习惯性操作。GitLab CE并不是一个单进程程序,它是一整套服务:Nginx、PostgreSQL、Redis、Sidekiq、Gitaly、Puma等等,装完一看内存占用普遍超过2GB,所以很多人第一次装完发现机器卡到不能自理。提前把环境规划讲清楚,后面能少走很多弯路。
这篇博文不会只贴命令,我会把每一步为什么这么做讲透,包括防火墙、SELinux、swap、external_url这些最容易被忽视但一错就是半天的点。适合三类人:准备在公司内网搭GitLab的运维和开发,想把自己代码仓库从第三方托管迁回本地的人,以及单纯想学一下Linux服务部署的初学者。整个过程跟着做,大概30到60分钟能跑完,取决于机器配置和网络速度。装完之后你就能拥有一个包含仓库管理、MR/CI、Wiki、Issue跟踪的完整平台。
1. 动手之前:先想清楚装完要给谁用
1.1 这不只是“一条命令”的事
很多人看到安装命令就一条yum install -y gitlab-ce,觉得跟装个Nginx差不多,实际上GitLab把一堆服务打成了一个Omnibus包,里面除了应用本身,还打包了数据库、缓存、Web服务器、后台任务队列。用Omnibus方式安装,好处是统一管理、配置集中,但代价是资源占用相当可观。
我第一次装的时候,拿一台2核2G的虚拟机硬跑,reconfigure过程直接卡死,后来把日志翻出来发现内存耗尽,进程被系统OOM Killer干掉。所以如果你想在生产环境长期用,最低建议4GB内存起步,8GB内存才算舒服。GitLab官方对4GB内存的定义是“可以跑,但会很吃力”,实际体验也确实如此:开十几个开发者、跑几条流水线,内存就会吃紧,频繁触发swap导致页面响应变慢。
这里有个概念要先建立:GitLab不是一个“软件”,它是一套“服务集群”。你在CentOS 7上安装它,本质上是在搭一个小型服务器群组,只是Omnibus包把复杂度包装起来了。理解了这一点,后面遇到什么502、内存不足、端口冲突,就不会一脸懵。
1.2 Omnibus、Docker、源码,为什么我选Omnibus
GitLab主流的安装方式有三类:Omnibus(rpm/deb一键包)、Docker容器、源码编译。源码方式在CentOS 7上非常痛苦,依赖极多,升级维护成本高,现在基本没人自己编译了。源码方式我直接不建议,除非你是想研究GitLab内部实现。Docker方式其实不错,一条docker run就能起一个实例,但这里有个细节:GitLab在容器里也是跑一整套内部服务,对宿主机内存、磁盘的要求并没有降低,而且数据卷、端口映射、HTTPS证书这些细节需要额外理解,对新手反而增加认知负担。
我推荐Omnibus方式,原因很实际。第一,gitlab-ctl这个管理命令把所有服务的启停、状态检查、配置重载统一起来了,不需要单独记nginx怎么重启、postgresql怎么启动。第二,rpm包安装后会自动配置好systemd服务,服务器重启后GitLab能自动拉起,省心。第三,CentOS 7本身就是Red Hat系,rpm是原生包管理,升级直接yum update gitlab-ce,路径最顺畅。
1.3 版本选择:社区版还是企业版
GitLab分CE社区版和EE企业版,安装步骤一样,只是包名不同。个人使用、小团队内网用,CE完全够。有人担心CE缺功能,实际上代码托管、Merge Request、CI/CD、Wiki、Issue这些核心功能CE都包含,EE多的主要是审计日志、多LDAP、弹性伸缩等企业级能力,小团队用不到。
装的时候直接装gitlab-ce就行,不要想着“先试试EE后面再说”,两个版本包之间切换虽然可行,但没必要。另外安装源默认给的是当前最新稳定版,不需要手动指定版本,除非你公司有版本合规要求,那才需要在repo里锁定具体版本号。对新装环境,跟随最新稳定版是最省心的选择。
2. 环境准备:把 CentOS 7 收拾干净再动手
2.1 先确认系统身份和基础状态
进服务器第一件事,确认你的系统确实是CentOS 7。虽然标题写了CentOS 7,但我见过太多人在CentOS 8甚至其他发行版上执行CentOS 7步骤,结果处处报错。用cat /etc/redhat-release看下,如果是7.x就继续。
系统时间也很重要,GitLab的HTTPS证书校验、日志排序、Cron任务都依赖准确时间。我习惯在装GitLab前把时区调到中国标准时间并同步:
sudo timedatectl set-timezone Asia/Shanghai sudo chronyd -qCentOS 7关于yum update -y,我的建议是装GitLab之前别直接执行全量更新。原因很现实:GitLab的rpm包本身会带依赖,它需要的运行库版本在CentOS 7的默认源里都有,不需要先升级一堆包。全量更新容易把内核、glibc这些基础组件升级到新版本,万一跟当前环境有兼容问题,排查起来非常头疼。如果你非要更新,至少先把需要用的磁盘空间预留好。
GitLab安装包加依赖大概会占2到4GB的空间,这还不算以后的仓库数据。所以装之前用df -h确认/opt和/var所在分区有足够空间。以后仓库数据默认全放到/var/opt/gitlab,别让这个目录所在磁盘只有十几GB,Git仓库长起来是很快的。
2.2 防火墙与SELinux:两个最容易背锅的地方
CentOS 7默认开着firewalld,默认策略会把80端口挡在外面。GitLab的Web服务走HTTP/HTTPS,SSH走22端口,这些都要放行。最简单的做法是直接停掉防火墙,但我不建议在正式环境这么干,正确的做法是只放行需要的端口:
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --reload如果装了云服务器,还要记得在安全组里放行对应的端口,这一步经常被忽略,防火墙放行了但外面访问不了,就是这个原因。
然后是SELinux。CentOS 7默认SELinux是Enforcing模式,GitLab的Nginx要监听端口、读写大量目录,默认策略下经常出现页面能打开但静态资源加载不了,或者Git clone时连接被拒的情况。GitLab官方对SELinux的态度是支持但需要额外配置策略,对小团队来说最简单的是直接设为permissive:
sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config第一行立即生效,第二行保证重启后依然生效。设成permissive之后,SELinux只会记录违规日志,不会真正拦截行为,对GitLab这种内部服务完全够用。千万别设成disabled,那是把所有SELinux保护层全部关掉,除非你很清楚自己在做什么。
2.3 swap别省:帮你扛过安装期的高峰
GitLab reconfigure的时候会同时启动数据库初始化、Nginx配置生成、资产文件预编译等一系列任务,内存峰值相当高。4GB内存机器在安装阶段很容易触发OOM,这时候一个swap能救命。
我个人习惯给2GB到4GB的swap,尤其内存小于8GB时,这一步很值得做。创建swap文件的方式:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab老版本内核可能需要用dd来创建swap文件,CentOS 7默认4.18内核一般fallocate够用。swap能缓解内存压力,但它不是万能的,如果日常使用中swap持续被大量占用,说明物理内存确实不够,该加内存就加内存。
3. GitLab CE 安装全流程记录
3.1 先装Postfix还是装完再配邮件
GitLab本身不自带邮件发送服务,它依赖系统里有一个SMTP服务器,默认情况下Omnibus包找的是Postfix。新用户注册、密码找回、MR通知、CI结果通知,全靠邮件。如果不装Postfix,这些功能都不会正常工作,但你不会立刻发现,因为GitLab不会在页面上弹红色警告。
所以我建议的安装顺序是:先装Postfix,再装GitLab。Postfix在CentOS 7源里直接有:
sudo yum install -y postfix sudo systemctl enable postfix sudo systemctl start postfix装完后检查一下systemctl status postfix,确认是active状态。如果你的环境不允许出站25端口,邮件功能还是发不出去,那也别慌,后面可以在GitLab里配置外部SMTP服务器,比如用企业邮箱、第三方邮件服务,这个等以后需要时再配。如果实在是内网测试不想折腾邮件,Postfix可以不启动,GitLab其他功能不受影响,只是通知类邮件发不了。
3.2 配置YUM源并执行安装
GitLab官方提供了安装脚本,一行命令就能把yum源配好:
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash这条命令做了三件事:下载GitLab仓库配置文件到/etc/yum.repos.d/gitlab_gitlab-ce.repo,导入GPG签名公钥,最后自动执行yum makecache刷新缓存。脚本输出里能看到仓库地址和源版本。
国内服务器访问官方源很慢,甚至超时。这种时候建议手动改用国内镜像源,新建/etc/yum.repos.d/gitlab-ce.repo,内容替换为镜像站地址。这里以清华源为例:
[gitlab-ce] name=Gitlab CE Repository baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ gpgcheck=0 enabled=1需要说明的是,这里gpgcheck=0是省掉了密钥校验的麻烦。如果你有安全洁癖,可以保留官方源里的GPG key导入步骤,再把gpgcheck=1写回。我一般在内网环境图省事会用0,外网环境还是建议完整校验。
源准备好后,直接安装:
sudo yum install -y gitlab-ce这个包目前大约1GB上下,下载时间取决于带宽。安装过程末尾会提示你用gitlab-ctl reconfigure完成初始化,还会提示默认的初始密码位置。到这一步,GitLab的二进制文件已经就位,但服务还没有真正起来,因为配置文件里最关键的一项external_url还没设置。
3.3 external_url 到底怎么填:这一步值得单独说
/etc/gitlab/gitlab.rb是GitLab的核心配置文件,安装后我要做的第一件事就是改external_url。这个词的意思是“外部访问这个GitLab的URL”,可以填域名也可以填IP。
# /etc/gitlab/gitlab.rb external_url 'http://10.0.0.8'如果你有正式域名,就填http://gitlab.company.com这种;如果是纯内网测试,直接填服务器IP。填完务必执行gitlab-ctl reconfigure让配置生效。这里很多人犯错:改了配置文件,却只执行gitlab-ctl restart,然后发现没生效。因为restart只是重启服务,不会重新读取gitlab.rb里的配置变化,只有reconfigure会把配置重新生成并应用。
如果机器80端口已经被其他服务占了,你要用别的端口访问GitLab,可以把external_url改成带端口的形式:external_url 'http://10.0.0.8:8090',GitLab会自动让Nginx监听8090端口,克隆地址也会带上端口。但这里有个坑:Git仓库走SSH协议的时候,默认用的是22端口。如果服务器22端口是ssh服务在占,你不能让GitLab的SSH也用22,得在gitlab.rb里单独设置:
gitlab_rails['gitlab_shell_ssh_port'] = 2222否则用户clone时得到的地址是git@10.0.0.8:group/project.git,但服务器的22端口根本不是GitLab的SSH服务,连不上。设了2222之后,clone地址会变成ssh://git@10.0.0.8:2222/group/project.git。这个细节不提前知道,等用户报“我拉不下代码”再排查就费劲了。
3.4 首次reconfigure与root账号登录
改完external_url,执行初始化:
sudo gitlab-ctl reconfigure这一步耗时长,4核8G的机器大概3到5分钟,2核4G的要8到10分钟。整个过程会依次初始化PostgreSQL、Redis、Nginx配置,启动Sidekiq、Gitaly,最后编译Webpack资产。期间输出一大片日志,看着像报错,其实大多数是INFO信息。判断成功与否,看最后几行有没有gitlab Reconfigured!,或者直接执行sudo gitlab-ctl status看服务状态。
安装完成后第一次访问,浏览器打开http://你的IP,会自动跳转到密码重置页。但这里有个问题:如果你没有这一步跳转,或者想直接用管理员账号登录,需要用初始密码。新版GitLab把初始root密码写进了文件:
sudo cat /etc/gitlab/initial_root_password文件里有个Password:字段,就是root的初始密码。这个文件只在安装后24小时内有效,那个时间段内你申请的密码会写入,过了24小时文件里的内容也不会变了,但如果你没及时保存,之后文件可能被自动清理。所以拿到密码后立刻登录,进去赶紧改密码。
登录成功后,我强烈建议顺手做一件事:关闭公开注册。公司内网GitLab默认是允许任何人注册账号的,哪怕你不知道地址,扫到IP就能注册。在管理设置里找到Sign-up restrictions,取消勾选Sign-up enabled,只保留管理员手动创建账号,这样避免陌生人注册进来。
4. 启动之后:日常管理和资源优化
4.1 reconfigure、start、restart 的命令区别
装完之后你手里的管理命令主要是gitlab-ctl,不要把它跟systemctl混淆。gitlab-ctl是Omnibus包装好的统一管理入口,它对内管理Nginx、PostgreSQL、Redis、Puma这些服务。
日常会用到三条命令,我刻意把它们拆开讲,因为用法差别很大:
sudo gitlab-ctl reconfigure:修改gitlab.rb配置文件后必须执行它,它会重新生成所有服务配置并重启受影响的服务。注意它不是“重启”,而是“应用配置变更”。sudo gitlab-ctl restart:重启GitLab所有服务,不读取配置变更。进程异常挂掉、内存泄漏需要重置时用。sudo gitlab-ctl status:查看所有服务当前状态。排查问题第一步,先看它输出。
另外单独重启某个服务也是支持的,比如sudo gitlab-ctl restart sidekiq。有时候Sidekiq卡住了,没必要整套服务重启,单点重启就能恢复,这在生产环境是很有用的操作。我有个习惯,做完任何配置修改,先跑gitlab-ctl status看看各服务是不是都是run,然后再打开页面验证功能。
4.2 内存不够时怎么把花哨功能关掉
先说一个现实:GitLab全功能启动后,内存占用通常在3到5GB不等,这还不算后台任务峰值。如果你只有4GB内存,开机后什么都没干内存已经见底。Omnibus包默认把一堆监控组件也装上了,其中Prometheus全家桶最吃内存。
省内存的第一步,关掉Prometheus监控:
# /etc/gitlab/gitlab.rb prometheus_monitoring['enable'] = false改完执行sudo gitlab-ctl reconfigure。这个默认带的监控体系,对小团队来说基本用不上,关掉能省下几百MB内存。第二步,调整Puma的worker数量。Puma是处理HTTP请求的应用服务器,默认会根据CPU核数起worker,已经占了不少内存。限制一下:
puma['worker_processes'] = 2 puma['max_threads'] = 4同样要reconfigure。调整之后内存占用会明显降低,但并发处理能力也相应下降。实时验证效果用free -h看内存,装完到现在内存下降很明显。这套操作对小规模内网使用是合理的取舍,人少并发低,不需要那么多worker吃内存。
4.3 备份、升级和卸载的合规流程
GitLab的数据分两部分,一部分是PostgreSQL数据库里的项目元数据、用户信息、MR记录,另一部分是Git仓库本体文件。所以备份命令是专门设计的,不是简单打包整个目录:
sudo gitlab-backup create老版本这条命令叫sudo gitlab-rake gitlab:backup:create,新版改成gitlab-backup。备份输出默认放/var/opt/gitlab/backups,文件名带时间戳。备份仓库数据库和Git文件,但有一个东西不会自动备份:配置文件。/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json必须手动备份。尤其是gitlab-secrets.json,它保存了GitLab的各种加密密钥,丢了的话,即使你有数据库备份,恢复出来也是各种解密错误。我习惯把这两个文件连同备份一起打包下载:
sudo tar czf /var/opt/gitlab/backups/gitlab-config-$(date +%F).tar.gz /etc/gitlab/升级GitLab前,流程必须是:先备份,再升级。在CentOS 7上升级就是sudo yum install -y gitlab-ce,yum会装最新版。但这里有个大坑:GitLab跨大版本升级不能直接跳,比如13升14可以,14升15可以,但13升15会失败。官方要求每次只能升一个大版本。所以如果你旧版本比较老,得先改成老版本对应的源,锁版本逐步升,一次一次reconfigure。这不是危言耸听,我见过有人从12直接升15,数据库迁移报错之后整个实例起不来,最后靠备份恢复才解决。
卸载倒是简单,sudo gitlab-ctl uninstall会停止服务并移除rpm安装记录,但数据目录还在。想彻底清掉数据,执行sudo gitlab-ctl cleanse,之后手动删除/etc/gitlab、/var/opt/gitlab、/var/log/gitlab这三个目录。一般只有准备重装才需要这么干。
5. 常见问题与排查速查表
5.1 几个我实际遇到过的问题
先说502。安装完第一次打开页面,看到“Whoa there! GitLab is taking too much time to respond.”,绝大多数情况下是服务还没完全启动。这不一定是故障,等多一两分钟刷新可能就好了。确认方法就是跑gitlab-ctl status,如果Puma或者Sidekiq还在启动中,等它从down变run。如果等了很久还是502,大概率是内存不足导致Puma起不来,用dmesg | tail能看到OOM Killer的痕迹。解决方案就是之前说的,加内存、加swap、关Prometheus,三选一或者都做。
再说reconfigure卡住。这可能是网络源慢,也可能是系统时间不对导致证书校验失败。如果卡在下载或者ruby_block上,先确认date时间是否正确,不对就同步;然后看是不是yum源访问慢,换国内镜像源。实在不行,重新执行一次reconfigure,有时候就是网络抖动导致某一步失败,重跑能过。
Postfix启动失败我也踩过。25端口被占是常见原因,看systemctl status postfix,确认端口是谁占了。如果确实不想用Postfix,就在gitlab.rb里把SMTP配置改成外部邮件服务,比如改成阿里云或腾讯的企业邮箱SMTP,这个后面可以单独配。
5.2 排查前先养成三个习惯
排错最重要的不是记命令,是建立一套自己的排查顺序。我每次遇到GitLab异常,第一件事是sudo gitlab-ctl status,看服务整体状态。第二件事是看日志,GitLab日志全在/var/log/gitlab下,按组件分目录,比如gitlab-rails目录里是应用日志,nginx目录里是访问日志和错误日志。回滚一个技巧:先看tail -n 200最近日志,时间点对齐出问题的时刻,基本能找到直接线索。
不要凭感觉改配置,很多“玄学”问题最后都能在日志里找到答案。比如静态资源加载404,看一眼Nginx错误日志,多半是SELinux拦截;比如git clone报权限错误,看一下gitlab-shell日志,多半是SSH key配置问题。
5.3 问题速查表
| 症状 | 最常见原因 | 处理动作 |
|---|---|---|
| 页面502 | Puma未启动或内存不足 | 运行gitlab-ctl status,查看OOM日志,加内存或关Prometheus |
| 静态资源加载失败 | SELinux拦截Nginx读写 | 临时setenforce 0,永久改permissive |
| 页面能开但克隆报错 | external_url或SSH端口配置错误 | 检查gitlab.rb里的external_url和gitlab_shell_ssh_port |
| 初始密码文件找不到 | 超过24小时后被清理 | 用gitlab-rails console修改root密码 |
| reconfigure卡在ruby_block | 网络源慢或系统时间不对 | 换国内镜像源,同步时间后重跑 |
| 邮件发不出去 | Postfix未启动或25端口被限制 | 启动Postfix,或配置外部SMTP |
写到这里,GitLab在CentOS 7上的安装流程、配置、管理、排错就基本讲完了。这套流程我在不同的机器上重复过很多次,最深的体会是:GitLab安装本身并不难,难的是先把环境准备做扎实。我现在的习惯是拿到一台新机器,固定顺序先把swap建好、SELinux关掉、防火墙端口放行、Postfix装好,然后才碰GitLab的安装包,顺序不乱,后面省下的时间远超前期这点准备功夫。你装的时候可能环境跟我不完全一样,但只要抓住“服务全套、配置统一、日志兜底”这几个关键词,遇到任何报错都能把问题缩小到一个可排查的范围内。