Mac上安装和配置Hexo博客

安装

安装Node.js

1
brew install node
1
2
node -v         
v18.11.0

安装Hexo 1

1
npm install -g hexo-cli
1
2
npm info hexo-cli version
4.3.0

Blog文件夹下初始化Hexo:

1
2
3
cd Blog
hexo init
npm install

升级Hexo 2

进入带有package.json文件的Hexo文件夹

1
npm update

安装/升级NexT主题 3 4

Blog文件夹下:

1
npm install hexo-theme-next@latest

修改Blog/_config.yml文件:

1
theme: next

测试:

1
2
hexo clean
hexo s --debug

浏览器打开http://localhost:4000

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
hexo -v

INFO Validating config
INFO ==================================
███╗ ██╗███████╗██╗ ██╗████████╗
████╗ ██║██╔════╝╚██╗██╔╝╚══██╔══╝
██╔██╗ ██║█████╗ ╚███╔╝ ██║
██║╚██╗██║██╔══╝ ██╔██╗ ██║
██║ ╚████║███████╗██╔╝ ██╗ ██║
╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝
========================================
NexT version 8.13.1
Documentation: https://theme-next.js.org
========================================
hexo: 6.3.0
hexo-cli: 4.3.0
os: darwin 21.6.0 12.6

node: 18.11.0
v8: 10.2.154.15-node.12
uv: 1.44.2
zlib: 1.2.11
brotli: 1.0.9
ares: 1.18.1
modules: 108
nghttp2: 1.50.0
napi: 8
llhttp: 6.0.10
openssl: 1.1.1q
cldr: 41.0
icu: 71.1
tz: 2022a
unicode: 14.0

配置

在Hexo中有两份主要的配置文件,其名称都是_config.yml。 其中,一份位于站点根目录下,主要包含Hexo本身的配置;另一份位于主题目录下/node_modules/hexo-theme-next/_config.yml,这份配置由主题作者提供,主要用于配置主题相关的选项。为了描述方便,在以下说明中,将前者称为站点配置文件, 后者称为主题配置文件

主题配置文件

主题配置文件文件/node_modules/hexo-theme-next/_config.yml中修改:

Schemes

1
scheme: Pisces

language

1
language: en
1
2
3
4
5
6
7
8
9
10
11
12
13
# Usage: `Key: /link/ || icon`
# Key is the name of menu item. If the translation for this item is available, the translated text will be loaded, otherwise the Key name will be used. Key is case-sensitive.
# Value before `||` delimiter is the target link, value after `||` delimiter is the name of Font Awesome icon.
# External url should start with http:// or https://
menu:
home: / || fa fa-home
about: /about/ || fa fa-user
tags: /tags/ || fa fa-tags
categories: /categories/ || fa fa-th
archives: /archives/ || fa fa-archive
#schedule: /schedule/ || fa fa-calendar
#sitemap: /sitemap.xml || fa fa-sitemap
#commonweal: /404/ || fa fa-heartbeat

手动创建页面tags:

1
hexo new page "tags"

修改Blog/source/tags/index.md

1
2
3
4
5
6
---
title: tags
date: 2016-01-28 18:44:44
type: "tags"
comments: false
---
1
hexo new page "categories"

修改Blog/source/categories/index.md

1
2
3
4
5
6
---
title: categories
date: 2016-01-28 19:18:13
type: "categories"
comments: false
---

手动创建页面categories:

1
hexo new page "categories"

修改Blog/source/categories/index.md

1
2
3
4
5
6
---
title: categories
date: 2016-01-28 19:18:13
type: "categories"
comments: false
---

手动创建页面about:

1
hexo new page "about"

修改Blog/source/about/index.md

1
2
3
4
5
---
title: about
date: 2016-01-28 19:43:39
comments: false
---
1
2
3
sidebar:
position: left
display: always

头像

放置在source/images/目录下,配置为:avatar: /images/avatar.png

1
2
3
4
5
6
# Sidebar Avatar
avatar:
# Replace the default image and set the url here.
url: /images/avatar.png
# If true, the avatar will be displayed in circle.
rounded: true

Google Analytics

1
2
3
4
5
6
7
# Google Analytics
# See: https://analytics.google.com
google_analytics:
tracking_id: G-FKR2744S26
# By default, NexT will load an external gtag.js script on your site.
# If you only need the pageview feature, set the following option to true to get a better performance.
only_pageview: false

社交链接

1
2
3
4
5
social:
GitHub: https://github.com/HanjieLuo || fab fa-github
Linkedin: https://www.linkedin.com/in/hanjie-luo-89602197 || fa-brands fa-linkedin-in
YouTube: https://www.youtube.com/luohanjie || fab fa-youtube
Bilibili: https://space.bilibili.com/319752 || fa-brands fa-bilibili

disqus

1
2
3
4
disqus:
enable: true
shortname: luohanjie
count: true

代码高亮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
codeblock:
# Code Highlight theme
# All available themes: https://theme-next.js.org/highlight/
theme:
light: stackoverflow-light
dark: stackoverflow-dark
prism:
light: prism
dark: prism-dark
# Add copy button on codeblock
copy_button:
enable: false
# Available values: default | flat | mac
style:

访客统计、访问次数统计、文章阅读次数统计

1
2
3
4
5
6
7
8
9
10
# Show Views / Visitors of the website / page with busuanzi.
# For more information: http://ibruce.info/2015/04/04/busuanzi/
busuanzi_count:
enable: true
total_visitors: true
total_visitors_icon: fa fa-user
total_views: true
total_views_icon: fa fa-eye
post_views: true
post_views_icon: far fa-eye

本地显示的数字是随机的,部署到服务器上面就好了。

站点建立时间

1
2
3
footer:
# Specify the year when the site was setup. If not defined, current year will be used.
since: 2016
1
npm install hexo-generator-searchdb

Blog\_config.yml添加:

1
2
3
4
5
search:
path: search.xml
field: post
content: true
format: html

修改/node_modules/hexo-theme-next/_config.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Local search
# Dependencies: https://github.com/next-theme/hexo-generator-searchdb
local_search:
enable: true
# If auto, trigger search by changing input.
# If manual, trigger search by pressing enter key or search button.
trigger: auto
# Show top n results per article, show all results by setting to -1
top_n_per_article: 1
# Unescape html strings to the readable one.
unescape: false
# Preload the search data when the page loads.
preload: false

mathjax 5

1
2
3
4
brew install pandoc

npm uninstall hexo-renderer-marked
npm install hexo-renderer-pandoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Math Formulas Render Support
# Warning: Please install / uninstall the relevant renderer according to the documentation.
# See: https://theme-next.js.org/docs/third-party-services/math-equations
# Server-side plugin: https://github.com/next-theme/hexo-filter-mathjax
math:
# Default (false) will load mathjax / katex script on demand.
# That is it only render those page which has `mathjax: true` in front-matter.
# If you set it to true, it will load mathjax / katex script EVERY PAGE.
every_page: true

mathjax:
enable: true
# Available values: none | ams | all
tags: ams

katex:
enable: false
# See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex
copy_tex: false

CDN

1
2
3
4
5
vendors:
internal: local
plugins: cdnjs
# Custom CDN URL
custom_cdn_url: https://lib.baomitu.com/${cdnjs_name}/${version}/${cdnjs_file}

Favicon

准备一张260x260以上大的图片:

favicon

用软件转换成svg格式,改名为logo.svg。在realfavicongenerator或者websiteplanet(It allows to create favicons from pictures that are up to 5 MB. thanks to Virgy)上生成favicon_package包,包括favicon-16x16-next.png(由favicon-16x16.png改名),favicon-32x32-next.png(由favicon-32x32.png改名),apple-touch-icon-next.png(由apple-touch-icon.png改名)。将以上4张图片复制到Blog/node_modules/hexo-theme-next/source/images/进行替换。

站点配置文件

站点配置文件文件_config.yml中修改:

网站

1
2
3
4
5
6
7
title: Hanjie's Blog
subtitle: 一只有理想的羊驼
description: ''
keywords:
author: Hanjie Luo
language: en
timezone: ''

网址

1
2
3
4
5
6
7
8
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: http://luohanjie.com
permalink: :year-:month-:day/:urlname.html
permalink_defaults:
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
trailing_html: true # Set to false to remove trailing '.html' from permalinks

文章的Formatter:

1
2
3
4
5
6
7
title: Mac上安装和配置Hexo博客
urlname: install-and-create-a-blog-with-hexo-on-mac
categories: [Tech, Web]
date: 2022-10-25 16:08:00
tags: [Web, Mac, Hexo, Next]
published: true
---

文章

1
2
3
4
5
6
7
8
# Writing
new_post_name: :title.md # File name of new posts
filename_case: 1
highlight:
enable: true
line_number: false
auto_detect: true
tab_replace:

分页

1
2
3
4
index_generator:
path: ''
per_page: 3
order_by: -date

hexo-renderer-markdown-it

支持footnote

可以通过将markdown渲染器替换为hexo-renderer-markdown-it,使得支持footnote功能6。必须要先卸载原先的渲染器,然后安装:

1
2
npm un hexo-renderer-marked --save
npm i hexo-renderer-markdown-it --save

然后在网站\_config.yml文件中添加:

1
2
3
markdown:
plugins:
- markdown-it-footnote

然后发现每一条footnote间都有一行间隔。想要去掉的话,可以在/Blogs//Users/luohanjie/Workspace/Web/Blog/node_modules/hexo-theme-next/source/css/_common/components/post/post-footer.styl中添加:

1
2
3
.footnote-item p {
margin-bottom: 0
}

hexo-renderer-markdown-it还支持很多其他的功能,具体可以到官网了解。

html

The html setting defines whether or not HTML content inside the document should be escaped or passed to the final result.

1
2
3
markdown:
render:
html: true # Doesn't escape HTML content

支持插入pdf

1
npm install --save hexo-pdf

主题配置文件文件/node_modules/hexo-theme-next/_config.yml中修改:

1
2
3
4
pdf:
enable: true
# Default height
height: 500px

使用:

1
2
3
4
5
6
7
8
# Normal PDF
{% pdf http://7xov2f.com1.z0.glb.clouddn.com/bash_freshman.pdf %}

#Google drive
{% pdf https://drive.google.com/file/d/0B6qSwdwPxPRdTEliX0dhQ2JfUEU/preview %}

#Slideshare
{% pdf http://www.slideshare.net/slideshow/embed_code/key/8Jl0hUt2OKUOOE %}

自定义字体

修改/node_modules/hexo-theme-next/_config.yml:

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
font:
enable: true

# Uri of fonts host, e.g. https://fonts.googleapis.com (Default).
host: https://cdn.baomitu.com

# Font options:
# `external: true` will load this font family from `host` above.
# `family: Times New Roman`. Without any quotes.
# `size: x.x`. Use `em` as unit. Default: 1 (16px)

# Global font settings used for all elements inside <body>.
global:
external: true
family: Noto Serif SC
size:

# Font settings for site title (.site-title).
title:
external: true
family: Noto Serif SC
size:

# Font settings for headlines (<h1> to <h6>).
headings:
external: true
family: Noto Serif SC
size:

# Font settings for posts (.post-body).
posts:
external: true
family: Noto Serif SC

# Font settings for <code> and code blocks.
codes:
external: true
family: Source Code Pro

编辑主题的Blog/node_modules/hexo-theme-next/source/css/_variables/base.styl文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Font size
$font-size-base = (hexo-config('font.enable') and hexo-config('font.global.size') is a 'unit') ? unit(hexo-config('font.global.size'), em) : 1em;
$font-size-smallest = .55em;
$font-size-smaller = .6125em;
$font-size-small = .675em;
$font-size-medium = 0.8em;
$font-size-large = 0.925em;
$font-size-larger = 1.15em;
$font-size-largest = 1.7em;


// Headings font size
$font-size-headings-step = .125em;
$font-size-headings-base = (hexo-config('font.enable') and hexo-config('font.headings.size') is a 'unit') ? unit(hexo-config('font.headings.size'), em) : 1.425em;

sitemap

1
npm install hexo-generator-sitemap --save

服务器部署 7

使用Git Hook自动部署到vps上。

创建用户

服务器上,创建git用户并且赋予权限:

1
2
3
adduser git
chmod 740 /etc/sudoers
nano /etc/sudoers
1
2
3
# User privilege specification
root ALL=(ALL:ALL) ALL
git ALL=(ALL:ALL) ALL
1
chmod 440 /etc/sudoers

建立密钥

本地Mac上,查看密钥(没有的话需要创建一个):

1
ls -al ~/.ssh

创建钥匙密钥:

1
2
3
4
cd ~/.ssh 
ssh-keygen -t rsa -C "你的邮箱" // 执行这个命令会提示输入用于保存的密钥名和口令之类的,都不填

touch ~/.ssh/config
1
2
3
4
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_rsa
1
ssh-add -K ~/.ssh/id_rsa

复制公匙:

1
pbcopy < ~/.ssh/id_rsa.pub

服务器上:

1
2
3
4
cd /home/git                   //切换到git用户目录
mkdir .ssh //创建.ssh目录
cd .ssh //进入.ssh目录
nano authorized_keys //将本地的公钥复制到authorized_keys文件里
1
2
3
chmod 700 /home/git
chmod 700 /home/git/.ssh #只有拥有者有读、写、执行权限
chmod 600 /home/git/.ssh/authorized_keys #只有拥有者有读写权限
1
nano /etc/ssh/sshd_config
1
2
3
4
// 取消这些注释
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
1
sudo /etc/init.d/ssh restart

关闭git用户的shell权限,设置后git用户可以通过ssh正常使用git服务,但无法登录shell:

1
nano /etc/passwd
1
git:x:1001:1001:,,,:/home/git:/bin/bash 改成 git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

Git仓库

服务器上:

1
2
3
4
5
6
apt-get install git

cd /home/git //切换到git用户目录
mkdir blog.git //创建仓库目录,以blog.git为例
cd blog.git //进入仓库目录
git init --bare //使用--bare参数初始化为裸仓库,这样创建的仓库不包含工作区

修改/home/git/blog.git目录的用户组权限为git:git

1
2
3
sudo chown git:git -R /home/git/.ssh
sudo chown git:git -R /home/git/.ssh/authorized_keys
sudo chown git:git -R /home/git/blog.git

本地Mac上测试:

1
2
3
ssh -v git@ip

git clone ssh://git@ip:port/home/git/blog.git

Git Hooks自动部署

在本地编辑Markdown文章,然后使用Git推送到VPS的Git仓库。Git Hooks实际上就是当Git仓库收到最新的push时,将Git仓库接受到的内容复制到VPS上的网站目录内。相当于完成了手动将public文件夹复制到VPS的网站根目录里的操作。

建立网站根目录:

1
2
3
cd /home/git
mkdir blog
sudo chown git:git -R /home/git/blog

创建post-receive文件:

1
2
cd /home/git/blog.git/hooks     //切换到hooks目录下
nano post-receive //创建post-receive文件并编辑
1
2
3
4
5
6
7
8
#!/bin/bash
GIT_REPO=/home/git/blog.git
TMP_GIT_CLONE=/tmp/blog
PUBLIC_WWW=/home/git/blog
rm -rf ${TMP_GIT_CLONE}
git clone $GIT_REPO $TMP_GIT_CLONE
rm -rf ${PUBLIC_WWW}/*
cp -rf ${TMP_GIT_CLONE}/* ${PUBLIC_WWW}
1
chmod +x post-receive

部署Nginx

服务器上:

1
2
3
sudo apt-get install nginx

sudo vim /etc/nginx/conf.d/blog.conf

写入:

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
server {
listen 80;
server_name example.com; # 自己的域名

root /home/git/blog; # 刚才说的路径
access_log /var/log/nginx/blog_access.log;
error_log /var/log/nginx/blog_error.log;

# 这里是针对静态资源文件做个缓存
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires 1d;
add_header Pragma public;
add_header Cache-Control "public";
}

# 如果使用了hexo-pdf插件,并且将文件放到服务器上,则还需添加
location ~* \.(pdf)$ {
add_header "Access-Control-Allow-Origin" "http://nagland.github.io";
expires 1d;
}

# 这里就是把请求转给我们的静态文件了
location / {
root /home/git/blog;
if (-f $request_filename) {
rewrite ^/(.*)$ /$1 break;
}
}
}

由于nginx的运行用户没有权限访问网站所在的目录,检查:

1
/etc/nginx/nginx.conf

可以将user的值改为git

重启:

1
service nginx restart

Hexo远程部署

本地Blog文件夹下:

1
npm install hexo-deployer-git --save

站点配置文件文件_config.yml中修改:

1
2
3
4
deploy:
type: git
repo: git@ip:blog.git
branch: master
1
git clone ssh://git@ip:port/home/git/blog.git
1
2
3
hexo clean
hexo generate
hexo deploy