2026 年在 DigitalOcean Droplet 上自托管 GitLab 指南
GitLab Community Edition 是一个替代方案,适合希望将源代码和 CI/CD 管道保存在自己的基础设施中,而不是依赖 GitLab.com 或 GitHub 的团队。在 DigitalOcean Droplet 上运行 GitLab 可以通过 Marketplace 一键应用或 Docker 进行,但您必须首先了解 GitLab 的资源限制,然后再选择规格,因为它将 Postgres、Redis、Sidekiq 和 Gitaly 全部组合在单一机器上。
目录
GitLab CE 的最低 Droplet 规格
GitLab 的官方文档规定了 Omnibus 安装的最低配置为 4 GB RAM 和 2 个 CPU 核心,适合拥有大约 20 个用户的小型团队。然而,GitLab 本身明确表示这个数字代表"运行的最低要求",而不是实际生产使用的推荐规格。gitlab-ctl reconfigure 流程以及在单一机器上并发运行 Puma、Sidekiq、PostgreSQL、Redis 和 Gitaly 的内存消耗远远超过预期。特别是在初始重新配置期间或运行重型 CI 作业时,GitLab 建议对于真实生产使用的单节点实例,至少需要 8 GB RAM,而不仅仅是用于测试。与 DigitalOcean 的 Droplet 层级相比,4 GiB RAM / 2 vCPU / 80 GB SSD / 4,000 GiB 传输流量的计划每月 $24,正好符合 GitLab 规定的最低配置,但在并发用户或 CI 运行器数量较多时感觉受限。8 GiB RAM / 4 vCPU / 160 GB SSD / 5,000 GiB 传输流量的计划每月 $48 对于每天活跃使用的 10-20 人团队来说达到了更好的平衡,为 Sidekiq 和 PostgreSQL 提供了足够的余地以避免持续交换。对于存储空间,除了 Droplet 附带的 SSD 外,存储库、CI 工件和容器注册表镜像的增长速度快于预期。配置 DigitalOcean Volumes,每 GiB 每月 $0.10,并将 /var/opt/gitlab/git-data 移到那里,让您可以独立调整大小,而无需迁移整个 Droplet。
- GitLab 规定最低配置为 4 GB RAM + 2 vCPU(约 20 个用户),但生产使用建议 8 GB 或更多。
- 4 GiB/2 vCPU/80 GB SSD Droplet 每月 $24 符合最低规格;适合测试或非常小的团队。
- 8 GiB/4 vCPU/160 GB SSD Droplet 每月 $48 是每天活跃使用的团队的最佳选择。
- 将存储库/工件存储分离到 DigitalOcean Volumes($0.10/GiB/月)以实现独立于 Droplet 的灵活调整。
通过 Marketplace 一键应用或 Docker 进行安装
让我们意外的一点是:DigitalOcean 在其 Marketplace 中包含 GitLab CE,创建 Droplet 时可以选择。系统自动在 Ubuntu 上安装 Omnibus 包。优势在于:无需手动安装命令,开启后 GitLab 在 cloud-init 完成后立即可用,通常需要 5-10 分钟。首次 SSH 连接时,您会找到设置外部 URL 的说明,通过编辑 /etc/gitlab/gitlab.rb 进行配置,然后运行 gitlab-ctl reconfigure 应用更改。另一个选择是 Docker,更适合想要完全控制卷、网络和资源限制的用户。名为 gitlab 的 docker-compose.yml 服务使用官方 gitlab/gitlab-ce:latest 镜像,且 hostname 从一开始就设置为您的真实域名。映射端口 '80:80'、'443:443' 和 '22:22'(如果端口 22 已在使用,可更改主机 SSH 端口),然后挂载三个卷:/etc/gitlab、/var/log/gitlab 和 /var/opt/gitlab 到主机路径,这样数据在容器重新创建时会保留。两种方法最终都运行相同的 Omnibus GitLab 软件;Marketplace 在裸操作系统上安装,而 Docker 在容器中运行,使后者更容易移动或通过卷副本进行备份。容器准备好后,通过 web UI 设置根密码,或检查 GitLab 在 /etc/gitlab/initial_root_password 中生成的临时密码,该密码在 24 小时后自动删除。
- Marketplace 一键应用自动在 Ubuntu 上部署 Omnibus GitLab;5-10 分钟内可用。
- Docker 设置使用
gitlab/gitlab-ce:latest镜像,映射端口 80/443/22 并挂载 /etc/gitlab、/var/log/gitlab、/var/opt/gitlab 卷。 - 两种方法都运行相同的 Omnibus GitLab;差异在于裸操作系统安装与容器化。
- 初始根密码在
/etc/gitlab/initial_root_password中,24 小时后自动删除。
域名和 SSL 配置
在设置 SSL 之前,将您的域名或子域名的 A 记录(例如 git.example.com)指向 Droplet IP 并等待传播,因为 Let's Encrypt 证书请求依赖于来自该 IP 的 HTTP 质询验证。对于 Omnibus 安装(Marketplace 或 Docker),编辑 /etc/gitlab/gitlab.rb 以设置 external_url 'https://git.example.com' 并使用 letsencrypt['enable'] = true 启用内置 Let's Encrypt。然后再次运行 gitlab-ctl reconfigure。系统会自动请求和安装证书,并设置 cron 作业进行续签。您不需要像常规网站那样进行单独的 Certbot 安装。一个需要注意的地方是:如果您的 Droplet 后面有启用了代理的 Cloudflare(橙色云),HTTP 质询可能会失败,因为 Let's Encrypt 看到的是 Cloudflare 的 IP,而不是您的 Droplet 的真实 IP。要么在首次证书请求期间临时禁用代理,要么改用 DNS 质询。对于已有 Nginx 或其他反向代理在前面的 Docker 部署,在 GitLab 内禁用 SSL 管理,让代理终止 SSL,以避免冲突的双层配置。设置后,通过 HTTPS 和 SSH 测试推送和拉取,以验证端口 22(或您为 git over SSH 分配的任何端口)仍然有效,因为同时更改 external_url 和 SSH 端口有时会中断现有的客户端连接。
- 将域名 A 记录指向 Droplet IP 并等待传播,然后再请求证书。
- 在
gitlab.rb中设置external_url和letsencrypt['enable'] = true,然后运行gitlab-ctl reconfigure。 - 如果使用 Cloudflare 代理(橙色云),在请求证书时临时禁用它或使用 DNS 质询。
- 如果已有反向代理在 Docker 容器前面,在 GitLab 内禁用 SSL 以避免冲突的配置。
GitLab 的备份和恢复
GitLab 包括通过 Rake 任务的内置备份工具。主要命令 gitlab-rake gitlab:backup:create 将存储库、数据库、上传、CI 工件和注册表镜像(如果已配置)打包到一个 tar 文件中,默认存储在 /var/opt/gitlab/backups 处。重要提示:此备份不包括配置文件或密钥。您必须单独备份 /etc/gitlab/gitlab.rb 和 /etc/gitlab/gitlab-secrets.json,因为没有密钥文件,即使恢复成功,您也无法解密原始数据库中存储的凭证。通过 gitlab-rake gitlab:backup:restore BACKUP=timestamp 进行恢复,指定来自备份文件名的时间戳。关键点:备份创建和恢复之间的 GitLab 版本必须完全匹配;每个版本的架构更改都不同,跨版本恢复经常失败。对于生产环境,设置 cron 作业以每天运行备份,并立即将备份文件和密钥复制到 Droplet 外,永远不要将它们保存在与生产相同的磁盘上。使用 DigitalOcean Spaces 配合 s3cmd 或 rclone 同步备份,或者以每 GiB 每月 $0.06 的价格拍摄 Droplet Snapshots,特别是在主要升级之前,因为快照让您可以比使用 Rake 恢复拼接更快地回滚整个系统。
- 使用
gitlab-rake gitlab:backup:create创建备份;文件保存到/var/opt/gitlab/backups。 - 备份不包括配置文件;始终单独保存
gitlab.rb和gitlab-secrets.json。 - 使用
gitlab-rake gitlab:backup:restore BACKUP=timestamp进行恢复,使用与备份相同的 GitLab 版本。
需要注意的资源限制
大多数人低估了 Omnibus 在一台机器上捆绑多个服务的事实:PostgreSQL、Redis、用于后台作业的 Sidekiq、用于存储库管理的 Gitaly、用于 web 服务的 Puma,以及启用时的容器注册表。它们都在单一 Droplet 上争夺内存和 CPU。在 4 GB Droplet 上,运行繁重的 CI/CD 作业同时有活跃用户经常会导致 Sidekiq 队列堆积或 web 界面缓慢。最常见的症状是系统严重交换,将页面加载从毫秒级变为秒级,或 gitlab-ctl reconfigure 中途卡住。如果使用 GitLab Runner 进行 CI/CD,在单独的 Droplet 上运行它,永远不要在主服务器上运行,因为繁重的 CI 作业可能会饱和 CPU 并中断并发用户的推送或拉取代码。磁盘空间是另一个陷阱,不仅仅是存储库,还有 CI 工件、日志和容器注册表镜像的累积速度远快于预期。如果没有自动清理旧工件的保留策略,磁盘会无声地填满,GitLab 会在没有警告的情况下停止。最后,升级版本带有限制:GitLab 强制执行您必须按顺序遵循的特定升级路径;在一次跳跃中跳过多个版本会冒数据库迁移失败的风险。始终阅读发行说明并计划增量升级,而不是放置数月后再一次性大幅跳跃。
- PostgreSQL、Redis、Sidekiq、Gitaly 和 Puma 全部一起运行,当负载激增时会争夺资源。
- 将 GitLab Runner 保存在单独的 Droplet 上,永远不要在主服务器上运行,以避免 CI 作业饥荒并发用户。
- 设置保留策略自动删除旧 CI 工件和注册表镜像,防止意外磁盘填满。
何时使用自托管 GitLab(真实用例)
在 Droplet 上自托管 GitLab 对于有明确理由将代码和数据保留在自己的基础设施中的团队是有意义的。示例:数据驻留法规要求源代码留在特定地理区域,或公司安全政策禁止将代码存储在第三方 SaaS 上。另一个常见情况是 CI/CD 运行器需要仅在内部可用的硬件或网络访问,当 GitLab 在同一私有网络上运行时更容易管理。寻求高级功能(如批准规则或高级 CI/CD)而不支付 per-seat SaaS 许可费用的小到中型团队可以使用 CE 自托管并跳过月度订阅,用运营开销换取功能访问。相反,拥有 20-30+ 活跃用户且真正需要高可用性的团队会超出单一 Droplet 的范围。他们需要参考架构将 Gitaly、PostgreSQL 和 Redis 分布在不同机器上,或者如果没有强制自托管的合规要求,他们应该考虑 GitLab.com SaaS。对于只有一两个运维人员的初创公司或小型开发团队,按本指南从单一 Droplet 开始,然后根据需要逐步扩展,比从第一天起过度设计复杂基础设施要好。
- 对于具有禁止第三方 SaaS 源代码的数据驻留或合规规则的团队理想。
- 适合需要直接访问内部硬件或网络的 CI/CD。
- 对于想要高级功能而无需 per-seat SaaS 费用的小型团队来说经济高效,前提是他们愿意管理运维。
- 超过 20-30 个用户或需要高可用性的团队应该升级到多机器参考架构或 SaaS。
常见错误及其修复方法
最常见的问题是 gitlab-ctl reconfigure 在 RAM 小于 4 GB 的 Droplet 上卡住或失败,通常是因为 PostgreSQL 迁移耗尽内存。快速修复:添加临时交换空间,然后重试 reconfigure。长期:将 Droplet 升级到 4-8 GB RAM。另一个常见陷阱是忘记在 DigitalOcean 的云防火墙中打开所需端口;默认规则通常仅允许 SSH,阻止 HTTP/HTTPS 访问。添加端口 80 和 443 的规则(如果启用了容器注册表,还有 5050)。DNS 未完全传播或 Cloudflare 代理掩盖真实 IP 时,SSL 证书请求经常失败。在重试 reconfigure 之前,使用 dig 或 nslookup 验证您的域名解析到 Droplet 的 IP。备份恢复失败是因为已安装的 GitLab 版本与备份的创建版本不匹配;始终先安装原始版本,恢复,然后升级,永远不要跨版本恢复。最后,磁盘会因 CI 工件累积而无声填满。通过在每个项目的 CI/CD 设置中设置工件过期策略或定期运行 Rake 任务来清理过期工件来修复。
- reconfigure 在低 RAM 时卡住/失败 → 添加临时交换,然后长期将 Droplet 升级到 4-8 GB。
- 即使 Droplet 正在运行,也无法访问 web 界面 → 检查云防火墙是否打开了端口 80/443(以及 Registry 的 5050)。
- SSL 证书请求失败 → 使用 dig/nslookup 验证 DNS 传播,如果需要临时禁用 Cloudflare 代理。
最佳实践
从为未来增长留有余地的 Droplet 规格开始,而不是最低配置,因为调整大小需要重启,这会影响所有活跃用户。通过 gitlab-rake gitlab:backup:create 在 cron 中设置每日自动备份,并立即使用 s3cmd 或 rclone 将备份文件与 gitlab-secrets.json 和 gitlab.rb 同步到外部位置,如 DigitalOcean Spaces。永远不要将备份保存在与生产相同的磁盘上。在每次主要版本升级前拍摄 Droplet Snapshot 以实现快速回滚,如果出现问题,比 Rake 恢复快得多,后者需要更长时间重新组装。启用 DigitalOcean 的云防火墙,并将 SSH 访问限制为已知 IP,而不是整个互联网。为 GitLab 的根和管理员账户打开 2FA。使用 DigitalOcean 监控设置警报,在 RAM 或磁盘使用率超过阈值时通知您,这样您就可以在系统崩溃前知道。随着团队的增长和 CI/CD 作业强度增加,尽早启动单独的 GitLab Runner Droplet,在主服务器的 CPU 成为瓶颈之前。最后,定期监控 GitLab 的发行说明,并按一致的时间表计划增量升级,而不是跳过版本数月然后尝试大幅跳跃,后者风险大得多。
- 选择具有增长空间的 Droplet;调整大小需要重启,影响所有用户。
- 通过 cron 自动化每日备份,立即同步到外部存储(Spaces、Rclone),始终包括 gitlab-secrets.json。
- 在主要升级前拍摄 Droplet Snapshots 以实现比 Rake 恢复更快的回滚。
- 通过云防火墙限制 SSH,为 GitLab 的管理员账户启用 2FA。
- 设置 DigitalOcean 监控警报以在系统用尽前获得 RAM/磁盘警告。
常见问题(FAQ)
gitlab-rake gitlab:backup:create,然后在同一脚本中添加一个步骤,将备份和 gitlab-secrets.json 复制到外部存储(如 DigitalOcean Spaces),通过 s3cmd 或 rclone,这样备份不会仅位于生产磁盘上。