最近后台收到好几个朋友问同一个问题:2026年了,想在自己服务器上装一套最新版GitLab,为什么网上教程都是零几年的老古董,照着一步步操作全是坑?我前阵子刚好帮团队在四台不同系统的机器上部署了一遍GitLab —— 一台Ubuntu 24.04、一台Debian 12、一台CentOS Stream 9,还有一台Windows上的测试服务器。折腾下来最大的感受是:GitLab官方文档其实写得相当清楚,真正让人头大的从来不是“命令敲不对”,而是不同系统之间依赖差异、软件源配置方式、权限模型和端口策略完全不一样,一套教程根本吃不下所有环境。
这篇文章我就把自己在2026年这个时间点部署最新版GitLab的完整过程、选型逻辑和踩坑记录整理出来。内容覆盖Linux系统(Debian/Ubuntu系、RHEL/CentOS系)和Windows/macOS环境下的常见安装路径,重点讲清楚每个命令背后的原因,以及装完之后的初始化配置、升级迁移和常见问题排查。适合运维、后端开发、团队技术负责人参考,也适合第一次接触自托管代码平台的新手照着操作。
1. 动手之前先定三件事:系统、硬件与域名规划
很多人拿到GitLab安装教程就开始敲命令,五分钟装完,半小时后发现自己在一个完全跑不动的环境里硬撑。我在部署之前会先把三件事定下来:用什么操作系统、机器配置够不够、域名和端口怎么规划。这三件事没想清楚,后面每一步都会别扭。
1.1 内存是第一道门槛:不同配置的真实表现
GitLab是一套综合体,不只是Web界面,它同时跑着Nginx、Puma(新版已经彻底用Puma替代了Unicorn)、PostgreSQL、Redis、Sidekiq、Prometheus等一堆组件。官方推荐配置是4GB内存起步,8GB才会“舒服”。但现实里很多人手头只有2GB甚至1GB的云主机,所以你需要知道不同配置下的真实表现:
| 内存 | 能否安装 | 实际体验 |
|---|---|---|
| 1GB | 可以装但基本跑不动 | 安装完成,reconfigure耗时很长,打开页面经常超时,Sidekiq频繁重启 |
| 2GB | 勉强运行 | 小团队(几人)代码托管和Issue能用,但推送大仓库时会卡顿 |
| 4GB | 推荐最低线 | 日常操作流畅,但CI并发跑起来压力明显 |
| 8GB及以上 | 推荐 | 多项目、多成员、CI Runner并发都相对稳定 |
如果你手头只有2GB,我的建议是安装前先配Swap。GitLab在刚启动时对内存的瞬时需求很高,我见过不少2GB内存机器装完以后Puma进程直接被系统杀掉的情况,加了4GB Swap之后才稳定下来。配置Swap很简单:
sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile不过要记住,Swap只是兜底方案,GitLab本身对磁盘I/O敏感,Swap用多了照样卡。有条件还是把内存加上去。
1.2 系统版本怎么选:LTS优先还是尝鲜
不同系统安装GitLab的难度差异,主要来自软件源配置和依赖库版本。我在2026年实测的几个系统里,体验排序大概是这样的:
- Ubuntu LTS(22.04/24.04):官方支持最完善,软件源脚本一键配置,依赖冲突最少。如果不是有特殊原因,这是省心程度最高的选择。
- Debian(12/13):和Ubuntu走同样的deb包路线,同样稳定。需要注意的是部分精简版Debian系统自带依赖不全,装之前先补基础软件包。
- CentOS Stream / RHEL系:走rpm包路线,整体也没问题,但默认的防火墙策略(firewalld)和SELinux会在装完后给你制造额外的“惊喜”,需要额外处理。
- Windows/macOS:官方不提供原生安装包,主流的做法是Docker容器化,或者干脆用虚拟机跑Linux。这在后面会单独展开。
系统选型的核心逻辑就一句话:能用Linux就用Linux,能用最新LTS版本就别用老版本。GitLab对较老系统的支持窗口是有限的,比如某些老版本系统在新版GitLab发布后很快就从官方支持列表中移除,等你想升级GitLab时会发现系统先不满足要求了,进退两难。
1.3 external_url决定后续一切:域名与端口想清楚再装
很多人忽略了这个看起来无关紧要的配置,实际上external_url是GitLab安装配置里最核心的一个选项。它决定了GitLab内置Nginx监听什么域名、生成的项目克隆地址长什么样、API和Webhook回调会往哪里发。
我见过最经典的错误是:装的时候图省事填了一个IP地址,比如http://192.168.1.100,结果后面配置了HTTPS证书,GitLab生成的克隆地址还是http://192.168.1.100,所有项目都要手动改地址,CI/CD里的Webhook全部要重新配置。
我的建议是,即使你现在没有正式域名,也请先在hosts里绑定一个,规划好最终要用的域名,比如http://gitlab.example.local或者https://git.example.com。同时想清楚端口策略:默认GitLab占用80/443,如果你机器上已经有其他Nginx在跑,就要提前给GitLab换端口,而不是装完再改,不然装完第一步reconfigure就可能听到端口冲突的报错。
2. Linux系安装:软件源配置与Omnibus包的前后细节
Linux系统上安装GitLab,主线方案只有一条:使用官方Omnibus安装包。这套方案把GitLab及其依赖的PostgreSQL、Redis、Nginx等全部打包成一套整体,安装完由gitlab-ctl统一管理,省去了手动装数据库和Web服务器的步骤。
2.1 为什么Omnibus包是官方推荐路径
网上有一些“源码安装”教程,告诉你从GitLab源码仓库拉代码、装一堆Ruby依赖、自己配数据库,最后还要手动维护Unicorn/Puma进程。我强烈建议你看到这类教程直接关掉。源码安装意味着每次升级都要手动处理依赖变动、数据库迁移、配置文件合并,任何一个环节出错都可能让整个服务起不来。
Omnibus包的好处在于:所有组件版本都经过官方测试和锁定,升级的时候只要换新包然后跑一遍gitlab-ctl reconfigure和gitlab-ctl upgrade,数据库迁移和配置文件检查会自动完成。它把“安装GitLab”这件事从一个复杂的系统集成项目,变成了“装一个软件包+改一个配置文件”的标准化操作。
2.2 Ubuntu/Debian系完整安装步骤
在Ubuntu 24.04上安装的过程,我完整梳理如下:
第一步,安装基础依赖:
sudo apt-get update sudo apt-get install -y curl openssh-server ca-certificates perl第二步,配置GitLab软件源。官方给出的方式是通过一个脚本自动添加:
cd /tmp curl -L https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash这个脚本做的事情包括:添加GitLab官方的apt仓库、导入GPG公钥、确认你的系统版本。执行完以后,软件源里就有了gitlab-ce包。如果你在的网络环境访问packages.gitlab.com很慢,可以把源地址替换为可访问的镜像站,把deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/这一行的域名换成对应的镜像地址。这一步影响的是下载速度,不影响后续任何功能。
第三步,正式安装。安装时就直接指定external_url:
sudo EXTERNAL_URL="http://gitlab.example.local" apt-get install gitlab-ce这一步会下载几百MB的安装包,安装完成后GitLab会自动执行初始配置,看到gitlab Reconfigured!就说明成功了。如果你忘记指定EXTERNAL_URL也没关系,装完之后可以在/etc/gitlab/gitlab.rb里修改,再执行sudo gitlab-ctl reconfigure同样生效。
2.3 RHEL/CentOS系完整安装步骤
CentOS Stream 9上整体流程类似,但有几个细节不同。首先是依赖安装用yum/dnf:
sudo dnf install -y curl policycoreutils openssh-server perl然后开启SSH服务(CentOS Stream默认有,但确认一下不会错):
sudo systemctl enable sshd sudo systemctl start sshd软件源配置同样用官方脚本:
cd /tmp curl -L https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash接着放行防火墙端口,这一步在Ubuntu上不需要,但在CentOS系上不做会直接导致外部访问不了:
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload最后安装:
sudo EXTERNAL_URL="http://gitlab.example.local" dnf install -y gitlab-ce2.4 两条路线的差异与软件源访问问题
Debian系和RHEL系在安装逻辑上没有本质区别,都是配源、装包、reconfigure三步。但有两个差异值得单独说。
第一,RHEL系的SELinux默认是开启的。如果SELinux状态是Enforcing,GitLab需要操作的一些目录和端口(特别是非默认端口)可能被拦截,导致服务看起来启动正常但访问时连接被拒绝。临时排查时可以先用setenforce 0确认是不是SELinux的问题,如果是就配置对应的SELinux策略,不要图省事永久关闭。
第二,软件源访问问题。GitLab官方源在国内和部分网络环境下访问速度不稳定,这个在2026年依然是很多人卡住的第一关。解决思路有两个:一个是前面提到的换镜像源,另一个是提前把安装包下载到本地,然后离线安装,也就是把.deb或.rpm文件传到目标机器上,用dpkg -i或rpm -ivh安装。离线安装的好处是不依赖网络环境,适合内网服务器。
3. Windows与macOS:容器化是绕不开的解法
在系统选型那节我提过,GitLab官方对Windows/macOS没有原生安装包。很多从Windows接触服务器的人第一次搜到这个消息会愣一下:连Windows这么主流的系统都不支持?确实不支持。GitLab官方设计上就是一个跑在Unix/Linux系系统上的服务,它对进程管理、socket并发、文件权限的依赖都很深,移植到Windows原生环境的成本和收益完全不成正比。
所以Windows和macOS上跑GitLab,主流方案就两个:Docker容器化,或者虚拟机跑Linux。前者轻量,适合开发测试;后者更接近生产环境,但资源占用高一层。
3.1 Docker方式跑GitLab CE的完整命令与参数说明
以Windows 11上装Docker Desktop为例,拉取官方镜像跑一个GitLab CE容器,核心命令是这样的:
docker run --detach \ --hostname gitlab.example.local \ --publish 8929:80 --publish 2224:22 \ --name gitlab \ --restart unless-stopped \ --volume $PWD/gitlab/config:/etc/gitlab \ --volume $PWD/gitlab/logs:/var/log/gitlab \ --volume $PWD/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest这里有几个参数需要解释清楚:
--hostname:对应GitLab内部的external_url域名,和Linux安装时那个EXTERNAL_URL是一个东西。--publish 8929:80:把容器的80端口映射到宿主机8929端口。为什么不用80?因为Windows上80端口经常被系统或其他程序占用,映射一个高位端口省去很多冲突麻烦。访问时用http://localhost:8929。--publish 2224:22:容器的22端口(SSH协议)映射到宿主机的2224端口。这样GitLab的SSH克隆地址端口会变成2224。--volume:数据持久化映射。这三条volume是把GitLab的配置、日志、数据都存到Windows本地目录,容器删除重建数据不丢。这是最容易被忽视的点,很多人图省事不映射volume,容器一删什么都没了。
容器第一次启动会自动执行初始配置,因为要初始化数据库和编译一堆资产,通常会等两三分钟,这个阶段看到容器状态是running但页面打不开是正常的,多等一会儿再看。
3.2 Docker Compose管理方式
跑测试环境用上面的docker run够了,但如果要在Windows/macOS上长期跑一个供团队使用的GitLab实例,我建议直接用Docker Compose,配置写进文件里,后续改端口、加卷、升级都清晰得多。
services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab restart: unless-stopped hostname: gitlab.example.local ports: - "8929:80" - "2224:22" volumes: - ./gitlab/config:/etc/gitlab - ./gitlab/logs:/var/log/gitlab - ./gitlab/data:/var/opt/gitlab然后:
docker compose up -d用Compose的好处是环境定义即文件,团队里任何人都能一键复现同一个GitLab环境。我自己的习惯是再配一个.env文件把端口和域名参数提取出来,避免写死。
3.3 macOS的Homebrew与Docker选择
macOS上除了Docker Desktop,还有人习惯用Homebrew装软件。我直说结论:Homebrew确实有和GitLab相关的formula,但那些要么是老版本,要么是社区维护的第三方包,不建议在2026年作为正式安装路径。macOS上最稳的还是Docker Desktop。
如果你不喜欢Docker Desktop的商业许可条款,也可以用colima(一个基于Lima的容器运行时)配合Docker CLI来跑。流程上安装colima后启动即可,后续docker命令和Desktop模式基本一致,但需要自己额外维护一些环境细节,对新手稍微多一层成本。日常开发和单机测试,Docker Desktop是省心选择。
4. 装完不等于能用:首次配置五连击
安装完成指令跑完、看到gitlab Reconfigured!,很多人就以为大功告成。实际上这个阶段GitLab只是“能启动”,距离“能正常使用”还有几步关键的初始化配置。我把新装实例必做的几件事总结成五个动作,按顺序做一遍基本不会漏。
4.1 首次访问与root初始密码
新装的GitLab(近几个大版本)首次访问时不会给你随机密码,而是让你在页面上自己设置root管理员的初始密码。这是一次性的,设置完就要记住:邮箱默认是admin@example.com,用户名root,密码是你自己设的那一串。
如果你装的是某些老教程对应的老版本,可能会出现初始密码存在/etc/gitlab/initial_root_password文件里的情况。新版本已经不再自动生成这个文件了,也不用再去翻。我第一次升级后发现找不到密码文件,还以为是安装有问题,后来才确认是版本行为变更。
4.2 修改external_url和时区
装的时候如果没指定域名,或者后来换了域名,需要修改/etc/gitlab/gitlab.rb:
external_url 'http://gitlab.example.local'如果不打算用域名,直接用IP也是常见的,但前面说过,后期改HTTPS会很麻烦。这里还是建议一开始就用最终域名。
时区配置在同一文件下:
gitlab_rails['time_zone'] = 'Asia/Shanghai'这两处改完都要执行:
sudo gitlab-ctl reconfigurereconfigure是GitLab里最常用的命令,它的作用是把你对gitlab.rb的修改翻译成实际服务配置,然后重启受影响的服务。修改任何配置之后都要跑一遍,这个习惯一定要养成。
4.3 HTTPS证书与端口调整
生产环境不可能一直用HTTP。我常用的方案有两个:一是用Let's Encrypt自动申请免费证书,GitLab原生支持;二是用内部CA签发的证书,适合纯内网环境。
Let's Encrypt方式需要在gitlab.rb里开启配置:
external_url 'https://gitlab.example.com' letsencrypt['enable'] = true letsencrypt['contact_emails'] = ['admin@example.com']然后reconfigure,GitLab会自动完成证书申请和续期配置。这种方式要求你的域名能公网解析到这台机器,且80端口能被Let's Encrypt验证服务访问到。
内网证书方式则是自己生成证书,然后把证书和私钥路径填到配置里:
nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.example.com.crt" nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.example.com.key"关于端口:如果80/443被占用,修改Nginx监听端口在这里:
nginx['listen_port'] = 8080 nginx['listen_https_options'] = 'ssl http2'改完reconfigure即可。注意端口一变,克隆地址和Webhook地址都会带上端口,团队里每个人都要同步更新习惯。
4.4 备份策略从第一天就要启动
GitLab里存的是代码、Issue、CI/CD配置、Merge Request记录,这些数据的价值不用多讲。我见过不止一个团队,用了大半年GitLab,从来没有做过备份,直到硬盘故障才发现恢复无门。备份策略一定要在装完当天就启动。
手工备份一条命令:
sudo gitlab-backup create新版GitLab的备份命令是gitlab-backup,老版本叫gitlab-rake gitlab:backup:create。备份文件默认生成在/var/opt/gitlab/backups目录。
我还建议你额外的备份三样东西:
/etc/gitlab/gitlab.rb:配置文件,丢了它备份数据也没法恢复/etc/gitlab/gitlab-secrets.json:保存着GitLab的各种加密密钥,这个文件丢了,即使有备份也恢复不了,因为加密数据解不开/var/opt/gitlab/backups目录下的备份文件本身
4.5 小内存优化项
如果你是在2GB内存的机器上跑GitLab,装完还要做几个瘦身动作,否则跑几天就会发现服务越来越慢,甚至直接OOM。我常用的优化项:
# 限制Puma worker数量 puma['worker_processes'] = 2 puma['min_threads'] = 1 puma['max_threads'] = 4 # 关闭不需要的监控组件 prometheus_monitoring['enable'] = false # 调低PostgreSQL缓存 postgresql['shared_buffers'] = "256MB"改了配置以后reconfigure生效。这些优化会轻微影响并发能力,但换来了小内存下的稳定运行,值得。等以后机器升级了,再把这些配置还原回去。
5. 从安装到升级的常见坑:我踩过的五处雷
安装过程本身不复杂,真正的挑战藏在各种“意外”里。我把自己在不同系统上踩过、也帮别人排查过的几个高频问题整理出来,每个都给出排查思路,不是直接丢结论,方便你遇到类似情况能自己顺着线索找根因。
5.1 系统时间不准导致服务起不来
现象:安装没报错,但打开页面提示证书过期或者登录请求异常。
这里的根因是系统时间和真实时间偏差太大。GitLab内部大量使用TLS和Token机制,时间不对会导致证书有效期校验失败、Session机制错乱。这个问题在离线安装的机器上尤其常见,很多内网服务器长期不开NTP。
排查方法:
date如果时间偏差明显,先校时:
sudo timedatectl set-ntp true sudo systemctl restart systemd-timesyncd校完时间再访问GitLab,很多莫名其妙的证书报错就消失了。
5.2 80/443端口被其他Nginx占用
现象:reconfigure时报出nginx相关错误,或者GitLab起来了但访问到的是另一个Web服务。
在已经有Web服务的机器上装GitLab是最容易撞这个坑的。GitLab内置了Nginx,默认监听80/443。如果系统里已经有一个Nginx在监听这些端口,GitLab的Nginx自然起不来。
排查方法:
sudo ss -tlnp | grep -E ':80|:443'看占用端口的进程是谁。解决方案有两种:一是让GitLab换端口,改/etc/gitlab/gitlab.rb里的nginx['listen_port'];二是关闭系统原有的Nginx,让GitLab独占80/443。
我的建议是,除非这台机器就是专职跑GitLab的,否则优先让GitLab换端口,避免影响已有的Web服务。
5.3 软件源超时或GPG签名校验失败
现象:配置软件源时能打开网页,但apt/yum更新时报超时,或者安装时提示GPG key验证失败。
软件源连接不稳定是2026年依然普遍存在的问题。超时可以直接换镜像源解决。GPG校验失败则通常是镜像源和官方源的key不同步,解决办法是把官方GPG key重新导入一次,或者改用官方源重新添加。
这里有个经验:很多人一遇到源的问题就怪网络,急着换各种源,其实很多情况下只是防火墙代理设置的问题。先把curl -I通不通测试一下,再决定换哪个源。盲目的多源切换只会留下安全隐患。
5.4 跨大版本升级先备份再查路线
现象:从老版本直接跳到最新版,升级后数据库迁移失败,服务起不来。
GitLab官方建议的升级策略是:大版本升级不要跨多个major版本直接跳。比如从16.x升到17.x没问题,但从15.x直接跳到17.x就会面临数据库结构变化过大导致的迁移风险。
我踩过最惨的一次,是把一个测试环境的GitLab从低版本直接升到最新版,升级过程中数据库迁移卡住,手动介入后迁移出了错误,最终只能从备份恢复。
正确流程是:
- 先执行
sudo gitlab-backup create备份 - 确认当前版本和要升级的目标版本之间的路径
- 如果需要跨多个大版本,先升级到中间版本,再继续下一个大版本
- 每次升级后都要跑
sudo gitlab-ctl reconfigure和sudo gitlab-ctl upgrade
欲速则不达,升级这种事,稳就是快。
5.5 备份恢复在不同系统之间迁移
现象:把一台机器的备份恢复到了另一台系统不同的机器,恢复完成后项目能看到,但仓库是空的。
备份文件里保存的是GitLab的PostgreSQL数据库数据、仓库文件、上传附件等。不同系统的文件路径基本一致(都是/var/opt/gitlab),理论上备份恢复是跨系统可用的。
但有个前提:恢复前要保证GitLab的版本一致。跨大版本恢复备份会有兼容问题。另外,恢复时一定要先把GitLab停掉再恢复,否则数据库还在写入,恢复过程会触发锁冲突:
sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq sudo gitlab-backup restore BACKUP=xxxx sudo gitlab-ctl reconfigure sudo gitlab-ctl restartBACKUP=后面填的是备份文件的名称,在/var/opt/gitlab/backups目录里能看到,不带_gitlab_backup.tar后缀。新版本恢复时会提示需要确认,因为恢复操作会覆盖现有数据,记得确认。
6. 说两个比安装更值得养成的习惯
安装只是用GitLab的第一步。我用了几年GitLab之后,发现真正影响长期体验的,往往是两个看起来不太起眼的运维习惯。
第一个习惯是:所有配置变更都以/etc/gitlab/gitlab.rb为中心,不要手动去改/var/opt/gitlab下的服务配置文件。GitLab的Omnibus设计思路是“gitlab.rb是唯一入口”,你手动改的任何组件配置,下次reconfigure就会被覆盖。我一开始不习惯这种设计,总觉得直接改Nginx配置更灵活,后来发现每次升级配置就被重置,才明白规范化的好处。配置文件里我习惯给每个修改项写上注释,注明修改日期和原因,一个月以后回头查改动记录会非常省心。
第二个习惯是:学会看日志,而不是遇到问题就重启。GitLab的日志查看命令是:
sudo gitlab-ctl tail nginx sudo gitlab-ctl tail puma sudo gitlab-ctl tail postgresql sudo gitlab-ctl tail sidekiqgitlab-ctl tail可以只查看单个服务的日志,对定位问题是决定性的帮助。很多人遇到故障的第一反应是gitlab-ctl restart全套服务重启,这样不仅浪费时间,还可能把关键错误信息冲掉。正确的做法是先翻对应服务的日志,找到第一处报错,再决定怎么处理。
最后想说的一点是:GitLab这套系统虽然组件多、依赖重,但它的运维模型其实非常规范。只要把规划(域名、硬件、系统)想清楚,安装(Omnibus包)走标准路径,初始化(配置、HTTPS、备份)做完整,后续的使用和维护都很顺。这比我早年折腾源码安装时的体验不知道好了多少。如果你正准备部署,记住我在文章里反复强调的那句话:装之前的规划,比装本身重要得多。