玩了这么久Hexo(也就两个月),从刚入行时的GitHub Pages
,再到NetLify
,Vercel
甚至CloudFarePages
各种免费托管平台,为了追求速度到阿里云OSS
,腾讯云COS
,各种对象存储,再到内网穿透,内网建站Frp
之类,或者说,如果你有一台服务器的话,直接在Nginx
上部署,然后你就会发现,免费的是最贵的,更划算的方案是花一点小钱,才能实现令人满意的效果。
就我个人经验而谈,最佳方案有两种:
- 如果没有服务器,那就对象存储
Nginx
服务器
在这基础上,有条件的套一层CDN
,也不用大费周折搞什么图床(这两种方案之下整图床都是负优化),图片直接放在博客的source
目录下即可(新建一个图片目录)。因为对于一般的个人博客,你的博客从一开始写到你放弃这个博客,你的图片也很难占用一个很大的空间,感觉10GB的空间都很富足了。如果你就是分享照片或者视频的网站当我没说。
那本文就将详细讲一下怎么把
Hexo
博客推送到Nginx
服务器。
从本地Hexo
到服务器有多种部署协议,如 SCP
、FTP
或 Git
,因为我们一开始大部分都是通过Git
部署到Github
,但是我们或多或少都遇到过因为网络问题而推送失败,真的很烦,有时候换几次网也不行,所以我一直对Git
推送这种方式耿耿于怀。
今天介绍的这种方式还是基于Git
,只不过是推送到自己的服务器,基本不存在网络问题,这就很舒畅。
我们都知道Nginx
服务器存放静态网页的目录在/usr/share/nginx/html/
下,在这下面你创建一个文件夹,存放你的public
文件夹,然后在/etc/nginx/conf.d/
下设置一个配置文件,这样就可以通过ip加端口或者域名来访问你的网站。
所以,可以直接推送到/usr/share/nginx/html/
下吗?
可行,但是比较复杂。
因为我们要通过Git
推送,就必须保证推送地址本身是个仓库,我们需要将其初始化为一个裸仓库或者非裸仓库。
(在 Git 中,仓库可以是裸仓库(bare repository)或非裸仓库(non-bare repository)。
非裸仓库是我们通常使用的仓库类型,它包含一个 .git
目录和工作目录。.git
目录包含了所有的版本控制信息,包括提交历史、分支、标签等。工作目录则包含了你的项目文件,你可以在这里编辑文件、查看文件的状态、进行提交等。
裸仓库只包含版本控制信息,没有工作目录。这意味着你不能在裸仓库中直接编辑文件或查看文件的状态。裸仓库通常用作远程仓库,例如在 GitHub 或 GitLab 上托管的仓库就是裸仓库。
总的来说,非裸仓库是你在本地进行开发时使用的仓库,它包含了工作目录,你可以在这里编辑文件、进行提交等。裸仓库通常用作远程仓库,用于存储版本控制信息,而不用于直接编辑文件。)
如果初始化为一个裸仓库,我们推送完成之后,看不到工作目录,也就看不到
public
文件夹,也就是目的地址并不能直接当作Nginx
的HTML
目录。
一个裸仓库的文件大概如下:
(我找半天也没找到我的静态文件目录)
如果推送到一个非裸仓库,里面默认包含工作树,当你试图推送到这个仓库的当前分支时,Git 会拒绝,因为这会使索引和工作树与你推送的内容不一致。
在本地推送时,你大概会遇到这种报错:
On branch master
nothing to commit, working tree clean
Enumerating objects: 710, done.
Counting objects: 100% (710/710), done.
Delta compression using up to 16 threads
Compressing objects: 100% (326/326), done.
Writing objects: 100% (550/550), 148.70 KiB | 1.33 MiB/s, done.
Total 550 (delta 285), reused 4 (delta 2), pack-reused 0
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
然而,如果你仍然想要这样做,你可以在服务器上的仓库中设置 receive.denyCurrentBranch
配置变量为 ignore
。这将允许你直接推送到当前分支,但你需要自己确保工作树与你推送的内容保持一致。你可以使用以下命令:
git config receive.denyCurrentBranch ignore
然后,你可以直接推送到你的服务器上的仓库。但是,你需要在每次推送后,手动在服务器上更新工作树,以使其与你推送的内容一致。你可以使用以下命令:
git reset --hard
请注意,这种方法有风险,因为如果你在服务器上的工作树中有未提交的更改,git reset --hard
命令会丢弃这些更改。
所以最佳的方案应该是:裸仓库和钩子
在服务器上创建一个裸仓库(bare repository)。裸仓库不包含工作树,只包含Git
的内部数据,因此你可以安全地推送到它。然后,你可以在服务器上设置一个钩子(hook),当你推送到裸仓库时,钩子会将你的博客静态文件复制到你的网站目录。
以下是在服务器上创建裸仓库和设置钩子的步骤:
- 在服务器上,创建一个新的裸仓库:
mkdir /path/to/your/bare/repo.git
cd /path/to/your/bare/repo.git
git init --bare
/path/to/your/bare/repo.git
是你裸仓库的地址。
- 在裸仓库的
hooks
目录下,创建一个名为post-receive
的文件,这将是你的钩子:
nano hooks/post-receive
- 在
post-receive
文件中,添加以下内容:
#!/bin/sh
DIR=yourhtml
if [ ! -d "$DIR" ]; then
mkdir -p "$DIR"
fi
GIT_WORK_TREE=$DIR git checkout -f
将yourhtml
换成你想在nginx中存放静态文件的目录,即你的网站目录,如果你就是用nginx,这个目录应该是usr/share/nginx/html/yourwebsite
,如果你用1panel
中的openresty
,这个目录应该是/opt/1panel/apps/openresty/openresty/www/sites/your-website-name/index/yourwebsite
,或者你用其他面板,自行寻找下网站在反代软件下的目录,很简单。
这将会在你推送到裸仓库时,将你的博客静态文件复制到你的网站目录。
- 保存并关闭文件,然后使其可执行:
chmod +x hooks/post-receive
然后,你可以在本地的 Hexo 博客的 public
目录中,将你的服务器的裸仓库添加为一个远程仓库,然后将你的博客静态文件推送到裸仓库。(这个只是单次部署的一个流程,如果你想每次都用hexo d
这个命令自动部署,可以跳过这个步骤,直接看下面的)你可以使用以下命令:
cd public
git remote add origin root@your_server:/path/to/your/bare/repo.git
git add .
git commit -m "Deploy my blog"
git push -u origin master
在这些命令中,root
是你的服务器用户名,your_server
是你的服务器地址,/path/to/your/bare/repo.git
是你在服务器上创建的裸仓库的路径。
然后,你可以在 Hexo 的配置文件 _config.yml
中设置部署命令,以便在运行 hexo d
命令时自动部署你的博客。你可以添加以下内容:
deploy:
type: git
repo: root@your_server:/path/to/your/bare/repo.git
branch: master
在这个配置中,root
是你的服务器用户名,your_server
是你的服务器地址,/path/to/your/bare/repo.git
是你在服务器上创建的裸仓库的路径。(当然你要提前设置好ssh免密登录)
然后,你可以运行 hexo d
命令来部署你的博客。这将会自动运行 git 命令,将你的博客静态文件推送到你的服务器上的裸仓库,然后钩子会将文件复制到你的网站目录。
最后,还有一个问题,既然我能把博客推送到一个裸仓库,那我为什么就找不到我博客的目录结构呢?
在Git
裸仓库中,你的博客文件实际上被存储在Git
的内部数据结构中,这些数据结构包括blobs
(用于存储文件数据)、trees
(用于存储目录结构)和commits
(用于存储历史记录)。这些数据结构被存储在裸仓库的 .git/objects
目录下。然而,这些数据是以 Git 的内部格式存储的,因此你不能直接在文件系统中看到你的博客的文件结构。