别忘了泡上一杯茶!
绕不开的存在
当然,谈到 Git
服务时,肯定绕不过 GitHub
。为什么要大费周章自建呢?GitHub
不好吗?
是很好,但是也没那么好,因为:
GitHub
是一家商业公司,那么首先盈利肯定是首要目的,为了不倒闭,指不准未来哪天就变质了。
- 同上,如果还是个自由软件爱好者的话,想必
GitHub
最近一些事件带来的臭味也不必我再提了……
Git
是分布式的,那么选择同样也是……不知道现在还有多少人还傻傻认为 Git
和 GitHub
是一体的呢?
也可参见 GiveUpGitHub 一文章。
Gitea
Gitea
是一个用 Go
编写、面向自建的、轻量级的 Git
服务。其安装十分便捷,直接下载个可执行文件也可快速搭建起来,当然为了后续跟其它服务联动,还是用 docker-compose
方便点。
话不多说,新建一个文件夹然后往里建 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 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
| version: "3.7"
services: gitea: image: gitea/gitea:latest container_name: gitea restart: unless-stopped environment: - USER_UID=1000 - USER_GID=1000 volumes: - ./data/gitea:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "127.0.0.1:3000:3000" - "2222:22" networks: - cicd_net
drone: container_name: drone image: drone/drone:latest restart: unless-stopped depends_on: - gitea environment: - DRONE_DATABASE_DRIVER=sqlite3 - DRONE_DATABASE_DATASOURCE=/data/database.sqlite - DRONE_GITEA_SERVER=https://my.git.server/ - DRONE_GIT_ALWAYS_AUTH=false - DRONE_RPC_SECRET=changeme... - DRONE_SERVER_PROTO=https - DRONE_SERVER_HOST=https://cicd.git.server - DRONE_GITEA_CLIENT_ID=changeme... - DRONE_GITEA_CLIENT_SECRET=changeme... ports: - "127.0.0.1:3001:80" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data/drone:/data networks: - cicd_net
drone-runner: container_name: drone-runner image: drone/drone-runner-docker:latest restart: unless-stopped depends_on: - drone environment: - DRONE_RPC_PROTO=http - DRONE_RPC_HOST=drone - DRONE_RPC_SECRET=changeme... - DRONE_RUNNER_NAME="action-runner" - DRONE_RUNNER_CAPACITY=2 - DRONE_RUNNER_NETWORKS=cicd_net - DRONE_DEBUG=false - DRONE_TRACE=false networks: - cicd_net volumes: - /var/run/docker.sock:/var/run/docker.sock
networks: cicd_net: name: cicd_net
|
因为预想场景是私人自用,所以选择了 SQlite3
数据库,觉得别扭可以自己改掉……
然后准备两个域名,这里用 my.git.server
域名指定用来运行 Gitea
服务的域名,一个 cicd.git.server
域名用来指定运行后续的自动构建服务的域名(可选)。
首先为 my.git.server
域名设定DNS
后申请证书,certbot certonly --nginx -d my.git.server
,申请后写入 nginx
配置:
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
| server { listen 80; listen [::]:80; server_name my.git.server;
location /.well-known/acme-challenge {} location / { return 301 https://$host$request_uri; } }
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name my.git.server;
access_log /var/log/nginx/access.log;
ssl_certificate /etc/letsencrypt/live/my.git.server/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/my.git.server/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_ecdh_curve secp384r1; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; resolver 9.9.9.9 80.67.169.12 valid=300s; resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header Content-Security-Policy "default-src 'self'; img-src *; frame-ancestors 'self'; frame-src https:";
location / { proxy_pass http://localhost:3000/; 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 $scheme; client_max_body_size 50m; } }
|
之后 nginx -s reload
重载配置,然后 docker-compose up -d gitea
把 Gitea
服务启动,之后前往 my.git.server
地址进行配置并新建一个管理员账户。
Drone
到此服务就基本可用了,但是我相信很多人割舍不下 GitHub
的一个原因就是因为它的 Actions
很香。不过可以选择 Drone
,一个同样用 GO
编写的、轻量级的自动构建服务,也可以让体验往 GitHub Actions
靠拢。
首先为 cicd.git.server
域名申请证书并写入 nginx
配置文件,配置文件可复用上面的,只需要更改相关域名和 nginx
配置文件里的 location /
里的 proxy_pass
端口号就行(本例子是 3001
)。
之后为 Drone
和 Gitea
联动做准备,登陆自己 Gitea
实例的帐号→设置→应用→创建新的 OAuth2 应用程序,应用名称随意填(本例子填 drone),重定向 URI 填入 https://cicd.git.server/login
(替换成自己的域名)。
点击创建应用→会生成一个客户端 ID 和一个客户端密钥→替换到上述 docker-compose.yml
里 drone
一栏的 DRONE_GITEA_CLIENT_ID
和 DRONE_GITEA_CLIENT_SECRET
。
之后再使用 openssl rand -hex 16
命令生成一串随机字符串给 DRONE_RPC_SECRET
使用(有两个地方需要替换)。
确认无误后使用 docker-compose up -d
启动全部服务,之后前往 https://cicd.git.server
地址查看是否正常运行,是的话点击登陆,看是否能够和 Gitea
进行联动,如果显示错误请检查是否与上述配置一致(例如我之前就遇到了无法验证的错误,排查后发现是某个路径多带了一个 /
导致之后生成的验证路径出错,去掉 /
之后就正常了)。
仓库操作
因为宿主机的 22
端口已被占用,所以克隆或者 PUSH
仓库使用的端口应该为 2222
,觉得别扭也有其他教程教如何与宿主机共用端口,我就不折腾了(反正 Just work!
)。
还有如果为网站使用了 Cloudflare
之类的 CDN
服务的话,那么 SSH
协议也是不能用的,得用网站域名下的真实 IP
地址克隆或 PUSH
仓库。
如果像我什么都没改的话,想要克隆仓库就会得到这么一个奇怪的地址:
git clone ssh://git@机子真实IP:2222/用户名/仓库名.git
反正 Just work
!
一个案例
那么接下来就讲讲我用这套服务的案例吧,自动生成文件并推送一个 HUGO
博客。
首先为仓库根目录写下 .drone.yml
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| kind: pipeline name: build
steps: - name: build image: klakegg/hugo:alpine commands: - hugo
- name: deploy image: node environment: CLOUDFLARE_API_TOKEN: from_secret: api_token CLOUDFLARE_ACCOUNT_ID: from_secret: account_id commands: - npm install -g wrangler - npx wrangler pages publish public --project-name 项目名 --commit-dirty=true
|
可以见到和 GitHub Actions
的配置还是挺像的,琢磨琢磨还是挺快上手的。
其中 steps
指定了所需步骤,image
指定了需要什么样的 docker
镜像,第一栏拉取了 klakegg/hugo
镜像并使用 hugo
命令生成静态文件。
之后是 deploy
一栏里的 environment
,像 GitHub
一样,密钥相关可以使用 secret
功能导入到环境变量中,可在自己的 cicd.git.server
→相关仓库→ Settings
→ Secrets
里进行导入。
接下来使用 node
镜像安装了个 wrangler
包,这是 Cloudflare Pages
部署要用的,如果也用 Cloudflare Pages
部署的话可以参考:
Wrangler pages commands
Running Wrangler in CI/CD
PS:不得不吐槽相关操作首先必须要用 project create
命令里的 --production-branch
显式指定部署分支否则接下来的部署都会被识别为预览而不会真正部署到……被这个坑卡了好一会……
之后再进行相关操作后应该能看见自己 Gitea
实例也有小绿勾了(小红叉也行,至少证实自动部署服务有在用了)!
加主题
默认主题还挺程序员风格的,既然都自建了,肯定要加点主题快乐一下了。
以现代主题为例。
如果是以上面的配置文件搭建起来的话要在自己文件夹下找到 ./data/gitea/gitea
路径,并在里头新建 public/css
下 wget https://codeberg.org/Freeplay/Gitea-Modern/raw/branch/main/Gitea/theme-gitea-modern.css
获取主题文件。
之后再编辑 ./data/gitea/gitea/conf/app.ini
文件,在最后面加上:
之后再用 docker-compose down
和 docker-compose up -d
重启服务。
安全
如果没有相关要求,请务必关闭实例的注册功能。
参见,记一次自建 Gitea + Drone 实例被挖矿的经历
也是修改 ./data/gitea/gitea/conf/app.ini
里的:
之后再用 docker-compose down
和 docker-compose up -d
重启服务,然后再检查站点是否关闭了注册入口。
参考
CICD With DroneCI and Gitea Using Docker Compose
Gitea Docs
Drone Docs
透過 Drone 建立自動部署流程,部署排程設定與權限管理 - 薛丁格的工程師