前言

waline是由lizheming开发的博客评论系统,从Valine衍生的带后端评论系统。可以将Waline等价成With backend Valine

Waline的服务端可以部署在VercelCloudBase或者服务器上,数据库可以使用LeanCloud、MySQL等,总计有多达48钟部署方式。在官方教程中,使用云服务部署都介绍的比较详细,下面介绍两种本地部署方式,可以自定义端口,配合多种数据库使用。

直接部署

直接部署方便对配置进行修改,不需要更新镜像,安装好模块后使用Node.js运行模块内的vanilla.js文件即可。

  1. 安装waline
1
2
mkdir walinejs && cd walinejs
cnpm install @waline/vercel --save
  1. 创建软链接,方便后续操作
1
2
ln -s node_modules/@waline/vercel ./waline
cd waline
  1. 创建config.js文件,在里面可以添加自定义 Hook,方便用户根据自身业务需求对 Waline 服务端行为进行定制,可以参考评论 Hooks,以下为示例:
config.js
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
forbiddenNicks = [
"forbidden"
]
forbiddenMails = [
"forbidden@example.com"
]

module.exports = {
// 禁止昵称或邮箱
async preSave(comment) {
const nick = comment.nick;
const mail = comment.mail;

const regNick = new RegExp('(' + forbiddenNicks.join('|') + ')', 'ig');
const regMail = new RegExp('(' + forbiddenMails.join('|') + ')', 'ig');

if (regNick.test(nick) || regMail.test(mail)) {
think.logger.debug(`Comment nick or mail check result: spam`);
return "403";
}
},
// 自动获取QQ邮箱,优先级高于 Gravatar
async avatarUrl(comment) {
const mail = comment.mail;
const regQQ = new RegExp('(\\d+)@qq\\.com$', 'i');
if (regQQ.test(mail)) {
const q = mail.replace(/@qq\.com/i, '').toLowerCase();
return 'https://q1.qlogo.cn/headimg_dl?dst_uin=' + q + '&spec=4';
}
},
};
  1. 创建ecosystem.config.js文件,内容如下:

如果你想使用配置中的邮件模板,请注意修改各种链接与标题等

ecosystem.config.js
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
module.exports = {
apps : [{
name: 'Waline',
cwd: './',
script: './vanilla.js',

watch: false,
error_file: "./logs/error.log",
out_file: "./logs/out.log",
log_date_format: "Z",
merge_logs: true,

env: {
port: 8360,
NODE_ENV: 'production',

IPQPS: 180,
secureDomains: [
'foolishfox.cn',
'waline.foolishfox.cn'
],
forbiddenWords: [
'空包',
'快递'
],
disallowIPList: [
'171.110.238.38'
],

SITE_NAME: 'Fox Home',
SITE_URL: 'https://foolishfox.cn',
AUTHOR_EMAIL: 'fox@foolishfox.cn',

AVATAR_PROXY: false,
GRAVATAR_STR: 'https://cravatar.cn/avatar/{{mail|md5}}',

MYSQL_HOST: 'localhost',
MYSQL_DB: 'db',
MYSQL_USER: 'user',
MYSQL_PASSWORD: 'password',

SMTP_USER: 'fox@foolishfox.cn',
SMTP_PASS: 'password',

mailSubject: '叮咚!『Fox Home』上有人@了你',
mailTemplate: `<div>
<style>
.box{background-color:white;border-bottom:2px solid #EB6844;border-radius:10px;box-shadow:rgba(0, 0, 0, 0.08) 0 0 18px;line-height:180%;width:500px;margin:50px auto;color:#555555;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;font-size:12px;}
.box .head{border-bottom:1px solid whitesmoke;font-size:14px;font-weight:normal;padding-bottom:15px;margin-bottom:15px;text-align: center;line-height: 28px;}
.box .head h3{margin-bottom: 0;margin: 0;}
.box .head .title{color: #EB6844;font-weight:bold;}
.box .body{padding:0 15px}
.box .body .content{background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;}
a{text-decoration:none; color:#EB6844}
img{max-width: 100%;display:block;margin:0 auto;border-radius: inherit;border-bottom-left-radius:unset;border-bottom-right-radius:unset;}
.button:hover{background:#EB6844;color:#ffffff}
.button{display: block;margin: 0 auto;width: 15%;line-height: 35px;padding: 0 15px;border:1px solid currentColor;border-radius: 50px;text-align: center;font-weight: bold;}
.vemoji{display: inline-block;vertical-align: middle;width: 1.25em;margin: 0.25em;}
</style>
<div class="box">
<img src="https://asset.foolishfox.cn/images/static/fox_paint.jpg">
<div class="head">
<h3> {{parent.nick}} ,</h3>有人回复了你在 <a href="https://foolishfox.cn" target="_blank"> Fox Home </a>上的评论!
</div>
&nbsp;&nbsp;&nbsp;&nbsp;你评论的:
<div class="body">
<div class="content">{{parent.comment | safe}}</div>
<p>被 <strong> {{self.nick}} </strong>回复:</p>
<div class="content">{{self.comment | safe}}</div>
<p style="margin:20px auto">
<a class="button" href="https://foolishfox.cn{{self.url}}" target="_blank"> 点击查看 </a>
</p>
<center>欢迎再来 <a href="https://foolishfox.cn" target="_blank">Fox Home</a> ! </center>
<p>
</p>
</div>
</div>
</div>`,

MAIL_SUBJECT_ADMIN: '叮咚!『Fox Home』上有新评论啦~',
MAIL_TEMPLATE_ADMIN: `<div>
<style>
.box{background-color:white;border-bottom:2px solid #EB6844;border-radius:10px;box-shadow:rgba(0, 0, 0, 0.08) 0 0 18px;line-height:180%;width:500px;margin:50px auto;color:#555555;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;font-size:12px;}
.box .head{border-bottom:1px solid whitesmoke;font-size:14px;font-weight:normal;padding-bottom:15px;margin-bottom:15px;text-align: center;line-height: 28px;}
.box .head h3{margin-bottom: 0;margin: 0;}
.box .head .title{color: #EB6844;font-weight:bold;}
.box .body{padding:0 15px}
.box .body .content{background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;}
a{text-decoration:none; color:#EB6844}
img{max-width: 100%;display:block;margin:0 auto;border-radius: inherit;border-bottom-left-radius:unset;border-bottom-right-radius:unset;}
.button:hover{background:#EB6844;color:#ffffff}
.button{display: block;margin: 0 auto;width: 15%;line-height: 35px;padding: 0 15px;border:1px solid currentColor;border-radius: 50px;text-align: center;font-weight: bold;}
.vemoji{display: inline-block;vertical-align: middle;width: 1.25em;margin: 0.25em;}
</style>
<div class="box">
<img src="https://asset.foolishfox.cn/static/fox_paint.jpg">
<div class="head">
<h3> {{self.nick}} ,</h3>在 <a href="https://foolishfox.cn" target="_blank"> Fox Home </a>上评论了!
</div>
<div class="body">
<div class="content">{{self.comment | safe}}</div>
<p style="margin:20px auto">
<a class="button" href="https://foolishfox.cn{{self.url}}" target="_blank"> 点击查看 </a>
</p>
</div>
</div>
</div>`
},
}],

deploy : {
production : {
user : 'SSH_USERNAME',
host : 'SSH_HOSTMACHINE',
ref : 'origin/master',
repo : 'GIT_REPOSITORY',
path : 'DESTINATION_PATH',
'pre-deploy-local': '',
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
'pre-setup': ''
}
}
};
  1. 使用pm2运行程序
1
2
cnpm install -g pm2
pm2 start ecosystem.config.js
  1. 设置反向目录代理,将waline.foolishfox.cn指向127.0.0.1:8360

Docker

关于Docker的相关信息已经过时

docker配置

在Docker容器内运行vanilla.js文件。

  1. 修改Node.js淘宝源
1
2
3
4
5
6
# 单次使用
npm install module_name --registry=https://registry.npm.taobao.org
# 永久修改
npm config set registry https://registry.npm.taobao.org
# 使用cnpm,安装了cnpm之后,npm install 都可以换成cnpm install
npm install -g cnpm --registry=https://registry.npm.taobao.org
  1. 构建镜像
1
2
3
git clone https://github.com/lizheming/waline.git
cd waline
docker build -t image_name -f packages/server/Dockerfile .
  1. 修改配置packages/client/.env,参考文档中所需环境变量配置即可
.env
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SKIP_PREFLIGHT_CHECK=true

# 数据库配置,参考https://waline.js.org/server/databases.html
MYSQL_HOST=127.0.0.1
MYSQL_DB=db_name
MYSQL_USER=db_user
MYSQL_PASSWORD=password

AKISMET_KEY=guess

SITE_NAME=Fox Home
SITE_URL=https://foolishfox.cn
AUTHOR_EMAIL=fox@foolishfox.cn

SC_KEY=SCK232027Td54bfab83cfabf0aereq2c31b6552cd35fe1a43720074

SMTP_HOST=smtp.ym.163.com
SMTP_PORT=465
SMTP_USER=fox@foolishfox.cn
SMTP_PASS=password
SENDER_NAME=fox
SENDER_EMAIL=fox@foolishfox.cn
  1. 运行镜像
1
docker run --env-file ./packages/client/.env -p 8360:8360 -d image_name
  1. 设置反向目录代理,将waline.foolishfox.cn指向127.0.0.1:8360
  2. 进入容器
1
2
3
4
5
6
# 查看容器id
root@iZ2ze8k2vy63cz277rsw8zZ:$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cebd15a83483 lizheming/waline "docker-entrypoint.s…" 44 seconds ago Up 42 seconds 0.0.0.0:8360->8360/tcp admiring_noether
# 进入容器
root@iZ2ze8k2vy63cz277rsw8zZ:$ docker exec -it cebd15a83483 /bin/bash
  1. 安装vim(可跳过)与验证组件
1
2
3
apt update
apt install vim
apt install apt-transport-https ca-certificates
  1. 更新软件源(使用清华源
1
2
3
4
5
6
7
8
9
# 备份
mv /etc/apt/sources.list /etc/apt/sources.list.bak
# vim修改
vim /etc/apt/sources.list
# echo修改
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free" >/etc/apt/sources.list
# 更新
apt update
...
1
2
3
4
5
6
7
8
9
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
  1. 配置config.js,路径为:node_modules/@waline/vercel/config.js,参考服务端配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
secureDomains: [
'foolishfox.cn',
'waline.foolishfox.cn',
'localhost',
'127.0.0.1'
],
forbiddenWords: [
'空包',
'快递',
'下单'
],
disallowIPList: [
'8.8.8.8'
]
};
  1. 修改主程序vanilla.js,导入自定义配置(已提交PR进行修复,无需再进行更改)
1
2
3
4
5
6
7
8
const path = require('path');
const Application = require('thinkjs');
...
let config = {}
try {
config = require('./config.js');
} catch(e) {}
...

前端配置

参考文档,需要注意的有:

  1. 本地(localhost)访问不增加计数(以hexo为例)
1
2
3
4
5
6
new Waline({
el: '#waline',
path: location.pathname,
serverURL: 'https://your-serverURL.domain.com',
visitor: location.hostname!=='localhost' && !{ theme.waline.visitor }
});

参考资料

  1. waline
  2. 博客服务器迁移过程
  3. pm2入门