0%

云服务器上搭建gitlab和gitea的方法

趁着618搞活动,以极低的价格买了一个云服务器。想着折腾点什么。发现可以自己搭一个git服务器。

开始的时候我试着装了装Gitlab。因为Gitlab CE版本是开源免费的,而且看到有些企业也在用。装上去运行后发现2核2G的云服务器直接卡死了,连ssh都登录不了。

后来又发现了gitea。这是一个轻量的git服务器。虽然没有gitlab那么多功能,但占用内存极少。在2核2G的云服务器上运行甚是欢快。

下面记录了安装和折腾过程。enjoy~~

安装Gitlab

拉取gitlab的docker镜像

1
docker pull gitlab/gitlab-ce:latest

新建一个存放gitlab的目录

1
mkdir -p ~/docker/docker_gitlab

新建配置文件

1
2
cd ~/docker/docker_gitlab
vim docker-compose.yml

将下面的内容贴进去。其中xx.xx.xx.xx需要修改成自己机器的ip地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3.1'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://xx.xx.xx.xx:8929'
gitlab_rails['gitlab_shell_ssh_port'] = 2224
ports:
- '8929:8929'
- '2224:2224'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'

启动Gitlab

1
sudo docker-compose up -d

关掉Gitlab

1
docker-compose down

重启docker

1
systemctl restart docker

查看启动日志

1
docker-compose logs -f

云服务器中设置gitlab端口放行

image-20220619002611885

查看gitlabroot用户的初始密码

进入到gitlab容器内部

1
docker exec -it gitlab /bin/bash

查看root初始密码

1
cat /etc/gitlab/initial_root_password

参考:

5分钟搭建自己的代码托管平台gitlab

https://zhuanlan.zhihu.com/p/387979095

选择gitea来搭建git服务器

相比较与gitlabgitea则轻量很多。在我买的服务器都不能流畅运行gitlab后,果断投入了gitea的怀抱。gitea的轻量和快速让我非常惊讶。下图展示了它的内存占用。

image-20220623211719230

这可比动辄吃掉3个多G的gitlab要来的清爽。

但是针对大型企业还是会选择gitlab的。因为它是一个大而全的东西。gitea因为轻量,势必会缺少一些功能。但对于个人和小团体来说已经是够用了。gitea官方有一张与gitlab的功能对比表。可以查看下面的网址了解一下。

https://docs.gitea.io/zh-cn/comparison/

安装gitea

使用docker来安装

在服务器中新建一个存放gitea数据的目录。

1
mkdir -p /usr/local/docker/docker_gitea

新建一个docker-compose.yml文件

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
version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.16.8
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- DB_TYPE=mysql
- DB_HOST=db:3306
- DB_NAME=gitea
- DB_USER=gitea
- DB_PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db

db:
image: mysql:8.0.29
restart: always
environment:
- MYSQL_ROOT_PASSWORD=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=gitea
- MYSQL_DATABASE=gitea
networks:
- gitea
volumes:
- ./mysql:/var/lib/mysql

使用下面的命令启动gitea

1
docker-compose up -d

更新gitea版本

只需要更新docker-compose.yml中的版本号。

1
image: gitea/gitea:1.16.8

查询gitea是否启动

1
docker-compose ps

查看gitea启动的log

1
docker-compose logs

需要在云服务器中的防火墙设置里打开相应的端口,此处是3000222

image-20220623231704309

使用nginx设置反向代理

每次访问gitea服务都在url后面加3000端口确实不太好看,也不方便。所以这里使用nginx反向代理。

ubuntu20安装nginx (云服务器里安装的ubuntu20.04)

1
2
sudo apt update
sudo apt install nginx

安装好后nginx会自动启动,可以用下面的命令查询nginx的状态

1
sudo systemctl status nginx

这时直接用浏览器访问服务器IP就可以看到nginx的欢迎界面了。

image-20220623222612567

配置反向代理

nginx 配置文件都在/etc/nginx/目录下。

修改nginx的配置文件/etc/nginx/nginx.conf,配置反向代理。

添加下面的内容到http下。

配置可参考:https://www.runoob.com/w3cnote/nginx-setup-intro.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name example.cn;[此处填写域名]
client_max_body_size 100M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://xx.xx.xx.xx:xxx; #设置ip和端口
}
location ~ .*\.(js|css|png)$ {
proxy_pass http://xx.xx.xx.xx:xxx; ##设置ip和端口
}
}

默认情况下,nginx 有一个上传单个文件大小限制,上传大于限制大小的文件会返回 413 错误,其大小限制默认值为 1MB

报错信息:

1
2
3
4
5
6
7
8
9
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 1.90 MiB | 8.94 MiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413
fatal: the remote end hung up unexpectedly
fatal: the remote end hung up unexpectedly

所以在上面的配置中加了client_max_body_size 100M;,以便修改这个限制。

检测配置文件语法是否正确

1
sudo /usr/sbin/nginx -t

重启nginx

1
sudo /usr/sbin/nginx

重新加载配置

1
sudo /usr/sbin/nginx -s reload

停止nginx

1
sudo /usr/sbin/nginx -s quit

配置gitea服务器的域名

打开docker_gitea/gitea/gitea/conf/app.ini文件。

修改DOMAINSSH_DOMAINROOT_URL的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = example.cn [这里填写域名]
SSH_DOMAIN = example.cn [这里填写域名]
HTTP_PORT = 3000
ROOT_URL = http://example.cn/ [这里填写域名]
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_CONTENT_PATH = /data/git/lfs
LFS_JWT_SECRET = XPTkmc3bXNfcDN3Nc5RmQcu-WZYmashiQpOAmlBJZ_M
OFFLINE_MODE = false

修改好后就可以保存,然后重启gitea

关闭gitea

1
docker-compose down

启动gitea

1
docker-compose up -d

设置域名解析

在腾讯购买域名后就可以使用DNSPod工具设置域名解析了。

image-20220623233107472

这里设置的git是域名的前缀,可以以此来区分不同的服务。记录值中填写服务器的公网IP。

这时我们就可以通过域名直接访问gitea服务器了。

设置容器ssh直连

目前可以使用http来克隆和推送代码了。但是容器的ssh接口映射到了主机的非标准接口,所以无法使用ssh来克隆和推送代码。

官方提供的设置的说明,可参考下面的链接。

https://docs.gitea.io/zh-cn/install-with-docker/#ssh-%E5%AE%B9%E5%99%A8%E7%9B%B4%E9%80%9A

数据迁移

如果想把git仓库的数据迁移到另外的服务器中,需要把gitea打包好拷贝到新的服务器中。

image-20220705085221952

同时mysql的备份需要先进入到mysql的docker环境中。

1
docker exec -it 2f986a21f76c /bin/bash  #2f986a21f76c 为docker container id

使用下面的命令备份数据库

1
mysqldump -uroot -pgitea --all-databases>all.sql

恢复数据库时,先启动gitea 的docker环境,让其生成mysql文件夹。

然后把之前备份好的all.sql文件拷贝到mysql文件夹中。

查看启动好的mysql docker id

1
docker ps -a

进入到mysql的docker环境中后进入到/var/lib/mysql目录中。

1
cd /var/lib/mysql

运行下面的命令恢复数据库

1
mysql --default-character-set=utf8mb4 -u 'root' -p <all.sql

提示输入密码时输入gitea

最后在gitea/gitea/conf/app.ini文件中重新配置一下gitea的域名。就是下面的SSH_DOMAINDOMAINROOT_URL

参考https://docs.gitea.cn/en-us/administration/backup-and-restore/

搭建Drone CI

Drone的官方文档:

https://docs.drone.io/

Drone是一个基于Docker技术的轻量CI/CD工具。它分为两个部分serverrunnerserver主要是对接Git服务器,获取仓库内容并解析pipeline文件。runner则运行pipeline文件中定义的内容。有多种runner可以使用。具体的介绍可以参考下面的网址:

https://docs.drone.io/runner/overview/

image-20220628232746375

比较常用的runnerDocker Runner。该runner会拉取相应的docker镜像,然后在镜像中运行定义的内容。

值得一提的是,runner是可以不和server运行在同一台服务器上的。多个runner也可以分别在不同的服务器上运行。

安装drone server

根据实际情况,修改下面的脚本并在云服务器上运行即可。

获取GITEA_CLIENT_IDGITEA_CLIENT_SECRET

gitea中添加一个OAuth2 Applications,以便Drone可以使用它访问gitea

需要注意的是Redirect URI中的域名需要添加login。并且如果域名申请的了SSL证书(可在DNSPod中操作),则使用https

获取SHARED_SECRET

使用下面的命令生成一个shared_secret

1
openssl rand -hex 16

使用脚本安装drone server

将上面获取到的内容修改到下面的脚本中。给脚本添加执行权限,然后运行即可。

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
#!/usr/bin/env bash

set -ex

GITEA_CLIENT_ID=0107e4c7-d1e8-4380-97f9-032f9eddc5e8
GITEA_CLIENT_SECRET=E6ibrZo8H3F3WNplLZITIkoJAVJAO2G99AxSQ2dhtPZZ
SHARED_SECRET=ac3963bc7225da1126185d1b88d5fddf
SERVER_HOST=drone.betainnovation.cn
SERVER_PROTOCOL=https

docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/lib/drone:/data \
--env=DRONE_GITEA_SERVER=http://git.betainnovation.cn/ \
--env=DRONE_GITEA_CLIENT_ID=${GITEA_CLIENT_ID} \
--env=DRONE_GITEA_CLIENT_SECRET=${GITEA_CLIENT_SECRET} \
--env=DRONE_AGENTS_ENABLED=true \
--env=DRONE_RPC_SECRET=${SHARED_SECRET} \
--env=DRONE_SERVER_HOST=${SERVER_HOST} \
--env=DRONE_SERVER_PROTO=${SERVER_PROTOCOL} \
--env=DRONE_TLS_AUTOCERT=true \
--publish=80:80 \
--publish=443:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:2.12.1

安装Docker Runner

根据实际情况,修改下面的脚本并在云服务器上运行即可。

这里的SHARED_SECRET跟上面安装server使用的要保持一致。

AGENT_SERVER_HOST就是drone server的域名。

修改好下面的脚本内容,添加执行权限然后运行即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env bash

set -ex

SHARED_SECRET=ac3963bc7225da1126185d1b88d5fddf
AGENT_SERVER_HOST=drone.betainnovation.cn
SERVER_PROTOCOL=https

docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--env=DRONE_RPC_PROTO=${SERVER_PROTOCOL} \
--env=DRONE_RPC_HOST=${AGENT_SERVER_HOST} \
--env=DRONE_RPC_SECRET=${SHARED_SECRET} \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_RUNNER_NAME=docker_runner_1 \
--publish=3000:3000 \
--restart=always \
--detach=true \
--name=drone-docker-runner-agent-01 \
drone/drone-runner-docker:1.8.2

编写pipeline

参考网址:

https://docs.drone.io/quickstart/docker/

默认情况下,执行pipeline时会在前面加上clone操作。

image-20220628232455981

pipeline示例:

下面的示例显示了如何使用飞书来发送构建信息。

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
kind: pipeline
type: docker
name: default

steps:
- name: greeting
image: alpine
commands:
- echo hello
- echo world


- name: feishu Notice success
pull: if-not-exists
image: hb0730/drone-plugin-notice:1.0.2
settings:
debug: true
notice_web_hok:
from_secret: feishu-robot-webhook
notice_secret:
from_secret: feishu-robot-secret
notice_type: feishu
message_type: markdown
message_at_all: true
message_title: Drone 构建通知
message_content: |
### 构建信息
> - 应用名称: [DRONE_REPO_NAME]
> - 构建结果: 预发布成功 ✅
> - 构建发起: [CI_COMMIT_AUTHOR_NAME]
> - 持续时间: [CUSTOM_BUILD_CONSUMING]s

构建日志: [点击查看详情]([DRONE_BUILD_LINK])
when:
status: success

设置飞书机器人

我们可在聊天群添加飞书机器人。

在群设置里,添加BOTS

image-20220628235812271

这里添加自定义机器人。这个类型的机器人可以使用webhook来交互。

将生成的Webhook URL设置到插件中即可。上面的示例是使用的drone secret。这个需要在drone server中配置。

image-20220629000258397

feishu插件参数 plugin params

  • notice_access_token (required) : 自定义机器人的 webhok

  • notice_type (required) : 机器人类型: dingtalk,feishu

  • message_type (required) : 消息类型: text,markdown

  • notice_secret : 如果设置了加签 , 可以把你的加签密钥填入此项完成加签操作。

  • message_at_all : 是否At所有人

  • message_at_mobiles : 你需要@的群成员的手机号,多个时用英文逗号(,)分隔 , 目前只支持 dingtalk

  • message_title : 标题,只支持markdown

  • message_content : 内容,支持占位符[] 替换,支持当前所有环境变量

  • debug : debug模式,打印env等信息

  • custom_started 开始时间环境变量,如:DRONE_BUILD_STARTED

  • custom_finished 完成时间环境变量,如:DRONE_BUILD_FINISHED

  • CUSTOM_BUILD_CONSUMING : 构建时间(秒)

使用Sonarqube扫描C/C++语言的项目

SonarQube的下载链接:

https://www.sonarqube.org/downloads/

SonarQube提供了下面多个版本。个人用途的话可以使用开源免费的社区版本。但是社区版本是不支持C/C++扫描的。好在有大神做了一个插件来解决这个问题。

image-20220711221722225

基于Docker安装SonarQube

  1. 拉取docker镜像
1
docker pull sonarqube:8.9.9-community

注意:当前的长期支持版为8.9.9,所以这里拉取这个版本。

  1. 新建一个docker_sonarsqube目录,并在里面创建一个docker-compose.yaml文件。写入下面的内容。
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
version: '3.1'
services:
db:
image: postgres
container_name: db
ports:
- 5432:5432
networks:
- sonarnet
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
sonarqube:
image: sonarqube:8.9.9-community
container_name: sonarqube
depends_on:
- db
ports:
- 9000:9000
networks:
- sonarnet
volumes:
- './logs:/opt/sonarqube/logs'
- './extensions:/opt/sonarqube/extensions'
- './data:/opt/sonarqube/data'
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
networks:
sonarnet:
driver: bridge
  1. 启动sonarqube
1
docker-compose up -d

查看启动过程的log

1
docker logs -f sonarqube

启动sonarqube时可能会报下面的错误。

image-20220711231006529

解决办法是,在/etc/sysctl.conf文件中添加下面的内容。

1
vm.max_map_count=262144

运行下面的命令使设置生效

1
sudo sysctl -p
  1. 访问sonarqube服务器

因为测试时是在自己电脑上安装的,所以可以访问http://127.0.0.1:9000来登录sonarqube服务器

默认账户和密码

1
2
账户: admin
密码: admin

登录后需要修改密码。

  1. 配置界面为中文

  1. 安装扫描C/C++的插件

插件的下载网址:

https://hub.fastgit.xyz/SonarOpenCommunity/sonar-cxx/releases

注意:这里放置的为github的代理网站,以便下载速度更快。原网址是https://github.com/SonarOpenCommunity/sonar-cxx/releases

亲测,sonarqube-8.9.9版本可以使用下面版本的插件。

将下载好的jar包放置在目录中的extensions/plugins文件夹中。

重启sonarqube就能生效了。

然后更新一下C++的扫描规则

可以看到规则数是0。我们需要点击右上角的按钮新建一个profile

然后点击下面的标记的按钮添加规则。

可以看到左边是规则的类别,右边是列出的规则。然后选择想要的规则并激活。

批量激活插件中包含的规则

可以看到规则已经加好了。

设置自定义的profile为默认。

sonarqube默认是关闭c++文件的探测。需要如下图所示设置需要探测的c++文件后缀。

  1. 下载安装SonarScanner

下载网址:

https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/

解压后移动到系统目录

1
mv sonar-scanner-4.7.0.2747-linux /opt/sonar-scanner

添加执行文件路径

1
echo 'export PATH="$PATH:/opt/sonar-scanner/bin"' >> ~/.bashrc
1
2
source ~/.bashrc
sonar-scanner -v

修改配置

1
vim /opt/sonar-scanner/conf/sonar-scanner.properties

如果sonarqube是安装在本地的,下面的url就写localhost。如果是安装在云服务器上就写服务器的ip。

1
2
sonar.host.url=http://localhost:9000
sonar.sourceEncoding=UTF-8

执行扫描

首先需要在sonarqube服务器上配置一个project。然后就能得到下面的命令。在需要扫描的目录下运行下面的命令即可。扫描结果可在服务器的网页上查看。

1
2
3
4
5
sonar-scanner \
-Dsonar.projectKey=Cplusplus-analysis \
-Dsonar.sources=. \
-Dsonar.host.url=http://118.116.56.150:9000 \
-Dsonar.login=495481cd66ab60d6fbd69586086f662dd7b4dd52

注意:第一次运行时需要下载东西会比较慢。

https://techexpert.tips/sonarqube/sonarqube-scanner-installation-ubuntu-linux/

  1. 静态代码分析

本机安装cppcheck

1
sudo apt-get update && sudo apt-get install cppcheck

使用cppcheck来检查代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

➜ test_git git:(master) ✗ cppcheck ./src
Checking src/main.cpp ...
src/main.cpp:8:2: error: Null pointer dereference: a [nullPointer]
*a = 9;
^
src/main.cpp:7:11: note: Assignment 'a=nullptr', assigned value is 0
int * a = nullptr;
^
src/main.cpp:8:2: note: Null pointer dereference
*a = 9;
^
➜ test_git git:(master) ✗ ament_cppcheck ./src
[src/main.cpp:8]: (error: nullPointer) Null pointer dereference: a
1 errors

基于dockercppcheck

1
2
3
4
docker pull neszt/cppcheck-docker

#在代码根目录运行
docker run -t -v $(pwd):/src neszt/cppcheck-docker

cppcheck集成到drone

.drone.yml文件中添加下面的内容。

1
2
3
4
5
6
- name: cppcheck
pull: if-not-exists
image: neszt/cppcheck-docker
commands:
- cppcheck --xml-version=2 . 2> cppcheck_report.xml

然后在sonarqube中设置报告的路径

image-20220725083924971

注意,报告的名称要跟.drone.yml文件中保持一致。

参考:

http://www.manongjc.com/detail/29-yxqbaowgctqxpxq.html

https://blog.csdn.net/weixin_44025546/article/details/111303183