runsisi's

technical notes

Gitlab 环境搭建

2019-01-09 runsisi#git

源代码管理工具大致经历了 CVS、SVN、Git 三个阶段,由于 Git 的去中心化、无限分支等特点,当前几乎所有项目都使用 Git 或类似的工具(如 Mercurial)进行源代码管理。

gitweb[1] 等工具可以为本地 Git 仓库提供简单的浏览器访问界面,但当项目需要多人协作开发时,需要类似 Github 或 Gitlab 这种源代码托管平台为团队协作开发提供集中的代码存储、评审、测试、合入以及流程约束。除了云端的代码托管,Github 和 Gitlab 也都提供企业版产品用于搭建企业内部私有的代码托管平台,但相比之下,由于 Gitlab 提供免费的社区版本(即 Gitlab CE),因此对于一些预算有限的企业或者小团队,搭建内部的 Gitlab 环境是一个不错的主意。

除了 Gitlab 外,简单易用的 git 平台还包括:gogsgitea,如果是小的团队,既不愿意创建 github 的公开仓库,而免费的 github 私有仓库不能满足要求,Gitlab 又太厚重的话,gogs 或者 gitea 值得尝试。

Gitlab 在各常见的 Linux 发行版或云平台上都有相应的安装包[2],因此搭建环境相对来说非常简单,本文对 Gitlab CE 在 CentOS 7.x 系统上的环境搭建进行简单的总结,不涉及 Gitlab CI [3]相关的内容。

[1] https://git-scm.com/docs/gitweb

[2] https://about.gitlab.com/installation/

[3] https://about.gitlab.com/features/gitlab-ci-cd/

1. 下载

Gitlab CE 在 Linux 发行版上的安装包下载地址[1] 在国内可能已经被 GFW 屏蔽了,国内有清华大学的源可以直接下载安装包[2],但是缺少 SUSE、Oracle Linux 等发行版的支持,因此如果有必要的话可能需要翻墙。

本文下载的安装包为:gitlab-ce-10.4.1-ce.0.el7.x86_64.rpm。

[1] https://packages.gitlab.com/gitlab/gitlab-ce

[2] https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/

2. 安装

在 CentOS 7.x 上 Gitlab 的安装包是一个独立的 RPM 包,直接安装即可,由于可能缺少一些依赖包,因此使用 yum 进行安装:

~$ sudo yum install gitlab-ce-10.4.1-ce.0.el7.x86_64.rpm
Loaded plugins: fastestmirror
Examining gitlab-ce-10.4.1-ce.0.el7.x86_64.rpm: gitlab-ce-10.4.1-ce.0.el7.x86_64
Marking gitlab-ce-10.4.1-ce.0.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package gitlab-ce.x86_64 0:10.4.1-ce.0.el7 will be installed
...

3. 配置

Gitlab 的配置文件为:/etc/gitlab/gitlab.rb,Gitlab 有非常好的文档[1]指导配置,当修改该配置文件之后,需要执行 sudo gitlab-ctl reconfigure 使配置生效。

需要修改的配置项如下:

~$ sudo vi /etc/gitlab/gitlab.rb
# 外部访问 URL
external_url 'http://src.example.com'
# 从 Gitlab 发出的邮件发件人信息设置
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'git@example.com'
gitlab_rails['gitlab_email_display_name'] = 'git@example'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@example'
# 数据备份配置
gitlab_rails['backup_path'] = "/data/backup/gitlab"
gitlab_rails['backup_archive_permissions'] = 0644
gitlab_rails['backup_keep_time'] = 604800
# git 项目保存位置
git_data_dirs({
  "default" => {
    "path" => "/data/gitlab"
  }
})
# Gitlab 使用的邮件发送服务器配置
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtpserver.example.com"
gitlab_rails['smtp_user_name'] = "user-abc"
gitlab_rails['smtp_password'] = "password-xxx"
gitlab_rails['smtp_authentication'] = "login"
# Gitlab 自带的 nginx 配置
nginx['client_max_body_size'] = '1024m'
nginx['listen_addresses'] = ['192.168.abc.xxx']

执行 gitlab-ctl reconfigure 使得配置生效:

~$ sudo gitlab-ctl reconfigure
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["gitlab"]
Synchronizing Cookbooks:
...
Running handlers complete
Chef Client finished, 2/505 resources updated in 10 seconds
gitlab Reconfigured!

此时就可以通过 external_url 指向的 URL 访问 Gitlab。

gitlab-ctl 支持 start/stop/restart/status 等命令,来操作或查看 Gitlab 的服务状态:

~$ sudo gitlab-ctl status
run: gitaly: (pid 30315) 1007s; run: log: (pid 985) 345425s
run: gitlab-monitor: (pid 30333) 1007s; run: log: (pid 949) 345425s
...
~$ sudo gitlab-ctl restart
ok: run: gitaly: (pid 311) 0s
ok: run: gitlab-monitor: (pid 328) 0s
...

如果更改了头像等设置,可能需要清空缓存才能看到效果,可以使用如下命令:

~$ sudo gitlab-rake cache:clear

[1] https://docs.gitlab.com/omnibus/settings/README.html

4. 备份

Git 是一个去中心化的系统,所有人在本地都有一份项目的完整代码(包括历史记录),因此能够最大限度的保证代码的安全,但是对于 Gitlab 这样的代码托管平台而言,项目相关的 issue、用户、权限控制等并不是去中心化保存的,因此定时的备份以及提供发生故障时的恢复手段非常重要。

可以执行如下命令进行整个 Gitlab 环境的备份[1]:

~$ sudo gitlab-rake gitlab:backup:create > /dev/null 2>&1

通过 cron 定时任务在每天早晨的 7 点进行定时备份:

~$ crontab -l
0   7   * * * sudo gitlab-rake gitlab:backup:create > /dev/null 2>&1

备份数据以 tar 包的形式保存在 gitlab_rails['backup_path'] 指定的路径下,默认保存的时间由 gitlab_rails['backup_keep_time'] 控制,在我们前面的配置中为 604800 秒即 7 天,因此,按照每天备份一次的策略就是总是保存最近的 6 个备份 tar 包,如下所示:

~$ sudo ls -l /data/backup/gitlab/
total 51625908
-rw-r--r-- 1 git git 8919736320 Feb  4 07:05 1517699122_2018_02_04_10.4.1_gitlab_backup.tar
-rw-r--r-- 1 git git 8919787520 Feb  5 07:05 1517785529_2018_02_05_10.4.1_gitlab_backup.tar
-rw-r--r-- 1 git git 8921896960 Feb  7 07:08 1517958484_2018_02_07_10.4.1_gitlab_backup.tar
-rw-r--r-- 1 git git 8597186560 Feb  8 07:05 1518044729_2018_02_08_10.4.1_gitlab_backup.tar
-rw-r--r-- 1 git git 8595886080 Feb  9 07:05 1518131131_2018_02_09_10.4.1_gitlab_backup.tar
-rw-r--r-- 1 git git 8910428160 Feb 10 07:05 1518217537_2018_02_10_10.4.1_gitlab_backup.tar

注意:/etc/gitlab/ 目录需要手工备份。

[1] https://docs.gitlab.com/ce/raketasks/backup_restore.html#backup

5. 还原

前提条件:

  • 当前 gitlab 实例必须与生成备份的 gitlab 版本保持一致;
  • 当前 gitlab 实例必须至少允许过一次 sudo gitlab-ctl reconfigure
  • 当前 gitlab 实例必须处于运行状态,可以通过 sudo gitlab-ctl start 启动;
  • 修改 gitlab 配置文件并生效
~# vi /etc/gitlab/gitlab.rb
~# gitlab-ctl reconfigure

注意,该步骤是针对在另外的机器进行还原进行的,如果只是在原 gitlab 实例所在的节点进行还原操作,并不需要这一步。

  1. 将备份文件拷贝至 /etc/gitlab/gitlab.rb 配置项 gitlab_rails['backup_path'] 指定的文件夹中,且 chown 为 git 用户;
~# grep backup_path /etc/gitlab/gitlab.rb
# gitlab_rails['manage_backup_path'] = true
gitlab_rails['backup_path'] = "/data/backup/gitlab"
~# cp 1549950137_2019_02_12_11.7.5_gitlab_backup.tar /data/backup/gitlab/
~# chown git.git /data/backup/gitlab/1549950137_2019_02_12_11.7.5_gitlab_backup.tar
  1. 停止需要访问数据库的进程 unicorn 和 sidekiq
~# gitlab-ctl stop unicorn
~# gitlab-ctl stop sidekiq
# 检查进程状态
~# gitlab-ctl status
  1. 指定备份数据执行还原操作
~# gitlab-rake gitlab:backup:restore BACKUP=1549950137_2019_02_12_11.7.5
Unpacking backup ... done
Before restoring the database, we will remove all existing
tables to avoid future upgrade problems. Be aware that if you have
custom tables in the GitLab database these tables and all data will be
removed.

Do you want to continue (yes/no)? yes
Removing all tables. Press `Ctrl-C` within 5 seconds to abort
Cleaning the database ...
...
This task will now rebuild the authorized_keys file.
You will lose any data stored in the authorized_keys file.
Do you want to continue (yes/no)? no
Quitting...

注意 BACKUP 的参数为备份文件名去掉 _gitlab_backup.tar 后缀。

  1. 还原 /etc/gitlab/gitlab-secrets.json
~# cp gitlab-secrets.json /etc/gitlab/
cp: overwrite ‘/etc/gitlab/gitlab-secrets.json’? y
  1. 重启 gitlab 等待一小会等待 gitlab 完全起来再执行检查
~# gitlab-ctl restart
~# gitlab-ctl status
~# gitlab-rake gitlab:check SANITIZE=true
...
Uploads directory tmp has correct permissions? ... no
  Try fixing it:
  sudo chown -R git /var/opt/gitlab/gitlab-rails/uploads
  sudo find /var/opt/gitlab/gitlab-rails/uploads -type f -exec chmod 0644 {} \;
  sudo find /var/opt/gitlab/gitlab-rails/uploads -type d -not -path /var/opt/gitlab/gitlab-rails/uploads -exec chmod 0700 {} \;
  For more information see:
  doc/install/installation.md in section "GitLab"
  Please fix the error above and rerun the checks.
...
  1. 根据检查结果进行修改
~# chown -R git /var/opt/gitlab/gitlab-rails/uploads
~# find /var/opt/gitlab/gitlab-rails/uploads -type f -exec chmod 0644 {} \;
~# find /var/opt/gitlab/gitlab-rails/uploads -type d -not -path /var/opt/gitlab/gitlab-rails/uploads -exec chmod 0700 {} \;
  1. 再次执行检查操作,确认一切 OK
~# gitlab-rake gitlab:check SANITIZE=true

[1] https://docs.gitlab.com/ce/raketasks/backup_restore.html#restore

6. 其他

GFW 屏蔽了 Gravatar,因此默认情况下访问 Gitlab 环境会非常慢,因此需要以管理员身份登录 Gitlab,然后在 Settings 里面找到并去掉如下复选框的勾选以禁用 Gravatar。

avatar

但在当前的版本(至少 <= 10.4.3 版本)这会导致所有没有显式上传头像的用户头像都无法正常显式,当前可以根据 [1] 中提到的方法进行规避,一旦 MR [2] 合入,在新版本中就不需要通过规避手段来解决这个问题了。

[1] https://gitlab.com/gitlab-org/gitlab-ce/issues/38715#note_53491127

[2] https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16681