本文介绍如何在自建服务器上使用 Jenkins 和 Gitee 自动部署博客。

最近给域名备了个案,于是花了点时间把博客从 Vercel 迁移到了国内服务器上。之前用的 Vercel 是能够在 Git 仓库发生变更后自动部署的,但迁到自建服务器上后这个功能就得自己实现了,搜索了一下实现方案,最后选用了 Jenkins。
环境信息
| 环境 | 版本 |
|---|---|
| 操作系统 | CentOS 7 |
| Jenkins | 2.277.4 |
| JDK | 1.8.0_282 |
| Nginx | 1.18.0 |
| Git Host | Gitee |
配置 Jenkins
安装 Jenkins
参考 官方文档 安装即可, CentOS 的步骤如下 :
1 |
# 添加 Yum 源 |
(可选)Jenkins 默认端口为 8080,可以在配置文件里修改:
1 |
vim /etc/sysconfig/jenkins |
最后添加开机启动:
1 |
# 重载服务(由于前面修改了 Jenkins 启动脚本) |
Jenkins 初始化
确保之前设置的端口在防火墙里已开放,然后浏览器访问 <ip>:<port>,按照向导一步步完成初始化。
安装插件
安装配置 NodeJS Plugin
登录 Dashboard,选择 Manage Jenkins > Manage Plugins,点击 Available,安装 NodeJS Plugin。
然后在 Dashboard > Manage Jenkins > Global Tool Configuration 里下滑找到 NodeJS ,点击 NodeJS installations …,配置如下:

选择 Node 版本,在 Global npm packages to install 里填入 Hexo 和 Yarn 依赖:
1
|
hexo-cli@4.2.0 yarn --registry https://registry.npm.taobao.org/
|
点 Save 保存。
安装 Gitee Plugin
由于 Github 在国内网络几乎不可用,这里把 Host 换成了 Gitee,因此还需要安装一个 Gitee Plugin。
Gitee 的配置参考 Gitee 的官方 帮助中心:
简单来说,在 Jenkins -> Manage Jenkins -> Configure System -> Gitee Configuration -> Gitee connections 里,按照文档配置如下:

添加 CI 任务
配置密钥(可跳过)
由于我博客项目设置为了私人仓库,所以需要额外生成密钥对并把公钥添加到 Gitee 里,如果你的仓库是公开状态,这一步可以跳过:
切换到 Jenkins 用户:
1
|
sudo su -s /bin/bash jenkins
|
生成密钥对:
1
|
ssh-keygen -o
|
查看公钥并复制:
1
|
cat ~/.ssh/id_rsa.pub
|
然后在 Gitee 网站右上角 个人头像 > 设置 > SSH 公钥 里粘贴公钥,点确定保存。
新建任务
新建任务
接下来就可以在 Jenkins 里新建构建博客的 CI 任务了!
打开 Dashboard,点击 New Item。输入 Item name,类型选择 Freestyle project。配置页里 Gitee connection 选择之前配置的 connection。
在 Source Code Management 里选择 Git,Repository URL 里填入仓库链接,如果这个时候显示权限失败,请返回上一小节配置密钥。
在 Build Triggers 里选择 Build when a change is pushed to Gitee. Gitee webhook URL: http://81.70.155.173:8089/gitee-project/blog ,注意复制这里的 webhook url,之后会用到。
然后再 Enabled Gitee triggers 里选中 Push Events,Secret Token for Gitee WebHook 里点击 Generate,同样保存备用。
Gitee 配置 Webhook
之前配置的 Webhook 需要在 Gitee 上同样配置一下才能正常工作:
登陆 Gitee 后在仓库主页点击 管理 > WebHooks > 添加 WebHooks,然后填入刚刚保存的 url 和 token,保存即可。
编写构建脚本
回到任务配置页,继续添加自动构建脚本:
在 Build 里点击 Add build step,选择 Execute shell,根据网站和博客的具体情况编写构建部署命令如下:
1 |
# 不安装 devDependences |
2021 年 5 月 28 日 更新,部署 mkdocs 的脚本如下:
1 |
/usr/bin/pip3.6 install -i https://pypi.tuna.tsinghua.edu.cn/simple mkdocs-material --user |
测试部署
完成 CI 任务的创建后,回到 Project 页面,点击 Build now,观察是否一切正常。然后通过 Git 更改后 push,测试 WebHook 是否正常。
如果部署时提示权限不足,可以把网址所在的目录 owner 改为 jenkins 来解决。
1
|
sudo chown -R jenkins:jenkins mysite/
|
其他
推送
原来用 Vercel 的时候,每次构建完毕,Vercel Bot 就会给我的仓库的 Commit 评论一下,然后会收到 Github 发来的邮件,提醒我构建完成,非常好用。当然,现在这个功能也只能自己写了。因为是国内服务器,直接排除了用 Telegram 推送。搜索了一下,发现了一个通过 QQ 推送消息的网站 Qmsg 酱 ,按照 文档 注册配置后可以获得一个 Qmsg Key,然后就可以调用 RESTful 接口发起推送了!
配置非常简单,在构建脚本的最后添加如下命令即可:
1 |
curl --location --request POST 'https://qmsg.zendee.cn/send/< 你的 qmsgKey>' \ |
这样每次部署完成,你会收到一条 QQ 消息:

国内网络的坑
这次迁移的过程中也遇到了一些坑。最开始本来打算沿用 Github 的,但测试发现 Clone 总是出错,于是被迫改成国内的 Gitee。可以在原仓库上额外添加 Gitee 远程仓库地址,让 Github 和 Gitee 并存:
1
|
git remote add gitee <url>
|
然后提交时,分别执行:
1 |
git push origin master |
就可以分别提交到两个仓库里了。
另外,博客用到的一个插件 hexo-all-minifier 也遇到了类似的问题。这个插件的安装脚本 install.js 会从 githubusercontent.com 里下载文件,而国内这个域名直接被 ban 了… 无语…于是我暂时去掉了这个插件,如果想解决可能需要重打包一下了…
刚尝试重打包了一下,太麻烦了,怕了怕了,还是换个包吧。
from
-----------------------------------------------------
- on mac install
$ brew install jenkins
$ jenkins
浏览器访问 http://localhost:8080 进入配置页面。 数据存储目录:~/.jenkins 包括插件,日志和Jobs等。
-
第一次需 Unlock: ~/.jenkins/secrets/initialAdminPassword 系统把密码生成到这个文件,只有能访问这个文件的人才说明是管理员
-
设置代理:代理服务器,认证账号密码和 no_proxy 设置。
如需重新初始化,请直接删除 ~/.jenkins 又可以重头开始配置。
点击:系统管理>管理插件>可选插件
- git plugin (新版本或默认安装)
- Publish Over SSH / SSH Credentials Plugin
- Email Extension Plugin (邮件通知)
下载插件的时候,往往需要用到代理(往往需海外代理)。可以在启动
jenkins时,设置http_proxy环境变量。后期设置代理的路径是:系统管理>管理插件>高级 Jenkins Plugin Center: https://updates.jenkins-ci.org/download/plugins/ 和 https://plugins.jenkins.io/
既然有插件,那就有生态:(1)插件仓库;(2)发布插件;(3)自动安装插件;(4)自动更新插件;(5)安装量/受欢迎程度统计;(6)Plugin之间的依赖管理。
安装完jenkins时,默认它的语言会跟浏览器设置的语言一致。但是为了跟国际接轨,我们尽可能强制用英文。需要下载Locale插件。
- 安装Locale插件
系统设置 (Manage Jenkins) -> 插件管理 (Manage Plugins) -> 可选插件 (Available)
然后搜索:Locale
- 设置为英文
http://localhost:8080/configure
Locale -> Default Language -> en_US.UTF-8 或者 zh_CN.UTF-8
Jenkins 可以有自己的账号体系,也可以跟公司的域账号LADP集成。只需要在Jenkins -> Configure Global Security中设置:
Jenkins 支持RESTful API,但需要认证,难道我们模拟登陆?当然不是,现在主流的做法是用户通过界面登陆Jenkins的Web管理界面,然后通过界面生成一个token,后期调用只要携带这个token即可。本质上跟普通Web登陆,输入用户名+密码,然后服务端生成一个session_id,浏览器通过COOKIE来承载这个session_id是一样的。只不过两者的生命周期不一样而已。
生成 API Token:
- 点击
Jenkins->People->admin(选择进入admin账户,以便以admin账户的名义)- 在
admin账户页面 的左侧栏,点击Configure->API Token选项卡
大家都知道Jenkins的界面是出了名的丑陋。但是作为一个后端程序员,有点想法,发明了一个Jenkins,前期找不到前端程序员合作,能搞出这样的界面也算是不容易了。当你不会做漂亮的界面,又想搞点事的时候,你怎么办呢?RESTful API + cli 呀。
比如,我们直接通过命令行,查询job列表:
$ jenkins-cli -s http://localhost:8080/ list-jobs
java.io.IOException: Server returned HTTP response code: 403 for URL: http://localhost:8080/jenkins/cli?remoting=false
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at hudson.cli.FullDuplexHttpStream.<init>(FullDuplexHttpStream.java:99)
at hudson.cli.CLI.plainHttpConnection(CLI.java:652)
at hudson.cli.CLI._main(CLI.java:612)
at hudson.cli.CLI.main(CLI.java:426)
$ export JENKINS_URL=http://localhost:8080/
$ jenkins-cli list-jobs
java.io.IOException: Server returned HTTP response code: 403 for URL: http://localhost:8080/jenkins/cli?remoting=false
$ jenkins-cli -auth admin:e6c630e01fce4191a2be2b602ca69874 list-jobs
hello-world-jresty
其中:
-s选项: 表示服务器地址。如果我们不想每次命令都输入,可以保存到$JENKINS_URL环境变量中。- API地址:JENKINS_URL=http://localhost:8080/ 而不是有些教程里面的 JENKINS_URL=http://localhost:8080/jenkins/ (本教程jenkins版本是 2.73)
- 账号密码:通过
-auth admin:e6c630e01fce4191a2be2b602ca69874指定账号和密码。- 帮助信息:在Web页面上,点击
jenkins->Manage Jenkins->Jenkins-Cli,也就是 http://localhost:8080/cli/ 会有帮助信息。
除了上文直接输入Web页面一样的用户名+密码的方式(这种用在RESTful API上,实质表现为HTTP Basic Auth形式),它还支持:API token认证 和 SSH Key 方式。
按前文说的步骤,生成 API Token:
- 点击
Jenkins->People->admin(选择进入admin账户,以便以admin账户的名义)- 在
admin账户页面 的左侧栏,点击Configure->API Token选项卡
$ jenkins-cli -auth admin:f69552d7a187b8a8944ab3f88b38ad76 list-jobs
hello-world-jresty
注意:形式跟账号密码是一样的?对!官方帮助是这么写的:
-auth [ USER:SECRET | @FILE ] : specify username and either password or API token (or load from them both from a file);
也可以把账号+API Token保存到文件,然后:
$ echo "admin:f69552d7a187b8a8944ab3f88b38ad76" > token.txt
$ jenkins-cli -auth @token.txt list-jobs
hello-world-jresty
from
mdblog/devops/jenkis概述与安装.md at master · tenebaul/mdblog · GitHub
Jenkins可以类似github.com一样,支持SSH Key方式认证:1)在本地生成秘钥对:~/.ssh/id_rsa和~/.ssh/id_rsa.pub;2) 把~/.ssh/id_rsa.pub粘贴到Jenkins Web
按下列步骤填写SSH Public Key: http://localhost:8080/me/configure
- 点击
Jenkins->People->admin(选择进入admin账户,以便以admin账户的名义)- 在
admin账户页面 的左侧栏,点击Configure->SSH Public Keys选项卡
接着直接使用命令行,它自己会用~/.ssh/id_rsa去签名的:
$ jenkins-cli list-jobs
ERROR: anonymous is missing the Overall/Read permission
$ jenkins-cli -i ~/.ssh/id_rsa list-jobs
ERROR: anonymous is missing the Overall/Read permission
报错了,我们还需要在服务端 Configure Global Security 打开一个选项开关。如下图勾选上 Allow anonymous read access即可:
$ jenkins-cli list-jobs
hello-world-jresty




