Blog部署下云过程记录

一、故事背景

目前Hexo博客体积有点大了,提交内容到Gitea执行Gitea Action时,发生任务卡死的频率越来越高了,昨天早上连着炸了好几次😥。

早上一手三连炸,宕机了一个多小时

我后面又查了一遍资料,发现Hexo Git仓库里也有很多大批量页面生成失败的交流贴,不过他们都是文章量到了1000-3000+才开始出现内存问题。

看了一圈,社区里提到或猜测的慢编译原因有这几个:

以上绝大多数问题我都无法进行干预,于是我考虑通过调整Gitea Action的workflow配置,增加一些限制项来控制任务使用的资源。我一共尝试了以下配置,都只能解决任务卡死不拖累云服务器也挂掉的问题,却无法让项目编译成功。

  1. 在任务上设置CPU、内存使用限制,禁用SWAP内存防止拖慢速度,options: --cpus 1 --memory 512m --memory-swap 512m
  2. 增加jobs任务级别的timeout-minutes超时限制;
  3. 在 Build 步骤增加Node环境变量NODE_OPTIONS: "--max-old-space-size=600"控制使用内存;
  4. 增加Build steps步骤级别的timeout-minutes超时限制;
  5. 给工作区目录挂载内存盘减少IOmount -t tmpfs -o size=512m tmpfs ./public

思来想去,想来思去。只能让Gitea下云了(这台2H2G的小鸡承受了太多了😂)。

二、调整方案

设想中的方案是:把Gitea迁移到本地,然后在本地服务器编译后通过SFTP/SCP/RSYNC等形式提交到云服务器上。虽然Hexo也有现成的FTP同步插件(hexo-deployer-ftpsync),但主包还是觉得通过Gitea工作流提交更稳重一些(既不会误操作发布半成品,也强制自己先在Dev环境预检后才能合并发布到生产环境😁)。

三、迁移过程

(1)搭建本地服务器

我这里用Vmware搭建了一台Linux服务器,并安装了1Panel面板,使得本地环境和云服务器保持一致,以求最大化的平稳迁移(就很神奇,有时候任何一个变数都会导致出现莫名其妙的问题😂)。

创建过程就不放了,遇到的问题就是上一篇提到的:本地自签名SSL证书后,创建的静态网站和反向代理应用都访问失败了。

(2)迁移云服务器Gitea数据至本地

本地环境搭好了之后,就要把Gitea数据迁移回本地。因为是 Gitea → Gitea,又都是同版本的,所以用官方自带的迁移是最快的。

  1. 先从1Panel打开Gitea应用的文件目录,在应用文件夹下找到/data/gitea/conf/app.ini配置文件,并增加下列配置(用于开放外部仓库的Gitea迁移功能):
app.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[migrations]
; 允许从本地/内网IP导入(解决核心问题)
ALLOW_LOCALNETWORKS = true
; 白名单:加入源Gitea的域名/IP(如 192.168.1.100、git.example.com)
ALLOWED_DOMAINS = 127.0.0.1,192.168.1.100,git.example.com
; 清空黑名单(默认空即可)
BLOCKED_DOMAINS =
; 自签HTTPS时忽略证书验证
SKIP_TLS_VERIFY = true

[git.timeout]
; 迁移超时时间 = 3小时(单位:秒)
; 如果仓库体积很大,远程Gitea的带宽又慢,就把这个设置的长一些,否则后面会报错:
; migration failed: clone timed out, consider increasing [git.timeout] MIGRATE in app.ini, underlying err: context deadline exceeded - fatal: early EOF
MIGRATE = 10800

如果不添加,那当你点击本地Gitea的迁移仓库时,就会看到这个报错:
您不能从不允许的主机导入,请询问管理员以检查 ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS 设置。

  1. (可选项)通过1Panel的容器列表界面,给Gitea容器添加dns配置项

在1Panel中依次找到 容器 → 找到 Gitea → 停止 → 编辑,在「启动参数」里添加:

1
--dns=114.114.114.114 --dns=8.8.8.8

适用于看到迁移动画,不到半分钟又遇到报错的:
dial tcp: lookup gitea.xxxxxx.com on xxx.xxx.xxx.xxx:xx: read udp xxx.xxx.xxx.xxx:xx->xxx.xxx.xxx.xxx:xx: i/o timeout

  1. 在云服务器的Gitea页面,点击右上角头像 → Settings(设置),在左侧菜单找到并点击 Applications(应用),在页面中输入令牌名称和勾选权限后就可以创建令牌了。

云端Gitea 创建外部访问令牌

  1. 然后在本地环境填入仓库URL刚生成的令牌,把下面能勾选的都选上,然后点击迁移仓库即可。

本地Gitea 进行迁移

慢慢等待仓库迁移即可

(3)创建云服务器rsync专用账号

让AI帮忙写了一个创建脚本,用于创建一个专用于同步代码文件的用户和创建对应的SSH KEY。主要修改下面高亮的参数即可。

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
#!/bin/bash
set -euo pipefail

######################## 配置项(只需改这里)########################
# 部署用户名
DEPLOY_USER="gitea-deploy-user"
# 你的两个网站目录,改成你实际路径
DIR_TEST="/var/www/test-web"
DIR_PROD="/var/www/prod-web"
#####################################################################

echo "===== 1. 创建低权限部署用户 ====="
# 创建用户,使用 /bin/bash(必须,解决rsync协议报错)
useradd -m -s /bin/bash "${DEPLOY_USER}" || echo "用户已存在,跳过创建"

echo "===== 2. 生成Gitea部署专用SSH密钥 ====="
DEPLOY_HOME="/home/${DEPLOY_USER}"
SSH_DIR="${DEPLOY_HOME}/.ssh"
mkdir -p "${SSH_DIR}"
chmod 700 "${SSH_DIR}"
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${SSH_DIR}"

# 生成无密码ed25519密钥
sudo -u "${DEPLOY_USER}" ssh-keygen -t ed25519 -C "gitea-action-deploy@ci" -N "" -f "${SSH_DIR}/gitea_action_key"

echo "===== 3. 创建rsync专用验证脚本(仅允许rsync命令) ====="
VALIDATE_SCRIPT="${DEPLOY_HOME}/validate-rsync.sh"
cat > "${VALIDATE_SCRIPT}" << 'EOF'
#!/bin/bash
# 仅允许rsync服务端命令执行
if [[ "$SSH_ORIGINAL_COMMAND" =~ ^rsync\ --server\ ]]; then
exec $SSH_ORIGINAL_COMMAND
else
echo "Access denied"
exit 1
fi
EOF

# 脚本权限
chmod +x "${VALIDATE_SCRIPT}"
chown "${DEPLOY_USER}:${DEPLOY_USER}" "${VALIDATE_SCRIPT}"

echo "===== 4. 写入受限公钥(企业级安全:仅允许rsync) ====="
PUB_KEY=$(cat "${SSH_DIR}/gitea_action_key.pub")
AUTH_KEYS="${SSH_DIR}/authorized_keys"

# 安全限制:仅允许执行rsync脚本 + 禁止转发 + 安全加固
LIMITS="command=\"${VALIDATE_SCRIPT}\",no-port-forwarding,no-agent-forwarding,no-X11-forwarding"
echo "${LIMITS} ${PUB_KEY}" > "${AUTH_KEYS}"

# SSH强制权限要求
chmod 600 "${AUTH_KEYS}"
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${SSH_DIR}"

echo "===== 5. 授权网站目录权限 ====="
mkdir -p "${DIR_TEST}" "${DIR_PROD}"
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${DIR_TEST}" "${DIR_PROD}"
chmod -R 755 "${DIR_TEST}" "${DIR_PROD}"

echo -e "\n==================== 部署配置完成 ===================="
echo "【部署用户名】:${DEPLOY_USER}"
echo "【测试环境目录】:${DIR_TEST}"
echo "【生产环境目录】:${DIR_PROD}"
echo -e "\n🔑 【Gitea仓库密钥 SSH_PRIVATE_KEY 完整内容】:"
cat "${SSH_DIR}/gitea_action_key"
echo -e "\n======================================================"
echo "✅ 安全状态:仅允许rsync文件同步,无法登录服务器、无法执行系统命令"
echo "✅ 部署状态:完美兼容Gitea Actions rsync部署"
echo "======================================================"

复制到云服务器并执行后,获取生成的密钥信息:

1
2
chmod +x deploy-init.sh
./deploy-init.sh

运行脚本后获得账号私钥

(4)本地Gitea添加相关工作流密钥

点击Gitea仓库右上角的设置,打开工作流 → 密钥,添加下列密钥和内容:

名称
SSH_PRIVATE_KEY 脚本生成的私钥
REMOTE_USER 脚本设置的【部署用户名】
REMOTE_HOST 服务器IP地址
REMOTE_PORT 服务器端口
TEST_REMOTE_DIR 脚本设置的【测试目录】
PROD_REMOTE_DIR 脚本设置的【生产目录】

注意不要添加到 工作流 → 变量 里,变量是公开的,提交就能看见。服务器 IP、用户名、目录路径都属于敏感信息,必须放在密钥才安全、才加密。

创建完成后如图所示

(5)工作流文件调整

修改原先工作流的部署步骤,改为使用burnett01/rsync-deployments@7.0.0包,通过rsync上传编译后的网站。

1
2
3
4
5
6
7
8
9
10
- name: Deploy Hexo
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete --stats
path: public/
remote_path: ${{ secrets.TEST_REMOTE_DIR secrets.PROD_REMOTE_DIR }}
remote_host: ${{ secrets.REMOTE_HOST }}
remote_port: ${{ secrets.REMOTE_PORT }}
remote_user: ${{ secrets.REMOTE_USER }}
remote_key: ${{ secrets.SSH_PRIVATE_KEY }}

四、最终效果

全套配置完成后,提速效果也非常明显(从过去的3-5分钟变成1分钟,提速60%以上👍)。OK啊,后面可以安心写博客了😂。

现在每次打包只需要1分钟了

Blog部署下云过程记录

作者:有点东西

链接: https://www.youdiandongxi.com/article/blog-deploy-change-log.html

协议:本文采用 CC BY-NC-SA 4.0 隐私协议,转载请注明出处!

评论区