Hexo博客迁移及自动化部署指南:从踩坑到成功

最近将我的 Hexo 博客迁移到了一台新服务器上。在这个过程中,虽然基本流程都懂,但在权限配置、SSH 端口等方面还是踩了一些小坑。特此记录下完整的迁移与自动化部署过程,希望能帮到有同样需求的朋友。

1. 迁移背景

  • 旧服务器环境:常规配置,使用 Git 钩子自动部署。
  • 新服务器环境:安装了宝塔面板 (BT-Panel),修改了默认 SSH 端口,网站目录托管在宝塔的 wwwroot 下。
  • 目标:实现本地在 VS Code 中写完文章后,执行 hexo d 即可一键推送到新服务器,并自动更新网站目录。

2. 服务器端配置

部署的核心思想是利用 Git 的裸仓库(Bare Repository)接收本地推送的代码,然后通过 post-receive 钩子脚本将代码自动检出(checkout)到 Nginx/宝塔 的网站根目录。

2.1 创建 Git 用户及 SSH 密钥

为了安全,最好不要直接用 root 用户接收 Git 推送,我们创建一个专门的 git 用户。

1
2
3
4
5
6
7
8
9
# 使用 root 登录服务器
adduser git

# 切换到 git 用户
su - git

# 配置 SSH 免密登录
mkdir ~/.ssh && chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys

2.2 创建裸仓库

git 用户的家目录下创建一个裸仓库,用来接收代码。

1
2
3
mkdir -p ~/repos
cd ~/repos
git init --bare taiblog.git

2.3 编写 Git 钩子 (Hook)

进入刚刚创建的裸仓库的 hooks 目录,编写自动化脚本。

1
2
cd ~/repos/taiblog.git/hooks
vim post-receive

在文件中填入以下内容。注意:--work-tree 的路径必须是你的实际网站根目录

1
2
3
#!/bin/bash
# 将推送过来的代码检出到指定的网站目录
git --work-tree=/www/wwwroot/blog.Lasuy.cn --git-dir=/home/git/repos/taiblog.git checkout -f

赋予脚本执行权限:

1
chmod +x post-receive

2.4 【踩坑点】目录权限与路径大小写

这是迁移过程中最容易出错的地方。

坑点 1:路径大小写严格区分
Linux 系统对路径大小写是敏感的。如果在配置 Git 钩子时,将 /www/wwwroot/blog.Lasuy.cn 错写成全小写的 blog.lasuy.cn,会导致 git checkout 失败或检出到错误的目录,表现为本地提示 Deploy done,但服务器页面死活不更新。

坑点 2:目录权限问题
如果在本地执行 hexo d 时遇到类似 remote: error: unable to unlink old '...': Permission denied 的报错,100% 是权限问题
因为网站目录通常是由 rootwww 创建的,而我们推送代码使用的是 git 用户,导致 git 用户没有权限向该目录写入或删除文件。

解决方法:切换回 root 用户,强制修改网站目录的所有权,并确保路径拼写完全正确。

1
2
3
4
5
6
7
8
# 切换回 root
exit

# 将网站目录的所有权赋给 git 用户和组(注意路径大小写必须和实际完全一致)
chown -R git:git /www/wwwroot/blog.Lasuy.cn

# 确保目录权限正确 (755 代表所有者有读写执行权限,其他用户有读执行权限)
chmod -R 755 /www/wwwroot/blog.Lasuy.cn

3. 本地 Hexo 配置

服务器端配置好后,回到本地项目,修改 _config.yml 文件中的 deploy 字段。

3.1 【踩坑点】非标准 SSH 端口

因为我的新服务器修改了 SSH 端口为 996(为了防爆破),所以不能使用默认的 git@IP:/path 格式,否则会报 Connection timed out

必须改用 ssh:// 协议,并在 IP 后加上端口号:

1
2
3
4
5
deploy:
type: git
# 格式:ssh://用户名@服务器IP:端口号/裸仓库绝对路径
repository: ssh://git@118.25.138.212:996/home/git/repos/taiblog.git
branch: master

4. 部署测试

一切配置妥当后,在本地终端执行:

1
2
hexo clean
hexo deploy

当你看到类似下面的输出时,说明部署大功告成:

1
2
3
4
5
Enumerating objects: 229, done.
Counting objects: 100% (229/229), done.
...
branch 'main' set up to track 'ssh://git@118.25.138.212:996/home/git/repos/taiblog.git/master'.
INFO Deploy done: git

现在,刷新你的浏览器,就能看到最新的博客内容了!

5. 进阶:配置 SSH 免密推送

每次部署都需要输入密码非常繁琐,配置 SSH 免密推送可以实现真正的“一键部署”。

5.1 获取本地公钥

在本地电脑终端执行以下命令,查看你的 SSH 公钥(通常是 id_rsa.pubid_ed25519.pub):

1
2
# Windows 环境下查看公钥
cat ~/.ssh/id_ed25519.pub

复制输出的那一大串以 ssh-ed25519ssh-rsa 开头的字符串。

5.2 将公钥配置到服务器

登录服务器,切换到 git 用户,将公钥写入到授权文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 切换到 git 用户
su - git

# 确保目录和文件存在并设置正确的安全权限
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# 使用 vim 编辑文件,将刚才复制的公钥粘贴进去
vim ~/.ssh/authorized_keys
# 或者直接使用 echo 追加 (替换为你自己的公钥内容)
# echo "ssh-ed25519 AAAAC3N... your_email@example.com" >> ~/.ssh/authorized_keys

保存退出后,在本地再次执行 hexo deploy,就不会再提示你输入密码了,丝滑推送!

总结

Hexo 的 Git 部署本质上就是一次 SSH 推送 + 服务器本地文件复制。遇到报错时,重点排查三点:

  1. 网络/端口连通性(Connection timed out):检查安全组、防火墙和 SSH 端口配置。
  2. 文件权限(Permission denied):检查 git 用户对目标 work-tree 目录是否有读写权限。
  3. 路径大小写(部署成功但页面不更新):Linux 严格区分大小写,检查宝塔面板中的目录名与 Git 钩子脚本中的 --work-tree 路径是否完全一致

希望这篇文章能帮你避开这些坑,享受丝滑的写作体验。