第一次在一台裸机上搭GitLab的时候,我连续折腾了两晚,卡在502页面直接怀疑人生。后来把官方文档翻了个底朝天,又把相关的技术社区帖子扫了一遍,才理清整个套路。这篇教程我会把从零到能push代码的完整过程都写下来,包括硬件怎么规划、Omnibus包和Docker怎么选、初始密码去哪找、跑完reconfigure之后还要配什么,以及我踩过的所有坑。无论你是刚接触Linux的新手,还是已经被各种"史上最详细"教程坑过的老手,跟着这篇文章走一遍,基本能稳稳当当把GitLab仓库跑起来。
1. 自建GitLab仓库前,先搞清楚这四件事
1.1 为什么不用现成的代码托管平台,非要自己搭
很多团队的第一反应是:GitHub、Gitee都能托管代码,为什么还要自己在Linux服务器上装一套GitLab?我接触过的自建场景主要分三类。
第一类是代码敏感。金融、医疗、政企类项目,代码根本不允许出内网,托管在第三方平台哪怕私有仓库也过不了合规审查,所以必须在自己的服务器上部署一套GitLab CE(社区版)。
第二类是团队协作需要深度定制。GitLab本身自带完整的CI/CD能力,可以跟Jenkins、Kubernetes、fluxcd之类的工具链深度集成。自建之后,你可以随意改域名、加存储、挂载S3备份、对接企业微信或钉钉通知,自由度完全在自己手里。
第三类是成本问题。代码托管平台对私有仓库数量和协作人数有限制,超过一定规模要收费。团队人数多、仓库数量大的时候,自建GitLab可能反而更省,毕竟它开源,绝大多数中小团队用社区版就完全够用。
1.2 GitLab CE与EE的差异:社区版到底缺了什么
安装之前先分清版本,否则看文档容易看懵。GitLab官方提供了两个分支:CE(Community Edition,社区版)和EE(Enterprise Edition,企业版)。
EE相比CE多了一些高级功能,比如多集群管理、安全合规扫描、效能分析等。对大多数中小团队来说,CE已经覆盖了日常几乎所有需求:无限私有仓库、Issue管理、Merge Request、CI/CD Runner、Wiki、Container Registry,这些都是免费的。
需要注意的一点是,GitLab官网下载页面的默认入口经常会引导你下载EE试用版,下载的时候一定看清楚包名。Debian/Ubuntu系的安装包是gitlab-ce,RHEL/CentOS系是gitlab-ce,别装成了gitlab-ee。EE虽然可以转CE,但过程很折腾,不如开始就装对。
1.3 安装方式怎么选:Omnibus包、Docker还是源码编译
GitLab官方推荐的安装方式有三种:Omnibus一体化安装包、Docker容器、源码编译。源码编译我只说一句:GitLab是Ruby on Rails的大型应用,依赖极其复杂,源码编译需要处理几百个gem包、数据库初始化、前端资源编译,没有个一天半天装不完,出了问题还很难排。除非你是GitLab的二次开发贡献者,否则绝对不要选这条路。
Omnibus包是官方打包的一体化安装包,把Ruby、PostgreSQL、Redis、Nginx、Puma这些组件全部绑在一起,一条命令装完,一条命令初始化。这是官方最推荐、也是社区里踩坑最少的方式。
Docker方式用容器封装,环境隔离性好,宿主机只要装好Docker Engine就能跑。它的优点是可以随意指定版本启动新容器,升级不污染原环境;缺点是数据卷管理和内存限制需要自己多花心思。在后面的章节我会把两种方式都展开讲。
1.4 什么场景下不建议自建
说句实话,GitLab是出了名的"内存大户",如果团队只有三五个开发者,而且没有专职运维,我更推荐直接用第三方的免费托管服务。自建一套GitLab,意味着你还要维护操作系统补丁、GitLab版本升级、备份恢复、磁盘扩容、邮件服务,这些隐性成本经常被忽略。
如果你们团队超过10人,或者有代码不能出内网的要求,或者有强CI/CD集成需求,那么自建才有真正的性价比。理解了这些边界条件,再往下安装就不容易半途而废。
2. 环境准备与硬件规划:多少人用决定你配多少内存
2.1 官方最低配置与实际体验配置对照
GitLab官方文档给了一套硬件参考值,但我实际用下来的体感和官方文档有差距。官方说4GB内存可以支撑500人左右的轻度使用,这种"理论上限"看看就行,真跑到500人,4GB内存的机器早就卡得连登录页都打不开了。
我给自己团队做配置规划时,一般按这个表来参考:
| 团队规模 | CPU核心数 | 内存 | 磁盘 | 适用场景说明 |
|---|---|---|---|---|
| 1-20人 | 2核 | 4GB | 50GB-100GB SSD | 代码托管为主,不常跑CI流水线 |
| 20-100人 | 4核 | 8GB | 200GB SSD | 频繁使用CI/CD Pipeline和Container Registry |
| 100人以上 | 8核以上 | 16GB以上 | 500GB以上 SSD | 高可用、多Runner、大规模构建并发 |
特别提醒一件事:GitLab启动后,Puma和PostgreSQL常驻内存大约要占掉2GB左右。如果机器内存刚好卡在4GB,系统本身还要吃掉一部分,很容易触发OOM(内存不足)导致服务被内核杀掉。所以内存宁多勿少。
2.2 系统版本与依赖检查
GitLab官方支持的主流Linux发行版包括:
- Ubuntu 20.04 LTS / 22.04 LTS
- Debian 11 / 12
- CentOS 7 / 8(CentOS 8已经停止维护,建议用Rocky Linux或AlmaLinux替代)
- openEuler、麒麟这类国产化系统如果基于CentOS/RHEL架构,也可以参照RHEL系的安装步骤操作
安装前先确认系统版本和架构:
cat /etc/os-release uname -mGitLab目前主要提供x86_64和aarch64两种架构的安装包。如果你的服务器是ARM架构(比如华为鲲鹏),下载的时候要挑选对应的aarch64包,别拿到x86_64的包硬装。
2.3 域名或IP规划:external_url是第一个大坑
安装GitLab之前,你必须先想清楚一个问题:用户最终通过什么地址访问它?
这个地址就是external_url,它可以是http://172.16.1.100,也可以是https://gitlab.example.com。很多人忽略了这个规划,随便填了一个内网IP,结果装完之后要用域名访问,又得回炉重造。
external_url最好在安装前就确定下来,因为GitLab安装完成后会把大量配置写进/etc/gitlab/gitlab.rb,还会根据这个URL生成Nginx配置和OAuth回调地址。中途修改虽然可行,但要重新跑一遍gitlab-ctl reconfigure,而且如果之前已经创建了项目,项目的Clone地址会全部变成旧地址,非常麻烦。
在写external_url的时候,有经验的运维都会直接在URL上区分HTTP和HTTPS,因为GitLab会根据这个URL自动决定是否生成SSL证书配置。生产环境强烈建议直接用https://开头。
3. 使用Omnibus包安装GitLab:完整步骤与关键参数
3.1 配置软件源:国内外网络环境都要知道的技巧
Omnibus包可以从GitLab官方仓库下载,但国内网络直连官方源的速度很不稳定,经常出现下载到一半断流的情况。我一般直接改用国内镜像源,速度和稳定性都靠谱得多。
以Ubuntu 20.04 LTS为例,使用清华镜像源的配置方法是:
# 安装基础依赖 sudo apt-get update sudo apt-get install -y curl openssh-server ca-certificates tzdata perl # 添加清华镜像源 curl -fsSL https://packages.gitlab.cn/repository/raw/script/setup.sh | sudo bash这里要说明一下,国内镜像源的方式不止一种,网上还能看到用mirrors.tuna.tsinghua.edu.cn/gitlab-ce的写法,但我实测下来,packages.gitlab.cn这个国内企业源稳定性和包更新的及时性都更好。
如果是CentOS、Rocky Linux这些RHEL系系统,需要先配置yum源:
# 添加GitLab CE源 cat > /etc/yum.repos.d/gitlab_gitlab-ce.repo <<EOF [gitlab-ce] name=GitLab CE Repository baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/ gpgcheck=0 enabled=1 EOF # 刷新缓存 sudo yum makecache3.2 安装GitLab CE并设置external_url
软件源配置好之后,安装命令反而是最简单的:
Ubuntu/Debian系:
sudo apt update sudo EXTERNAL_URL="http://gitlab.example.com" apt install gitlab-ceRHEL/CentOS系:
sudo EXTERNAL_URL="http://gitlab.example.com" yum install -y gitlab-ceEXTERNAL_URL环境变量是官方推荐的第一配置方式,它会在安装过程中自动写入/etc/gitlab/gitlab.rb。如果你安装的时候忘了设置,也完全不用慌,装完之后手动编辑配置文件一样能改:
sudo vi /etc/gitlab/gitlab.rb找到这一行,去掉注释并改成你的地址:
external_url 'http://gitlab.example.com'然后执行配置生效命令:
sudo gitlab-ctl reconfigure这里要多说一句,gitlab-ctl reconfigure是整个安装流程里最关键的步骤,它负责把GitLab所有组件(PostgreSQL、Redis、Nginx、Puma、Sidekiq等)初始化并启动。首次执行时间非常长,通常在3到10分钟之间,期间终端没什么输出变化,千万不要以为是卡死了就Ctrl+C中断。
3.3 安装过程中的常见"假死"现象
我见过太多人卡在这一步。运行reconfigure的时候,终端停留在某个Ruby任务半天不动,就急不可耐地关掉终端或者重启服务,结果下次启动直接乱套。
正确的做法是耐心等待,同时另开一个终端观察运行状态:
sudo tail -f /var/log/gitlab/gitlab-rails/production.log或者查看Nginx是否已经开始监听端口:
sudo netstat -tlnp | grep -E "80|443|8080"如果看到Nginx已经监听80或443端口,说明web服务已经起来了。这时候再用浏览器访问你设置的external_url,应该能看到GitLab的登录页面。
3.4 初始密码:隐藏了24小时就消失的那个文件
这是新手最容易卡住的地方。GitLab首次初始化后,root账号的初始密码会被随机生成并写入一个临时文件:
sudo cat /etc/gitlab/initial_root_password打开这个文件,你会看到类似下面的内容:
# WARNING: This value is valid only for the next 24 hours. # After the first sign in, the password will be automatically changed. Password: xxxxxxxxxxxx初始密码的有效期只有24小时,首次登录后系统还会强制要求修改密码。所以安装完一定要第一时间登录,把密码改成自己的,别等着第二天再处理,到时候初始密码过期就只能上控制台重置了。
这里顺便提一个应急重置密码的方法,如果你真的错过了初始密码也不用慌,可以用Rails控制台改:
sudo gitlab-rails console进入交互界面后输入:
user = User.find_by(username: 'root') user.password = '你的新密码' user.password_confirmation = '你的新密码' user.save!输入quit退出控制台,重新登录即可。
4. 首个仓库落地:改密码、关注册、配SSH、传代码
4.1 修改root密码并关闭对外开放注册
用root账号和初始密码登录GitLab后,系统会跳到修改密码页面。这里我建议直接把密码设成一个强密码,并找个密码管理器存起来。
登录进去之后第一步不是急着创建项目,而是先关掉对外开放注册。默认情况下GitLab是允许任何人注册账号的,如果你的服务器暴露在公网,就会被各种垃圾账号扫到。关闭路径在系统管理区域:Admin Area -> Settings -> Sign-up restrictions,把"Sign-up enabled"的勾选去掉,保存即可。
4.2 创建项目与群组:先建组再建项目
GitLab的权限管理模型是"群组(Group)-> 子群组(Subgroup)或者 项目(Project)"。我推荐有多个项目并行时,先创建一个群组,再在群组下面创建项目。
比如可以创建一个名为devops的群组,然后在这个群组下创建名为backend-service的项目。群组成员会自动继承群组的权限,不用每个项目重复设置一遍成员,管理成本非常低。
创建项目的时候,GitLab会问你要不要用README初始化仓库。如果是空项目,可以直接勾选初始化README,这样clone下来就有一个默认分支,省去手动commit的麻烦。
4.3 本机配置SSH Key:Push代码的第一步
创建完项目后,页面会提示你配置SSH Key,这是GitLab最常见的认证方式。在本地电脑上执行:
ssh-keygen -t ed25519 -C "youremail@example.com"一路回车生成默认密钥对,然后查看公钥:
cat ~/.ssh/id_ed25519.pub把公钥内容复制粘到GitLab的Preferences -> SSH Keys页面。这里强调一点,官方现在推荐ed25519算法,比老旧的RSA 2048更安全、密钥更短。如果你的机器上没有id_ed25519.pub,也可以生成RSA密钥:
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"SSH Key配置好之后,可以用以下命令测试连通性:
ssh -T git@gitlab.example.com看到Welcome to GitLab, @username!就说明认证已经通了。
4.4 用命令行推代码到GitLab仓库
配置好SSH后,在本地项目目录里执行:
git init git add . git commit -m "initial commit" git remote add origin git@gitlab.example.com:devops/backend-service.git git push -u origin main如果你是在已有的项目里操作,直接把远程仓库地址改到GitLab就行。这里有个小细节,2023年后新创建的GitLab项目默认分支名是main而不是master,push之前先确认一下本地分支名,避免推送时分支对不上又多一次冲突。
5. 换条路走:用Docker部署GitLab的完整流程与对比
5.1 Docker方式相对Omnibus包的优势和劣势
Docker方式这几年越来越流行,因为它把GitLab的依赖封装在容器里,宿主机上不需要装Ruby、PostgreSQL等一堆东西。我用Docker部署GitLab的体感是:
优点很明显:一是升级方便,修改image版本号后重新创建容器就行;二是排查问题时可以直接进容器操作,与宿主机隔离,不会搞坏系统环境;三是在开发机上临时起一个测试环境特别快。
缺点也同样明显:一是容器内文件系统是临时的,所有数据必须通过volume挂载到宿主机,如果不小心删掉容器又没挂好数据卷,数据直接归零;二是容器和宿主机之间的文件权限问题经常导致GitLab写文件失败。三是GitLab官方对Docker的支持虽然很成熟,但某些依赖组件(比如外置PostgreSQL、Redis)在容器模式下配置要麻烦一些。
5.2 docker run部署GitLab的关键参数说明
Docker部署GitLab官方镜像的命令大致如下:
sudo docker run --detach \ --hostname gitlab.example.com \ --publish 8443:443 --publish 8080:80 --publish 2222:22 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest逐个参数解释一下:
--hostname:相当于Omnibus方式里的external_url,GitLab会根据它生成Nginx配置。--publish:端口映射。8443:443表示用宿主机的8443端口映射容器的443端口(HTTPS),8080:80是HTTP端口,2222:22是SSH端口。生产环境SSH端口尽量不要映射成22,因为宿主机自己的SSH通常占用了22。--volume:数据卷挂载。config目录保存GitLab配置,logs保存日志,data是核心数据目录,包括Git仓库、数据库文件、上传文件等。这三个目录必须持久化,否则容器一重启全没。
创建完成后,等待容器初始化:
sudo docker logs -f gitlab看到gitlab Reconfigured!字样,就说明已经初始化完毕了。
5.3 Docker方式升级和数据迁移的注意事项
Docker方式升级GitLab非常简单,很多人最喜欢的就是这一点。升级流程一般是:
# 备份 docker exec -t gitlab gitlab-backup create # 拉取新版本镜像 docker pull gitlab/gitlab-ce:16.11.0-ce.0 # 停止并删除旧容器 docker stop gitlab docker rm gitlab # 用相同参数创建新容器 docker run ... gitlab/gitlab-ce:16.11.0-ce.0这里建议不要直接使用latest标签,GitLab大版本升级(比如从15升到16)时数据库迁移可能不兼容,最好指定确切的小版本号。升级前一定先看官方Upgrade Path文档,别跨好几个大版本一步到位,那会造成数据库无法迁移的惨案。
6. 高频故障与自救清单:502、内存告警、启动卡死
6.1 502 Whoops:刚启动最常见的那页白屏
访问GitLab看到502 Whoops, GitLab is taking too much time to respond.是刚安装完最常见的报错。它分两种原因。
第一种是reconfigure还没跑完,服务没有完全启动。这种情况只需继续等待,观察sudu gitlab-ctl status命令的输出,直到所有组件都显示run状态即可。
第二种是内存不足导致Puma或PostgreSQL起不来。用free -h查看内存情况,如果发现内存占用已经超过90%,建议先加Swap再启动:
# 创建4GB的Swap文件 sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab加了Swap之后重启一下GitLab:
sudo gitlab-ctl restart6.2 内存被占满:调整Puma和Sidekiq参数
GitLab默认配置比较激进,Puma会尝试把所有可用内存都利用起来。在8GB内存的机器上,GitLab跑一段时间后内存占用经常直奔6GB。
这时候需要手动限制Puma的worker数量。编辑/etc/gitlab/gitlab.rb:
puma['worker_processes'] = 2 puma['min_threads'] = 4 puma['max_threads'] = 8然后执行sudo gitlab-ctl reconfigure。这个值不是越大越好,worker太多会被内存拖累,太少在高并发下会有明显延迟。我实测4核8GB的机器,2个worker加8个线程对10人以内团队完全够用。
6.3 邮件发不出去:SMTP配置才是重灾区
很多团队装好GitLab后,发现密码找回邮件、CI通知邮件都发不出去。原因是GitLab默认没有配置SMTP服务器。
配置SMTP需要编辑/etc/gitlab/gitlab.rb,加入类似下面的内容:
gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "smtp.example.com" gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = "noreply@example.com" gitlab_rails['smtp_password'] = "yourpassword" gitlab_rails['smtp_domain'] = "example.com" gitlab_rails['smtp_authentication'] = "login" gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = true不同的邮件服务商配置各不相同,如果是企业邮箱一般在配置里能找到SMTP参数。配好之后跑gitlab-ctl reconfigure,然后在后台发一封测试邮件:Admin Area -> Settings -> 验证SMTP设置。
6.4 与Jenkins联动时的权限设置
GitLab最常见的联动场景就是和Jenkins做CI/CD。连接时需要在GitLab创建一个Personal Access Token,路径在Preferences -> Access Tokens。给Token至少勾选api和read_repository权限。Jenkins侧安装GitLab插件后,在"Manage Jenkins -> Configure System -> GitLab"里填入GitLab地址和Token,测试连接显示success就行。这里常遇到的问题是Jenkins服务器访问GitLab的SSH端口没有放通,或者Token权限没勾选导致拉代码401。
6.5 SSH克隆端口异常:默认22端口被抢占
如果服务器本身已经把22端口用于SSH登录,Docker方式的GitLab容器里SSH服务就无法映射到宿主机的22端口,必须映射成其他端口,比如前面的2222:22。这时候项目页面上展示的Clone地址是ssh://git@gitlab.example.com:2222/devops/backend-service.git,但如果你的DNS或hosts解析有问题,clone时依然会连不上。
解决办法是在本机~/.ssh/config里加一段配置:
Host gitlab.example.com Port 2222 User git这样git clone git@gitlab.example.com:devops/backend-service.git就会自动走2222端口,不需要每次手写端口。
7. 备份恢复与版本升级:平时多做一步,数据安全一大截
7.1 gitlab-backup备份和恢复
GitLab仓库最怕的不是服务器宕机,而是磁盘损坏或误删。我强烈建议无论环境大小,都配置定期备份。Omnibus包自带备份命令:
sudo gitlab-backup create默认备份文件存放在/var/opt/gitlab/backups/目录,文件名格式类似1717012345_2024_05_29_16.10.0_gitlab_backup.tar。
恢复备份前,先确认新环境GitLab版本与备份时的版本一致或兼容。恢复命令:
# 停止相关服务,避免数据写入 sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq # 恢复备份(输入文件名中时间戳和版本部分) sudo gitlab-backup restore BACKUP=1717012345_2024_05_29_16.10.0 # 重启服务 sudo gitlab-ctl start这里要特别提醒,备份不光是Git仓库本身,配置文件/etc/gitlab/gitlab.rb和密钥文件也要一起备份。没有正确的gitlab-secrets.json文件,即使恢复了数据库也无法解密仓库里的敏感信息。所以把整个/etc/gitlab目录都纳入备份计划是最稳妥的。
7.2 版本升级的正确姿势
GitLab升级最忌讳直接跨多个大版本跳,官方也不建议这样操作。升级前一定要先看官方Upgrade Path文档,确认从当前版本到目标版本的路线图。
以16.x为例,如果当前是15.11,想要升到16.11,必须按15.11 -> 16.0 -> 16.5 -> 16.11这样的步骤,每个大版本先升到最新的补丁版本,再进入下一个大版本。虽然看起来繁琐,但能有效避免数据库迁移失败。
升级前做好备份,然后执行:
sudo apt update sudo apt install --only-upgrade gitlab-ce或者从官方仓库下载指定版本的安装包,用dpkg -i或rpm -Uvh安装。升级完成后记得跑一遍sudo gitlab-ctl reconfigure让新版本配置生效。
7.3 日志查看:排查问题最锋利的刀
GitLab日志分布在多个路径,遇到问题别瞎猜,直接看日志是最快的方式。以下是我常用的几个:
# 总览所有服务状态 sudo gitlab-ctl status # Nginx访问日志和错误日志 sudo tail -f /var/log/gitlab/nginx/gitlab_access.log sudo tail -f /var/log/gitlab/nginx/gitlab_error.log # GitLab应用日志(看502、权限、认证问题) sudo tail -f /var/log/gitlab/gitlab-rails/production.log # PostgreSQL日志(数据库连接异常) sudo tail -f /var/log/gitlab/postgresql/current # Puma日志(Ruby进程崩溃) sudo tail -f /var/log/gitlab/puma/current排查的时候养成"先查内存、再查日志、最后看网络端口"的三步打法,90%的问题都能定位到根因。
我最后再分享一个小习惯:每次装完GitLab,我都会新建一个"管理员操作记录"页面,把安装日期、版本号、external_url、备份任务的cron表达式、SMTP配置这几项关键信息都记下来。几个月后再去维护这台服务器时,根本不用回忆当初怎么装的,直接翻记录就能对上。GitLab这类系统一旦用起来就是长期依赖,前期这些细致工作,往后会帮大忙。