一、故事背景
目前Hexo博客体积有点大了,提交内容到Gitea执行Gitea Action时,发生任务卡死的频率越来越高了,昨天早上连着炸了好几次😥。
早上一手三连炸,宕机了一个多小时
我后面又查了一遍资料,发现Hexo Git仓库里也有很多大批量页面生成失败的交流贴,不过他们都是文章量到了1000-3000+才开始出现内存问题。
看了一圈,社区里提到或猜测的慢编译原因有这几个:
以上绝大多数问题我都无法进行干预,于是我考虑通过调整Gitea Action的workflow配置,增加一些限制项来控制任务使用的资源。我一共尝试了以下配置,都只能解决任务卡死不拖累云服务器也挂掉的问题,却无法让项目编译成功。
- 在任务上设置CPU、内存使用限制,禁用SWAP内存防止拖慢速度,
options: --cpus 1 --memory 512m --memory-swap 512m;
- 增加
jobs任务级别的timeout-minutes超时限制;
- 在 Build 步骤增加Node环境变量
NODE_OPTIONS: "--max-old-space-size=600"控制使用内存;
- 增加
Build steps步骤级别的timeout-minutes超时限制;
- 给工作区目录挂载内存盘减少IO
mount -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,又都是同版本的,所以用官方自带的迁移是最快的。
- 先从1Panel打开Gitea应用的文件目录,在应用文件夹下找到
/data/gitea/conf/app.ini配置文件,并增加下列配置(用于开放外部仓库的Gitea迁移功能):
app.ini1 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 设置。
- (可选项)通过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
- 在云服务器的Gitea页面,点击右上角头像 → Settings(设置),在左侧菜单找到并点击 Applications(应用),在页面中输入令牌名称和勾选权限后就可以创建令牌了。
云端Gitea 创建外部访问令牌
- 然后在本地环境填入仓库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. 创建低权限部署用户 ====="
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}"
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'
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"
LIMITS="command=\"${VALIDATE_SCRIPT}\",no-port-forwarding,no-agent-forwarding,no-X11-forwarding" echo "${LIMITS} ${PUB_KEY}" > "${AUTH_KEYS}"
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分钟了