Hexo 博客部署到服务器完整教程
这篇文章记录一套从零到可上线的 Hexo 部署流程:本地用 Hexo 写文章并生成静态文件,把生成后的 public/ 上传到自己的云服务器,再由 Docker 中的 Nginx 对外提供访问。
最终目标是:
1 | 本地 Hexo 项目 |
这套方式的优点是结构清晰、排错简单。Hexo 只负责生成静态页面,服务器只负责托管 HTML、CSS、JS、图片等静态资源。
一、准备工作
你需要准备:
- 一台云服务器,例如阿里云 ECS。
- 一个域名,例如
example.com。 - 本地安装 Node.js、npm、Git。
- 服务器安装 Docker 和 Docker Compose。
- 本地可以通过 SSH 连接服务器。
本文示例中使用:
1 | 服务器 IP:47.115.213.32 |
实际使用时,把这些值替换成你自己的。
二、本地安装并初始化 Hexo
先检查本地环境:
1 | node -v |
安装 Hexo CLI:
1 | npm install -g hexo-cli |
初始化博客:
1 | hexo init myblog |
本地预览:
1 | hexo server |
默认访问:
1 | http://localhost:4000 |
新建文章:
1 | hexo new "我的第一篇博客" |
文章会生成在:
1 | source/_posts/ |
生成静态文件:
1 | hexo clean |
生成结果在:
1 | public/ |
后续真正部署到服务器的就是 public/ 目录里的内容,不是整个 Hexo 项目。
三、服务器目录规划
登录服务器:
1 | ssh root@47.115.213.32 |
创建目录:
1 | sudo mkdir -p /opt/hexo-blog/html |
推荐目录结构:
1 | /opt/hexo-blog |
其中最重要的是:
1 | /opt/hexo-blog/html |
这个目录会挂载到 Nginx 容器里的:
1 | /usr/share/nginx/html |
也就是说,服务器上的 /opt/hexo-blog/html/index.html,在容器里就是 /usr/share/nginx/html/index.html。
四、编写 Docker Compose
创建 docker-compose.yml:
1 | sudo nano /opt/hexo-blog/docker-compose.yml |
写入:
1 | services: |
说明:
80:80用于 HTTP 访问和证书验证。443:443用于 HTTPS 访问。./html:/usr/share/nginx/html:ro把静态文件挂载给 Nginx。./conf.d:/etc/nginx/conf.d:ro把 Nginx 配置挂载进容器。./certbot/conf:/etc/letsencrypt保存证书。
五、先配置 HTTP 站点
在申请 HTTPS 之前,建议先让 HTTP 正常访问。
创建 Nginx 配置:
1 | sudo nano /opt/hexo-blog/conf.d/hexo.conf |
如果你已经有域名,先写:
1 | server { |
如果还没有域名,可以临时使用 IP:
1 | server { |
启动 Nginx:
1 | cd /opt/hexo-blog |
检查容器:
1 | sudo docker ps |
检查 Nginx 配置:
1 | sudo docker compose exec nginx nginx -t |
六、上传 Hexo 静态文件
在本地 Hexo 项目里生成静态文件:
1 | hexo clean |
如果你本地是 Windows PowerShell,可以用:
1 | ssh root@47.115.213.32 "rm -rf /opt/hexo-blog/html/*" |
上传后,在服务器检查:
1 | ls -la /opt/hexo-blog/html |
应该能看到:
1 | index.html |
此时访问:
1 | http://47.115.213.32/ |
或:
1 | http://lbwxxc.top/ |
如果能打开页面,说明 Hexo 静态文件和 Nginx 托管已经正常。
七、配置域名 DNS
如果不使用 CDN,最简单的 DNS 配置是 A 记录直连 ECS:
1 | @ A 47.115.213.32 |
含义:
@表示根域名,例如lbwxxc.top。www表示www.lbwxxc.top。- A 记录的值填服务器公网 IP。
配置完成后,本地刷新 DNS:
1 | ipconfig /flushdns |
检查解析:
1 | nslookup lbwxxc.top |
正确结果应该都指向:
1 | 47.115.213.32 |
注意:同一个主机记录不能同时存在 CNAME 和 A。比如 @ 不能既有 CNAME 又有 A,www 也不能既有 CNAME 又有 A。
八、配置 HTTPS
确认 HTTP 可以访问后,再申请 HTTPS 证书。
先确保 Nginx 配置里有这个验证路径:
1 | location /.well-known/acme-challenge/ { |
然后执行 Certbot:
1 | sudo docker run --rm \ |
证书成功后,修改 Nginx 配置:
1 | sudo nano /opt/hexo-blog/conf.d/hexo.conf |
不使用 CDN 时,推荐这样写:
1 | server { |
检查并重载:
1 | cd /opt/hexo-blog |
测试:
1 | curl.exe --ssl-no-revoke -I https://lbwxxc.top/ |
正常应该看到:
1 | HTTP/1.1 200 OK |
九、日常更新博客流程
本地写文章:
1 | hexo new "文章标题" |
确认没问题后生成:
1 | hexo clean |
上传到服务器:
1 | ssh root@47.115.213.32 "rm -rf /opt/hexo-blog/html/*" |
这种情况下不需要重启 Nginx,也不需要重启 Docker 容器。因为 Nginx 只是读取挂载目录里的静态文件,你替换了 /opt/hexo-blog/html 里的内容,下一次访问就会读到新文件。
只有修改这些内容时,才需要重载 Nginx:
- Nginx 配置文件。
docker-compose.yml。- HTTPS 证书配置。
- 域名
server_name。
重载命令:
1 | sudo docker compose exec nginx nginx -t |
十、写一个本地部署脚本
可以在 Hexo 项目根目录创建 deploy.ps1:
1 | hexo clean |
以后更新文章后执行:
1 | .\deploy.ps1 |
如果你使用 CDN,部署后还需要去 CDN 控制台刷新缓存,尤其是首页、文章页、CSS、JS 有变化时。
十一、使用 CDN 时的配置
如果你使用阿里云 CDN,链路会变成:
1 | 用户 -> CDN -> ECS 源站 Nginx |
这时 DNS 不再直接 A 到服务器,而是 CNAME 到 CDN:
1 | @ CNAME lbwxxc.top 对应的 CDN CNAME |
CDN 控制台建议:
1 | HTTPS:开启 |
重点:如果 CDN 回源走 HTTP,源站 Nginx 不要再把 HTTP 跳转到 HTTPS,否则很容易出现重定向循环。
走 CDN 时,源站 Nginx 可以只监听 80:
1 | server { |
也就是说:
1 | 不走 CDN:Nginx 做 HTTP -> HTTPS 跳转。 |
这是整套部署中最容易出错的地方。
十二、最终推荐方案
如果不使用 CDN:
1 | DNS: |
如果使用 CDN:
1 | DNS: |
十三、易错问题汇总与解决方案
1. 关闭 CDN 后网站访问不了
现象:
1 | CDN 已停止,但访问域名失败。 |
例如:
1 | lbwxxc.top -> lbwxxc.top.w.cdngslb.com -> offline.specialcdnstatus.com |
原因:
1 | 你停用了 CDN,但 DNS 仍然指向 CDN。 |
解决:
1 | 删除或暂停 @ 的 CNAME。 |
示例:
1 | @ A 47.115.213.32 |
2. 根域名能否访问取决于 @ 记录
现象:
1 | https://www.lbwxxc.top 可以访问 |
原因通常是:
1 | www 已经 A 到服务器 IP。 |
解决:
1 | 把 @ 记录也改成 A 记录: |
验证:
1 | ipconfig /flushdns |
两者都应该解析到服务器 IP。
3. A 记录和 CNAME 不能同时存在
同一个主机记录不能同时配置 A 和 CNAME。
错误示例:
1 | @ CNAME xxx.cdn.com |
正确做法:
1 | 不用 CDN:保留 A,删除 CNAME。 |
4. HTTPS 证书申请失败
常见原因:
- 域名没有解析到当前服务器。
- 服务器安全组没有放行 80 端口。
- Docker 没有映射 80 端口。
- Nginx 没有配置
/.well-known/acme-challenge/。 - CDN 干扰了验证请求。
排查顺序:
1 | nslookup lbwxxc.top |
如果还没申请证书,先不要急着写复杂的 HTTPS 配置。先确保 HTTP 能正常访问。
5. Windows curl 报证书吊销检查错误
现象:
1 | CRYPT_E_REVOCATION_OFFLINE |
或:
1 | schannel: next InitializeSecurityContext failed |
可以用:
1 | curl.exe --ssl-no-revoke -I https://www.lbwxxc.top/ |
如果返回 200 OK,说明网站 HTTPS 基本正常,问题可能是 Windows 本地证书吊销检查无法联网完成。
6. 浏览器提示重定向次数过多
现象:
1 | ERR_TOO_MANY_REDIRECTS |
常见原因:
1 | CDN 回源 HTTP。 |
解决:
1 | 走 CDN:让 CDN 做 HTTP -> HTTPS,源站 Nginx 不跳。 |
7. 修改文章后需要重启 Nginx 吗
不需要。
文章更新流程只是替换静态文件:
1 | hexo generate -> public/ -> 上传到 /opt/hexo-blog/html |
Nginx 会直接读取新文件。
只有修改 Nginx 配置、证书配置、端口映射时,才需要:
1 | sudo docker compose exec nginx nginx -t |
8. 访问 404 页面但状态码不对
如果这样写:
1 | location / { |
用户可能看到 404 页面,但 HTTP 状态码是 200。
更推荐:
1 | location / { |
这样状态码更准确。
9. Docker Nginx 访问不到静态文件
检查挂载:
1 | volumes: |
检查服务器目录:
1 | ls -la /opt/hexo-blog/html |
检查容器内目录:
1 | sudo docker compose exec nginx ls -la /usr/share/nginx/html |
如果容器内看不到 index.html,说明挂载目录或上传路径错了。
10. 主题配置导致 Hexo 生成报错
如果使用 Stellar 等主题,常见报错可能不是 Hexo 本身问题,而是主题配置层级写错。
例如 article.related_posts 被写空、写错层级,或者把整个 article 覆盖成 null,都可能导致生成失败。
建议检查:
1 | _config.yml |
相关文章配置可以先关闭:
1 | article: |
如果想开启相关文章,再安装对应插件并按主题文档配置。
11. 主题语言配置不生效
简体中文通常应该写:
1 | language: zh-CN |
不要写成:
1 | language: zh-TW |
zh-TW 是繁体中文,zh-CN 才是简体中文。
如果主题还有自己的语言文件,也要确认主题目录下是否存在对应的 zh-CN.yml。
总结
Hexo 部署到自己的服务器,本质上只有三件事:
1 | 1. 本地生成静态文件。 |
Docker Nginx 方案的核心配置是:
1 | /opt/hexo-blog/html -> /usr/share/nginx/html |
不用 CDN 时,DNS 直接 A 到 ECS,Nginx 负责 HTTPS 跳转。
使用 CDN 时,DNS CNAME 到 CDN,CDN 负责 HTTPS 跳转,源站 Nginx 不要再跳 HTTPS。
把这几条关系理清楚,后续无论是更新文章、配置证书、排查 DNS,都会简单很多。