GitLab 自动部署 GitHub Pages 博客

在之前《搭建家庭私人 GitLab 服务器》说到我现在有这样的需求,而且根据上一篇,我们已经搭建好了这样的一个环境。那么有什么就赶紧用起来吧。

那么这一篇主要是介绍一下如何用这个家庭私人 GitLab 实现自动部署托管在 GitHub Pages 上的博客。本文使用的是 Hexo 框架 + Next 主题,其他的静态博客框架大同小异。这的关注点不在搭建博客,这里假定你已经有了一个正在托管的 GitHub Pages 博客。这篇文章将此博客为例子讲解一下。

为什么

用过 Hexo 的都知道,它需要在你的本地电脑上搭建一个 Node 环境。安装框架、自定义修改配置、Markdown 写文章,然后生成、最后利用 Git 推送到 GitHub 仓库 然后才能在网上看到发布的文章。那么这样带来了一个问题:如果某一天你本地的写博客的环境丢失了(比如电脑坏了,硬盘坏了等等等等)那么如果你想再更新你的博客就需要再次搭建这样一个环境,除了需要将所有的配置再次配置一遍,关键是旧的 Markdown 文章已经几乎再找不回来了。

几年前我也是因为这个原因导致放弃了之前写了很多文章的博客。那到这里就有人想了,如果我把位于本地的那个 ‘环境’ 也用 Git 管理起来呢?不错的想法,之后我也是这样做的,在 GitHub 上再新建一个仓库,用来保存本地写博客的环境,这样一来,即使换电脑了,只需要把这个仓库 clone 下来,安装一下相关的依赖,就可以继续了。

看起来很美好,但很快就遇到另一个问题:这里相当于把你的博客所有源码都公开了出去,有什么弊端么?比如假如你使用了 hexo-blog-encrypt 插件对某些博客进行加密,密码使需要明文写在待加密博客的头部信息里的。好家伙,这样一来,不就成了防君子不防小人了?所以这就需要把源码托管在我们之前搭建那个家庭私人的 GitLab 上的。

但是过了一段时间,我又双叒叕发现了一个问题:我经常忘记把本地的博客源码 push 到 GitLab 上。大部分的时候都是本地写完,修改的差不多之后就 hexo deploy 部署后就忘了 push 到 GitLab,导致用的时候该丢的文章还是丢了。恼羞成怒之下,萌生了利用 GitLab CI/CD 自动部署。实现每次写完文章,只需要 push 本地源码到 GitLab,然后 GitLab 自动部署。这样一来就不怕每次写完文章手动部署之后忘记提交本地源码,二来也减少了需要手动的步骤。毕竟懒惰才是人类的第一生产力。

开始吧

安装 Docker

使用 GitLab CI/CD 功能不是必须 Docker,但是容器化的 Docker 能够隔离物理机,防止一言不合一个 rm -rf /* 让你的心血白费。

以下命令需要 ssh 到 GitLab 服务所在的机器中进行

  1. 卸载旧版本 Docker(如果没安装过,可以省略)
    sudo apt remove docker docker-engine docker.io containerd runc
  2. 安装必要依赖
    sudo apt update && sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
  3. 添加 apt 源
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

    echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  4. 安装 Docker
    sudo apt update && sudo apt install docker-ce docker-ce-cli containerd.io
  5. 启动 Docker
    sudo systemctl enable docker
    sudo systemctl start docker

如果以上命令没有出现错误,那么 docker 就已经安装到服务器上了。如果不放心,可以通过 sudo docker -v 命令,如果输出类似 Docker version 20.10.12, build e91ed57 就说明 docker 已经正确安装了。

安装 Gitlab-Runner

以下的命令都需要 ssh 到 GitLab 服务所在的机器中进行

  1. 添加 gitlab-runner 库
    curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
  2. 安装 gitlab-runner
    sudo apt install gitlab-runner

如果一切顺利,gitlab-runner 就安装好了,可以运行 sudo gitlab-runner -v 如果没有错误,则说明 gitlab-runner 安装成功。

注册 Runner

首先使用 root 用户登录 gitlab -> 点击左上方 Menu -> 进入 Admin -> 点击左侧面板 Overview 下的 Runners

然后点击右上方 Register an instance runner,复制 Registration token

再次通过 ssh 连接 GitLab 服务器注册一个共享 Runner

$ sudo gitlab-runner register
Enter the GitLab instance URL (for example, https://gitlab.com/):
http://git.home/ # 本地 GitLab 域名或者IP
Enter the registration token:
xxxxxxxxxxxxxxxx # 上面获取到的 token
Enter a description for the runner:
[ubuntu]: node # runner 自定一个名字
Enter tags for the runner (comma-separated):
node # runner tag 的名字,通过 tag 指定运行 runner
Registering runner... succeeded runner=xxxxxx
Enter an executor: custom, ssh, docker-ssh+machine, kubernetes, docker, docker-ssh, parallels, shell, virtualbox, docker+machine:
docker # 这里选择 docker
Enter the default Docker image (for example, ruby:2.6):
node:17 # docker 镜像以及版本
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

当创建好 Runner 之后,再次回到 Runners 页面刷新就可以显示刚刚创建的 Runner 了。

创建 SSH 密钥对

在本地或者服务器上执行

ssh-keygen -f blog -t rsa -b 2048 -C "xxxx@xxx.xxx"     # 邮箱自行替换

生成一个无密码的 SSH 的密钥对

公钥为 blog.pub,私钥为 blog

GitHub 添加 Deploy keys

登录 GitHub,进入部署的博客仓库,点击 Settings -> Deploy keys -> Add deploy key

blog.pub 公钥的内容全部复制到 Key 中,然后 Title 处自定义一个名字

GitLab 配置 CI/CD

进入 GitLab 博客项目,点击 Settings 下的 CI/CD,右侧展开 Runners 选项卡,右侧 Shared runners 打开 Enable shared runners for this project 选项

然后再展开到下方 Variables

添加两个环境变量分别是

  • SSH_KNOWN_HOSTS
    github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
  • SSH_PRIVATE_KEY
    创建 SSH 密钥对 中的私钥 blog 内容

项目 .gitlab-ci.yml 配置

经过以上配置,现在离成功有一步之遥。

在 GitLab 博客源码项目根目录下创建一个 .gitlab-ci.yml 的配置文件

stages:
- deploy

deploy:
stage: deploy
only:
- main # 指定只有主分支触发该 CI
tags:
- node # 此处 tag 指定创建 GitLab Runner 时候填写 tag 名字
before_script:
- ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- "which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )"
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- rm -rf ~/.ssh/id_rsa
- touch ~/.ssh/id_rsa
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- rm -rf ~/.ssh/known_hosts
- touch ~/.ssh/known_hosts
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 700 ~/.ssh
- chmod 700 ~/.ssh/*
- git config --global user.email "xxxx@xxx.xxx" # GitHub 的邮箱
- git config --global user.name "xxxx" # GitHub 的名字
- git config --global init.defaultBranch main # GitHub 项目的主分支 main 或者 master
script:
- npm install -g hexo-cli
- npm install hexo-deployer-git --save
- npm install hexo-renderer-swig --save
- npm install hexo-generator-searchdb --save
- npm install hexo-symbols-count-time --save
- npm install hexo-generator-sitemap --save
- npm install hexo-abbrlink --save # 以上 npm 步骤根据自己添加的插件自定义
- hexo clean
- hexo generate
- hexo deploy

然后 git add .gitlab-ci.yml 最后推送到仓库之后,从侧边 CI/CDPipelines 就可以看到自动运行部署工作了

结束

经过以上的步骤,现在就可以每次在本地编辑后,只需要推送到 GitLab 并稍等片刻,GitHub Pages 的页面就有最新的内容了。