
CentOS 7 下用 RPM 包手动安装 GitLab这个话题在社区里问的人一直不少。尤其是这两年 Docker 虽然方便但很多内网环境、等保要求高的机房根本不给用容器或者你手里就是一台 2C4G 的旧服务器怎么省资源怎么来。我自己前前后后在内网部署过五六次 GitLab CE从最开始的踩坑踩到怀疑人生到现在基本半小时搞定中间积累了不少细节。这篇文章就把完整的 RPM 手动安装流程、版本选择逻辑、常见坑位排查一次性讲清楚照着做基本能一遍过。先说结论RPM 手动安装适合内网环境、离线部署、对版本有严格要求的场景相比 Docker 版它更贴近裸金属性能排错也更直接。但前提是你要理解它的依赖关系不能上来就rpm -ivh gitlab-ce.rpm一把梭那样大概率会撞上一堆依赖报错。下面从安装方式选型开始讲。1. 安装方式选型为什么我坚持用 RPM 手动装1.1 三种安装方式对比谁适合什么场景GitLab 官方提供的安装方式主要有三种Omnibus 包安装RPM/DEB、Docker 容器安装、源码编译安装。很多人一上来就选 Docker觉得一条命令搞定但实际用起来未必顺手。Docker 安装适合快速验证、资源隔离要求高的场景但数据卷管理、备份恢复、版本升级都比裸机复杂而且内网没有镜像源的时候光拉一个gitlab/gitlab-ce:latest就能卡半天。源码编译适合二次开发、深度定制但编译耗时极长依赖一堆 Ruby/Go 工具链日常部署完全不推荐属于自虐行为。RPM 安装Omnibus 包把 GitLab 所有的组件Nginx、Puma、PostgreSQL、Redis、Sidekiq 等全部打进一个包里统一用gitlab-ctl管理。安装过程虽然要手动处理依赖但装完之后服务管理、日志查看、备份恢复都非常直观跑在内网里占用的资源也比 Docker 少 20%~30%。我个人在实际项目里的选择标准是如果是临时演示环境用 Docker 没问题如果是公司正式用的代码仓库或者干脆是涉密内网一律 RPM。原因很简单RPM 装的 GitLab数据都在/var/opt/gitlab下备份直接打包这个目录就行不像 Docker 还要一层一层进容器里操作出了问题也好排查。1.2 RPM 方式的核心优势以及必须付出的代价RPM 包最核心的优势是版本锁定和可离线部署。比如你的项目组经过测试锁定 GitLab 15.11.x那你就把这个版本的 RPM 包存到本地以后不管是新服务器扩容还是灾备恢复都用同一个版本避免出现昨天还能跑今天升级完莫名其妙挂了的悲剧。但代价也很明确依赖需要手动解决。GitLab 的 RPM 包依赖policycoreutils-python、openssh-server、postfix等系统组件CentOS 7 最小化安装后这些默认都没有直接 rpm 安装必然报Failed dependencies。所以后面我会专门用一节讲怎么把这些依赖一次性装齐。注意CentOS 7 默认的 yum 源里不少包版本比较老比如policycoreutils-python有时候装不上需要先yum update或装 EPEL 源。这块我在第三节里给出了具体的命令。2. 环境准备CentOS 7 服务器要提前做哪些事2.1 硬件配置参考别拿 1G 内存挑战 GitLabGitLab 是一个吃内存的大户。官方给的推荐是 4GB 内存起步、2 核 CPU但那是理想状态实际跑起来 4GB 也就刚够用。我自己在 2G 内存的机器上跑过一次GitLab 页面能打开但随便一个仓库的页面加载都要等好几秒CI 跑起来更是直接 OOM。所以如果你手头的机器只有 2G 内存建议先加 swap具体在第五节会讲。磁盘方面系统盘放/至少留 20G 给 GitLab 本体代码仓库数据单独挂一个数据盘到/var/opt/gitlab。做好磁盘规划很重要因为 GitLab 后期数据增长很快我一个不到 20 人的团队跑了半年仓库数据就有 60 多 G里面包含大量二进制文件和 CI 产物。数据盘记得用 LVM 或者 xfs后面扩容量方便。2.2 系统初始化关闭防火墙还是放行端口这是个问题CentOS 7 默认开着 firewalldGitLab 装完后要访问 Web 页面需要放行 80/443 端口。有两种做法一种是直接关防火墙测试环境我经常这么干省事systemctl stop firewalld systemctl disable firewalld另一种是放行端口生产环境建议用这个firewall-cmd --permanent --add-servicehttp firewall-cmd --permanent --add-servicehttps firewall-cmd --reload另外 SELinux 也要提前处理。CentOS 7 默认是 EnforcingGitLab 的 Omnibus 包对 SELinux 的兼容性一直被人吐槽虽然官方说支持但真跑起来容易莫名其妙 502。我的做法是直接临时关闭或者等装完确认没问题再开回来setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config2.3 主机名和 hosts 解析提前想好域名GitLab 装完后访问地址取决于你在gitlab.rb里配置的external_url。如果你打算用 IP 访问那直接设成http://192.168.x.x就行。但如果你要用域名访问一定要提前在 DNS 或者各客户机的 hosts 文件里配好解析并同步修改服务器主机名因为 GitLab 内部很多地方会用到hostname -f。# 修改主机名 hostnamectl set-hostname gitlab.example.com # 编辑 hosts 确保本机解析到固定 IP echo 192.168.1.100 gitlab.example.com /etc/hosts3. 依赖处理与 RPM 包下载最容易被卡住的一步3.1 安装基础依赖一次性把坑填平GitLab 的 RPM 依赖项主要包含这几个openssh-server、postfix邮件通知用、policycoreutils-pythonSELinux 管理工具、perl、curl、telnet等。用以下命令一口气装齐yum install -y curl policycoreutils-python openssh-server postfix perl如果提示找不到policycoreutils-python说明你的 yum 源里没有这个包先执行yum update刷新源数据或者安装 EPEL 源yum install -y epel-release yum install -y policycoreutils-python这里插一句很多人装到一半卡住就是因为 yum 源里依赖包版本不全。CentOS 7 官方源在 2024 年进入维护期后部分包迁移到了 vault 源如果你用的是旧镜像建议先确认/etc/yum.repos.d/CentOS-Base.repo里的 baseurl 是否可用必要时替换为 vault.centos.org。启动 postfix 并设为开机自启systemctl start postfix systemctl enable postfix有个小细节如果 postfix 起不来多半是 25 端口被占用或者/etc/postfix/main.cf里的inet_interfaces没配置对。GitLab 发邮件不是核心功能临时不想折腾的话可以把 postfix 放在后面再弄GitLab 安装本身不强制要求 postfix 处于运行状态。3.2 GitLab 社区版 RPM 包怎么下版本怎么选GitLab 分社区版CE和企业版EE两者功能差异主要在权限管理、审计、多集群管理等功能上普通的代码托管需求 CE 完全够用而且免费。网上有人问 CE 和 EE 能不能互相转换理论上可以但没必要折腾直接 CE。下载渠道国内首选清华 tuna 镜像站速度快且稳定。在浏览器里打开https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/里面按版本号分目录结构类似gitlab-ce-16.0.1-ce.0.el7.x86_64.rpm gitlab-ce-16.0.2-ce.0.el7.x86_64.rpm ...选择版本时不要盲目追新。GitLab 每个大版本会调整底层组件比如 13.x 用 Puma 替换了 Unicorn14.x 之后默认数据库版本变化这些差异在你后续升级时要格外小心。我的建议是选择当前稳定版的前一个或两个 minor 版本例如最新是 16.10那部署就选 16.8 或 16.9。这样既避免最新版引入未知问题又能保证后续还有升级空间。下载命令用清华源wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.9.1-ce.0.el7.x86_64.rpm提示下载前看好文件大小GitLab 的 RPM 包通常在 700MB~1GB 之间小水管可能要下挺久。建议在服务器上直接 wget别在本地下了再传省一步。3.3 离线环境怎么搞把依赖和 RPM 包一起拷进去很多内网环境是不能上外网的这时候就要在一台能上外网的机器上用yumdownloader把依赖包拉下来再一起拷贝到内网。# 安装 yum-utils yum install -y yum-utils # 下载依赖包到当前目录 yumdownloader --resolve curl policycoreutils-python openssh-server postfix perl然后把下载好的所有 RPM 包连同 GitLab 主包一起传到内网服务器用rpm -ivh *.rpm批量安装。这里要注意安装顺序先把系统依赖装完再装 gitlab-ce 主包。如果依赖之间有嵌套依赖rpm -ivh会自动处理当前目录下的 RPM 文件所以直接一把梭也行但出错了不要慌看缺哪个单独装哪个就好。4. 手动安装 GitLab 全流程实录4.1 rpm 安装命令执行细节怎么判断装成功了依赖就绪后执行安装命令rpm -ivh gitlab-ce-16.9.1-ce.0.el7.x86_64.rpm看到Thank you for installing GitLab!字样就说明安装完成。安装过程会生成/etc/gitlab/gitlab.rb配置文件以及创建gitlab用户和一系列目录结构。值得注意rpm -ivh和rpm -Uvh有区别前者是全新安装后者是升级安装。首次部署用-ivh即可如果用-Uvh反而可能在系统里残留旧的配置信息。另外如果之前装过 GitLab建议先rpm -qa | grep gitlab确认一下避免重复安装导致配置文件被覆盖。4.2 修改 gitlab.rb 核心配置项装完之后最关键的步骤是编辑/etc/gitlab/gitlab.rb配置文件。这个文件是官方注释大杂烩有一千多行我们只需要改几个核心项其他保持默认。# 外部访问地址可以写 IP 也可以写域名 external_url http://gitlab.example.com # 时区默认是 UTC改成上海否则日志时间对不上 gitlab_rails[time_zone] Asia/Shanghai # 备份保留时间秒默认保留 7 天 gitlab_rails[backup_keep_time] 604800 # 关闭默认的 prometheus省内存2G 小内存机器强烈建议 prometheus_monitoring[enable] false这里重点说下external_url的注意点如果你设置了https://GitLab 会自动启用 SSL 配置这时候你需要准备证书否则页面打不开。第一次部署没有现成证书建议先用http://后续需要再加 HTTPS不要一上来就挑战高难度。4.3 重新配置与启动这条命令要跑挺久配置改完后执行关键的一步——初始化并启动所有组件gitlab-ctl reconfigure这条命令会完成以下工作生成配置文件、创建数据库、初始化 GitLab 内部的服务PostgreSQL、Redis、Puma、Sidekiq、Nginx 等、启动服务。执行时间取决于机器性能一般情况下 5 到 10 分钟慢的机器可能 20 分钟。期间要密切关注终端有没有报错。尤其是这一行Running handlers: Running handlers complete只要看到complete就说明 reconfigure 成功。如果中途报错最常见的是内存不足导致 PostgreSQL 起不来或者某个端口被占用参考第六节排查。全部完成后安装状态用以下命令确认gitlab-ctl status输出里所有服务的run状态都是ok就说明 GitLab 已经正常运行。常见输出大致长这样run: alertmanager: (pid 2749) 22s; run: log: (pid 2749) 22s run: gitaly: (pid 2791) 21s; run: log: (pid 2791) 21s run: logrotate: (pid 2812) 21s; run: log: (pid 2812) 21s run: nginx: (pid 2975) 19s; run: log: (pid 2975) 19s run: postgresql: (pid 2933) 20s; run: log: (pid 2933) 20s run: puma: (pid 2891) 20s; run: log: (pid 2891) 20s ...4.4 首次访问与管理员密码获取一切就绪后在浏览器里访问http://gitlab.example.com第一次会跳转到重置密码页面让你设置root管理员密码。这里有个坑如果你在浏览器里没有看到重置密码页而是直接到了登录页说明 GitLab 版本较新初始密码存在/etc/gitlab/initial_root_password文件里24 小时有效。cat /etc/gitlab/initial_root_password拿到初始密码后用root账号登录然后马上到「偏好设置」里修改密码并开启两步验证如果你所在团队有安全要求的话。我见过不少团队用默认密码用了大半年最后仓库被扒了才后悔这环节别偷懒。5. 小内存优化与日常维护基础操作5.1 2G 内存机器跑 GitLab怎么抢救一下如果你手里的服务器只有 2G 内存GitLab 装完很可能会出现页面转圈、刷新超时、git push 卡死的情况。我之前在一台 2G 的云服务器上试过跑 GitLab CE 15.x内存占用直接飙到 95%Puma worker 频繁被杀。抢救方案有两步亲测有效。第一步加 swap# 创建 4G swap 文件 dd if/dev/zero of/swapfile bs1M count4096 mkswap /swapfile swapon /swapfile # 写入 fstab开机自动挂载 echo /swapfile swap swap defaults 0 0 /etc/fstab第二步在gitlab.rb里进一步限制资源占用# 减少 puma worker 数量默认是 CPU 核数*2小内存改成 2 个 puma[worker_processes] 2 puma[min_threads] 1 puma[max_threads] 4 # 降低 sidekiq 并发 sidekiq[max_concurrency] 10 # 关闭一些不要的组件 prometheus_monitoring[enable] false grafana[enable] false改完执行gitlab-ctl reconfigure让配置生效。这样一顿操作下来2G 内存跑日常代码托管功能是没问题的但 CI 并发任务就别想了老老实实单跑。5.2 日志查看与日常巡检命令服务跑起来之后日常巡检主要靠这几个命令# 查看所有组件运行状态 gitlab-ctl status # 查看各组件日志 gitlab-ctl tail nginx gitlab-ctl tail postgresql gitlab-ctl tail puma # 查看整体日志 gitlab-ctl tailgitlab-ctl tail支持传组件名参数比如gitlab-ctl tail puma这样只输出 Puma 的日志排查 502 的时候特别有用。日志量大的时候用--lines参数控制输出行数比如gitlab-ctl tail puma --lines 200。还有一个容易被忽略的点磁盘空间监控。GitLab 在磁盘满了之后会出现各种诡异问题最常见的是数据库只读错误和 Git push 报 permission denied实际上就是没空间了。养成定期df -h的习惯配合日志清理脚本能避免大部分事故。5.3 备份与恢复别等数据丢了再后悔RPM 版 GitLab 备份非常直接一条命令gitlab-backup create备份文件生成在/var/opt/gitlab/backups目录是一个 tar 包命名类似1692432000_2023_08_19_16.9.1_gitlab_backup.tar。注意这个备份只包含 GitLab 的数据库和仓库数据不包含gitlab.rb配置文件和 SSL 证书。所以完整备份要加上这两个路径cp /etc/gitlab/gitlab.rb /var/opt/gitlab/backups/ cp -r /etc/gitlab/ssl /var/opt/gitlab/backups/恢复的原理很简单把备份文件放到同一台或新机器的/var/opt/gitlab/backups/目录下执行gitlab-backup restore BACKUP1692432000_2023_08_19_16.9.1这个命令会在恢复前清空当前数据库执行前务必确认你是在目标机器上、备份文件路径正确。恢复完成后执行gitlab-ctl reconfigure和gitlab-ctl restart让服务重新加载。6. 常见问题与排查技巧实录6.1 502 Bad Gateway一半以上的坑都在这GitLab 页面刷出 502 是新手遇到最多的问题根本原因通常是后端服务没起来Nginx 在等待上游响应时超时了。排查路径按照以下顺序走第一步看 Puma 状态gitlab-ctl status puma如果 Puma 是 down 的多半是启动报错了。查看日志gitlab-ctl tail puma一个很常见的原因是内存不足导致 Puma worker 起不来日志里出现Cannot allocate memory。另一个原因是 Puma 端口被别的进程占用GitLab 默认端口是 8080如果你的服务器上跑了 Tomcat、Jenkins 之类的东西很容易撞车。解决办法是改 Puma 端口# gitlab.rb 里 puma[port] 8088然后 reconfigure 重启即可。如果 Puma 起来了还是 502看下 Nginx 的日志gitlab-ctl tail nginx常见报错是connect() failed (111: Connection refused)说明 Nginx 和后端之间通信有问题多半是 Puma 监听的是/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket这个 socket 文件而权限不对导致 Nginx 无法连接。这时候检查/var/opt/gitlab/gitlab-rails/sockets/目录的属主是不是gitlab:gitlab不是的话chown -R gitlab:gitlab一下再重启服务。6.2 端口冲突GitLab 的 80 端口被占用了怎么办GitLab 内置的 Nginx 默认监听 80 端口。如果你机器上已经跑了其他 Web 服务比如宝塔面板、OpenResty那 reconfigure 时大概率会报Address already in use。解决方法是给 GitLab 的 Nginx 换一个端口比如 8081# gitlab.rb 里 nginx[listen_port] 8081 nginx[listen_https] false注意修改了端口之后访问地址要改成external_url http://gitlab.example.com:8081或者在 external_url 里不写端口、通过 Nginx 反代来转发。如果只是临时测试直接把external_url改成http://192.168.x.x:8081是最省事的。6.3 root 密码忘了怎么办一条命令重置如果你不小心忘了 root 密码在服务器上执行gitlab-rails runner user User.where(username: root).first; user.password YourNewPassword123; user.password_confirmation YourNewPassword123; user.save!这条命令通过 Rails Runner 直接操作数据库重置密码比去数据库改 hash 靠谱得多。执行成功后用新密码登录即可。注意密码复杂度要满足 GitLab 的最低要求至少 8 位包含字母和数字。6.4 git clone/push 时出现 Request Entity Too Large 或 413默认 Nginx 上传文件大小限制是 250MB如果你要推送大于这个体积的单个文件就会报 413。修改nginx[client_max_body_size] 1024m然后 reconfigure。这个配置对代码仓库本身影响不大但对 CI 产物、模型文件这类大文件友好很多。如果你的团队经常存二进制大文件建议给仓库开启 Git LFS大文件存储配置里也要同步调大限制。6.5 版本升级的坑从 16.x 升级到 17.x 前必看RPM 版升级 GitLab 时最容易犯的错误是跨大版本跳级。GitLab 官方强调版本升级必须逐个大版本升比如 16.9 → 17.0 → 17.1不能从 16.9 直接升到 17.5。跳级的后果是数据库迁移失败页面直接打不开恢复起来极其痛苦。正确的升级流程是先做一次完整备份gitlab-backup create逐个大版本升级rpm -Uvh gitlab-ce-17.0.x.rpm升级后执行gitlab-ctl reconfigure确认服务正常后再下载下一个大版本继续升级前建议读一下每个版本的升级文档尤其是涉及 PostgreSQL 主版本升级的耗时会比较长。如果升级过程中途失败不要慌用备份恢复回去先保持旧版本稳定运行再排查问题。7. 热词答疑GitLab 使用与 CI/CD 扩展常见疑问7.1 GitLab 账号是必须注册吗和 Jenkins 怎么对接GitLab 是私有化部署的代码托管平台账号体系是独立管理的需要由管理员在后台创建用户或者开启用户自助注册。企业内网部署建议关闭自助注册# gitlab.rb 里 gitlab_rails[gitlab_signup_enabled] false然后管理员在「管理区域 → 用户 → 新建用户」里手动添加。和 Jenkins 对接时常见做法是在 Jenkins 里安装 GitLab Plugin然后在 GitLab 的「用户设置 → 访问令牌」中生成一个 API Token填到 Jenkins 的系统配置里实现自动拉取代码或触发构建。GitLab 15 之后对 API Token 的权限划分更细生成时记得勾选api、read_repository、write_repository等对应权限。7.2 Git push 报 Login failed 或认证失败怎么排查Git 客户端 push 时报类似Login failed. Check API token or GitLab version的错误大多数情况是两种一是账号密码错误二是高版本 Git 客户端与 GitLab 旧版本在认证协议差异上不兼容。GitLab 15.0 之后移除了对弱认证方式的支持如果你的 Git 客户端版本过老加密算法不匹配就会出现登录失败。解决办法是升级 Git 客户端或者用 SSH 方式克隆仓库并配置 SSH 密钥。7.3 用 Docker 装的 GitLab怎么把数据迁到 RPM 版如果你之前用的是 Docker 版 GitLab想迁到 RPM 版流程是在 Docker 容器里执行gitlab-backup create把备份 tar 包拷贝到宿主机再拷贝到 RPM 版服务器的/var/opt/gitlab/backups/目录。复制 Docker 容器里的/etc/gitlab/gitlab.rb到 RPM 服务器的/etc/gitlab/gitlab.rb注意对比内容差异有些路径和配置项可能不兼容。在 RPM 版服务器上执行gitlab-ctl reconfigure然后执行gitlab-backup restore BACKUPxxx。迁移过程中最容易出问题的是数据库版本不一致。比如 Docker 镜像里的 PostgreSQL 是 14RPM 版默认可能是 12 或 13就需要先gitlab-ctl pg-upgrade把数据库升到对应版本再恢复。这一步非常耗时间建议在维护窗口做并且提前演练一遍。7.4 搭建 GitLab CI/CD 的硬件和版本要求GitLab CI/CD 是很多人搭 GitLab 的附带需求。如果你要在同一台服务器上跑 GitLab 和 GitLab Runner配置至少要 4C8G否则 CI 任务跑起来整台机器都会卡死。我的建议是GitLab 和 Runner 分开部署GitLab 放在稳定的服务器上Runner 用 Docker 模式跑在另一台机器或者直接用 Kubernetes 调度。CI 这块还有几个实用配置点Runner 注册时选择 executor 为 docker缓存目录挂载到本地磁盘避免重复下载依赖.gitlab-ci.yml里针对不同分支设置不同的构建和测试流程。GitLab 自带的 Container Registry 也可以直接启用在gitlab.rb里设置registry[enable] true然后配置 Nginx 的 5050 端口就能在仓库里直接存取 Docker 镜像。这样 CI 构建完直接推到 GitLab 内置的 Registry部署时在服务器docker pull下来整条链路不需要外部 Docker Hub内网部署特别合适。8. 写在最后的运维体会RPM 手动安装 GitLab 这件事看着繁琐但真正跑熟之后反而比 Docker 版更让人踏实。核心收获是你清楚每一个组件在系统里跑在哪个进程、日志在哪、配置在哪出了问题不用靠猜。GitLab 这个软件本身设计得挺完善大部分故障都是环境问题端口冲突、内存不足、磁盘写满、依赖缺失只要按本文的顺序排查都能快速定位。最后再分享一个我自己的习惯每次装完 GitLab我会第一时间在/etc/gitlab/gitlab.rb顶部加一段注释记录安装日期、RPM 包版本、以及改过哪些配置项。JiHu 或者 GitLab 官方升级文档里经常说确保你的配置是最新的如果没有记录dev 环境升级失败后回到生产环境都不知道改了什么。这个小习惯帮我省过好几次大麻烦希望对你有用。