Homelab(8): 搭建自用 Gitlab 与 Docker 仓库

本文最后更新于:1 年前

为了托管一些私有的代码,折腾 CI/CD,我用 Docker 搭建一套自己的 Gitlab. Gitlab 社区版功能很强大, 包含且不限于 代码托管、容器镜像库,Gitlab Pages 以及 CI/CD。

搭建服务

我用的是 docker-compose 搭建的,Gitlab 版本为 14.1.1-ce.0, 整个镜像文件有 2.23G,配置文件如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
version: '3'
services:
web:
image: 'gitlab/gitlab-ce:14.1.1-ce.0'
restart: always
container_name: gitlab
hostname: 'gitlab.razeen.cn'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url "https://gitlab.razeen.cn"
letsencrypt['enable'] = false
nginx['redirect_http_to_https'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false
gitlab_pages['enable'] = true
gitlab_pages['inplace_chroot'] = true
pages_external_url "https://pages.razeen.cn"
pages_nginx['listen_port'] = 80
pages_nginx['listen_https'] = false
registry['enabled'] = true
registry_nginx['listen_port'] = 5050
registry_nginx['listen_https'] = false
registry_external_url "https://registry.razeen.cn"
gitlab_rails['gitlab_shell_ssh_port'] = 20022
gitlab_rails['gitlab_email_from'] = 'git@xxx.xxx'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "xxxx@xxxx.cn"
gitlab_rails['smtp_password'] = "xxxxxxx"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_domain'] = "exmail.qq.com"
grafana['enable'] = false
prometheus_monitoring['enable'] = false
ports:
- '127.0.0.1:19080:80'
- '127.0.0.1:19050:5050'
- '20022:22'
volumes:
- './config:/etc/gitlab'
- './data:/var/opt/gitlab'
- './logs:/var/log/gitlab'

在配置中,我们只使用了一个环境变量 GITLAB_OMNIBUS_CONFIG 就将我们需要的参数指定好了。其中主要开启了:

  • Gitlab
  • Pages (静态页面)
  • Registry (镜像仓库)
  • SMTP 服务

简要配置介绍如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# gitlab 服务的地址
external_url "https://gitlab.razeen.cn"

# 如果你开启了该选项, 可以自动申请并使用 Let\`s Encrypt 的证书,当然还要配合一些其他设置。 我这里由于 `HTTPS` 是我自己管理的就关闭了该选项;
letsencrypt['enable'] = false

# Gitlab 主服务 Nginx 的配置, 我把 HTTPS 关闭了,全部自己统计管理;
nginx['redirect_http_to_https'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false

# 有时会结合 CI/CD 部署一些静态页面,就把 Pages 开了。
gitlab_pages['enable'] = true
gitlab_pages['inplace_chroot'] = true
pages_external_url "https://pages.razeen.cn"
pages_nginx['listen_port'] = 80
pages_nginx['listen_https'] = false

# 镜像仓库是必须要有的,一些镜像放到内部,自用起来速度杠杠的。
registry['enabled'] = true
registry_nginx['listen_port'] = 5050
registry_nginx['listen_https'] = false
registry_external_url "https://registry.razeen.cn"

# 一些基础的配置,SSH 端口,以及 SMTP 邮件服务(我用的QQ的)。
gitlab_rails['gitlab_shell_ssh_port'] = 20022
gitlab_rails['gitlab_email_from'] = 'git@xxx.xxx'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "xxxx@xxxx.cn"
gitlab_rails['smtp_password'] = "xxxxxxx"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_domain'] = "exmail.qq.com"

# grafana 和 prometheus 我关了,后面自建
grafana['enable'] = false
prometheus_monitoring['enable'] = false


# 几个关键的端口先映射出来,80是服务端口,5050是镜像仓库,22就是SSH了。
ports:
- '127.0.0.1:19080:80'
- '127.0.0.1:19050:5050'
- '20022:22'

# 配置、数据、日志 目录也持久化一下
volumes:
- './config:/etc/gitlab'
- './data:/var/opt/gitlab'
- './logs:/var/log/gitlab'

配置好这些,镜像拉下来后,第一次等个几分钟就启动好了(取决于服务器性能)。。。

通配符证书申请

由于要开启 HTTPS, 证书少不了, 首先想到的是 Let`s Encrypt 的通配符了,结合 Acme 自动化,免费 且 省心。 但 Let`s Encrypt 目前在国内申请老不稳定,我就选用了 ZeroSSL 的通配证书, 两行命令搞定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 注册账户
docker run --rm -it \
-v "$(pwd)/acme":/acme.sh \
neilpang/acme.sh --register-account -m me@razeen.me --server zerossl

# 申请 ECC 证书, 我用的是 DNSPod 直接写上 DNS 服务商密钥的两个环境变量即可。
# 其他的还参考 https://github.com/acmesh-official/acme.sh/wiki/dnsapi
docker run --rm -it \
-v "$(pwd)/acme":/acme.sh \
--net=host \
-e "DP_Id=xxxx" \
-e "DP_Key=xxxx" \
neilpang/acme.sh --issue \
--dns dns_dp \
-d "razeen.cn" \
-d "*.razeen.cn" \
-d "*.pages.razeen.cn" \
--keylength ec-256 \
--dnssleep 300 \
--force

这样证书就申请好了,在$(pwd)/acme目录下可找到对应目录及文件。

自建 Nginx

由于机器上我有一些其他服务要用 Nginx, 我就统一用了同一个 Nginx, 配置如下。

  • Gitlab 服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
server {
listen 443 ssl http2;

server_name gitlab.razeen.cn;
server_tokens off; ## Don't show the nginx version number, a security best practice

## Increase this if you want to upload large attachments
## Or if you want to accept large git objects over http
client_max_body_size 0;

## Strong SSL Security
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
ssl_certificate /etc/nginx/ssl/razeen_wildcard.crt;
ssl_certificate_key /etc/nginx/ssl/razeen_wildcard.key;

ssl_verify_client optional;
ssl_client_certificate /etc/nginx/ssl/myroot.pem;
ssl_verify_depth 1;


# GitLab needs backwards compatible ciphers to retain compatibility with Java IDEs
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_tickets off;
ssl_session_timeout 1d;

access_log /var/log/nginx/access_gitlab.log;
error_log /var/log/nginx/error_gitlab.log;


## HSTS Config
## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
add_header Strict-Transport-Security "max-age=63072000";

# Rails sets a default policy of strict-origin-when-cross-origin, so
# hide that and just send the one we've configured for nginx
proxy_hide_header Referrer-Policy;
add_header Referrer-Policy strict-origin-when-cross-origin;


if ($http_host = "") {
set $http_host_with_default "gitlab.razeen.cn";
}

if ($http_host != "") {
set $http_host_with_default $http_host;
}



## https://github.com/gitlabhq/gitlabhq/issues/694
## Some requests take more than 30 seconds.
proxy_read_timeout 3600;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_http_version 1.1;

proxy_set_header Host $http_host_with_default;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-Ssl on;

proxy_set_header X-Real-IP $real_addr;
proxy_set_header X-Forwarded-For $forwarded_for;
proxy_set_header X-Forwarded-Proto https;

location / {
proxy_cache off;
proxy_pass http://127.0.0.1:19080;
}
}

  • 镜像仓库配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

server {
listen 443 ssl;
server_name register.razeen.cn;
server_tokens off; ## Don't show the nginx version number, a security best practice

client_max_body_size 0;
chunked_transfer_encoding on;

## Strong SSL Security
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
ssl_certificate /etc/nginx/ssl/razeen_wildcard.crt;
ssl_certificate_key /etc/nginx/ssl/razeen_wildcard.key;

ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_tickets off;
ssl_session_timeout 1d;


## HSTS Config
## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
add_header Strict-Transport-Security "max-age=63072000";

access_log /var/log/nginx/access_gitlab_registry.log;
error_log /var/log/nginx/error_gitlab_registry.log;

location / {

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;

proxy_read_timeout 900;
proxy_cache off;
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;

proxy_pass http://127.0.0.1:19050;
}
}
  • Pages 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
server {
listen 443 ssl http2;
server_name ~^(?<group>.*)\.pages\.razeen\.cn$;
server_tokens off; ## Don't show the nginx version number, a security best practice

## Disable symlink traversal
disable_symlinks on;

## Strong SSL Security
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
ssl_certificate /etc/nginx/ssl/razeen_wildcard.crt;
ssl_certificate_key /etc/nginx/ssl/razeen_wildcard.key;


# GitLab needs backwards compatible ciphers to retain compatibility with Java IDEs
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_tickets off;
ssl_session_timeout 1d;

access_log /var/log/nginx/access_gitlab_pages.log;
error_log /var/log/nginx/error_gitlab_pages.log;

## HSTS Config
## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
add_header Strict-Transport-Security "max-age=63072000";



# Pass everything to pages daemon
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Real-IP $real_addr;
proxy_set_header X-Forwarded-For $forwarded_for;
proxy_set_header X-Forwarded-Proto https;

proxy_cache off;
proxy_pass http://127.0.0.1:19080;
}
}

配置好后,我们就可以愉快的通过 HTTPS 访问了。到这我们 Gitlab 就搭建好了,功能使用我们就可以后面慢慢折腾啦。

最后,看一下我的管理界面(我还拼了个简单的Logo==)。

my-gitlab-admin