Hexo 博客从 GitHub Pages 迁移到你自己的服务器。
这篇文章记录我把 Hexo + GitHub Pages 迁移到自己的服务器上的一套可用方案。
最终思路很简单:
- 服务器上准备一个裸仓库
hexo.git - 本地执行
hexo d时,把生成好的静态文件推送到这个仓库 - 服务器通过
post-receive钩子自动把最新内容检出到网站目录 - Nginx 读取网站目录,对外提供静态页面
- 域名、SSL、外网访问交给 Nginx Proxy Manager 处理
这样做的好处是:
- 本地更新博客后,直接
hexo clean && hexo g && hexo d - 服务器不需要手动上传文件
- 部署路径固定,后续维护比较省心
这里主要参考了这篇文章的思路:
https://www.cnblogs.com/cheyaoyao/p/17836522.html#33-git-%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE
一、服务器端准备 Git 自动部署
1. 安装 Git
apt update |
2. 创建 git 用户
adduser git |
如果你后面要让 git 用户通过钩子把文件写入站点目录,通常会涉及 sudo 或 ACL 权限控制。
如果要给 git 用户 sudo 权限,可以这样做:
chmod 740 /etc/sudoers |
找到:
root ALL=(ALL) ALL |
在下面添加:
git ALL=(ALL) ALL |
保存后恢复权限:
chmod 400 /etc/sudoers |
3. 创建裸仓库
cd /home/git |
这里创建的是一个裸仓库,它只负责接收推送,不直接用来当网站目录。
二、配置 Git 钩子自动发布
编辑钩子文件:
sudo vim /home/git/hexo.git/hooks/post-receive |
写入下面内容:
|
然后给钩子执行权限:
chmod +x /home/git/hexo.git/hooks/post-receive |
这个钩子的作用是:
- 每次本地
git push到hexo.git - 服务器自动把最新文件强制检出到
/data/hexo - 最终 Nginx 直接读取
/data/hexo提供静态站点
三、给网站目录配置权限
这一步非常重要,也是最容易踩坑的地方。
很多人以为只要:
chown -R www-data:www-data /data/hexo |
就够了,但实际往往不够。因为这里涉及两个角色:
git:负责写入、更新博客静态文件www-data:Nginx 默认运行用户,负责读取博客文件
也就是说,git 要能写,www-data 要能读,而且 Nginx 不只是要读文件本身,还必须能“进入路径上的每一级目录”。
1. 先创建网站目录
sudo mkdir -p /data/hexo |
2. 先理解 Linux 目录权限
目录权限和文件权限不完全一样:
r:可以查看目录内容列表w:可以在目录里创建、删除、重命名x:可以进入目录
对于 Nginx 来说,最关键的是:
它必须对路径上的每一级目录都至少有 x 权限,否则即使文件本身可读,也会报 403 或 502。
例如你的博客目录是:
/data/hexo/index.html |
那么 Nginx 至少要能穿过:
//data/data/hexo
所以不能只盯着 /data/hexo,父目录权限也要检查。
3. 推荐做法:使用 ACL 同时给 git 和 www-data 授权
先安装 ACL 工具:
apt install acl -y |
然后给 git 和 www-data 分别授权:
sudo setfacl -R -m u:git:rwx /data/hexo |
这几条命令的含义:
u:git:rwx:git用户可读、可写、可进入目录u:www-data:rx:www-data用户可读、可进入目录,但不能写-R:递归作用到当前已有文件和目录-d:设置默认 ACL,后续新生成的文件和目录也自动继承
4. 父目录也要保证可以进入
如果 /data 本身权限太严,Nginx 依旧读不到 /data/hexo。
所以建议检查:
namei -l /data/hexo/index.html |
这个命令会把路径的每一级权限拆开显示,非常适合排查 “为什么文件明明在,但 Nginx 读不到” 这种问题。
如果发现 /data 没有给 www-data 执行权限,可以补:
sudo setfacl -m u:www-data:x /data |
如果 /data 下还有更深层目录,也要同样检查。
5. 查看 ACL 是否生效
getfacl /data/hexo |
你会看到类似结果:
# file: /data/hexo |
如果这里只给了 git,没给 www-data,Nginx 就会打不开文件。
6. 如果你想用 chown 的简单方式
也可以这样做:
sudo chown -R git:www-data /data/hexo |
这种方式思路是:
- 所有者给
git - 所属组给
www-data - 目录可进入、可读
- 文件可读
但这种方式不如 ACL 灵活,后面如果文件来源复杂,ACL 更稳一些。
四、配置本地 Hexo 部署
在本地博客目录安装 Git 部署插件:
npm install hexo-deployer-git --save |
修改博客根目录下的 _config.yml:
deploy: |
同时确认站点地址也改成你自己的域名:
url: https://www.zxzlimit.xin |
以后本地更新博客,直接执行:
hexo clean && hexo g && hexo d |
如果还没配置 SSH 免密,每次部署都要输密码。
五、配置 SSH 免密登录
可以直接用:
ssh-copy-id git@your_server_ip |
或者自己手动生成公钥并追加到服务器的 ~/.ssh/authorized_keys。
配置完成后,再执行 hexo d 就不会反复输入密码了。
六、配置 Nginx 读取静态站点
我这里的做法是:
- Nginx 监听本地端口
8123 - Nginx Proxy Manager 负责把域名和 SSL 代理到这个端口
先安装 Nginx,然后编辑:
sudo vim /etc/nginx/sites-available/default |
写入:
server { |
检查配置:
sudo nginx -t |
重启:
sudo systemctl restart nginx |
此时本机应该可以通过下面地址访问:
http://服务器IP:8123 |
如果访问失败,优先检查三类问题:
1. Nginx 配置语法是否正确
sudo nginx -t |
2. Nginx 是否真的在监听 8123
ss -tlnp | grep 8123 |
3. 权限是否真的到位
重点检查:
namei -l /data/hexo/index.html |
最后这条非常实用,它能直接模拟 www-data 是否真的能读到文件。
如果输出不是 ok,就说明还是权限问题。
七、查看部署日志
如果本地推送成功了,但页面没更新,就去服务器上看钩子日志:
cat /home/git/hexo.git/deploy.log |
常见问题基本都能从这里看出来,比如:
git用户没权限写/data/hexo- 钩子文件没执行权限
- 仓库路径写错
- 检出目录不存在
八、最终流程总结
以后你的更新流程就是:
- 本地写文章
- 执行:
hexo clean && hexo g && hexo d |
- 本地把静态文件推送到服务器裸仓库
- 服务器钩子自动检出到
/data/hexo - Nginx 直接读取
/data/hexo - NPM 负责域名和 SSL 对外访问
这套方案的核心优点是:
- 不需要每次手工上传静态文件
- 不依赖 GitHub Pages
- 更新路径稳定
- 本地和服务器职责清晰
如果后面访问还是有问题,优先排查的顺序建议固定为:
hexo d是否推送成功deploy.log是否有报错/data/hexo是否真的有最新文件www-data是否真的能读取这些文件nginx -t是否通过8123端口是否正常监听
这样排查会比一开始就怀疑 Nginx、怀疑 Hexo、怀疑域名快很多。