部署 Waline 评论系统到自己的服务器完全指南 (保姆级教程 2026)
转载自 我的个人博客
部署 Waline 评论系统到自己的服务器完全指南 (保姆级教程 2026)
简介
Waline 是一个自托管的静态博客评论系统。基于 Node.js,内置管理后台,数据存 SQLite —— 意味着不需要单独装数据库,一个 Docker 容器就跑了。前端是 Web Component(Vue),原生支持暗黑模式、浏览量统计、表情包、Markdown 渲染、数学公式。
这篇教程假设你有一台服务器和一个域名,带你从零把 Waline 跑起来,每一步都有解释。
为什么选 Waline 而不是 Twikoo
| 对比 | Waline | Twikoo |
|---|---|---|
| 数据库 | SQLite(无需额外容器) | MongoDB(必须) |
| 管理后台 | 内置/ui,注册即用 | 访问/#/login设置密码 |
| 垃圾过滤 | Akismet + IP 频率 + 关键词 + 相似度检测 | 仅 IP 频率限制 |
| 浏览量统计 | 内置,一行配置 | 不支持 |
| 前端框架 | Web Component(Vue) | 传统 JS |
| 暗黑模式 | dark: 'auto'自适应 | 需手动适配 |
| 登录方式 | 注册 + GitHub OAuth | 仅密码 |
| 镜像体积 | ~150MB(含 SQLite) | 需额外 MongoDB 镜像 |
结论:新项目直接用 Waline,更轻量、功能更全、部署更简单。
第一步:准备工作
你需要这些
| 东西 | 说明 |
|---|---|
| 一台服务器 | 1c1g 足够。能 SSH 上去、能装 Docker |
| 一个域名 | 前端 HTTPS 页面无法请求 HTTP 后端,所以必须有域名配 SSL |
| 一个子域名 | 给 Waline 专用,比如comment.你的域名.com |
| 15 分钟 | 从零到评论可用 |
没有域名怎么办
如果你还没有域名,先去任意域名注册商买一个(Namesilo / Cloudflare / 阿里云 都行)。最便宜的.xyz一年几块钱。
买完后,在你的 DNS 管理页面添加一条 A 记录,把子域名指向服务器 IP:
类型: A 主机记录: comment (表示 comment.你的域名.com) 记录值: 123.456.789.0 (你的服务器公网 IP) TTL: 600DNS 生效可能需要几分钟。验证一下:
nslookupcomment.example.com第二步:安装 Docker
如果你的服务器还没装 Docker,先装上。
# 官方一键安装脚本curl-fsSLhttps://get.docker.com|sudosh# 把当前用户加入 docker 组,以后不用每次加 sudosudousermod-aGdocker$USER# 退出 SSH 重新登录,让用户组生效exit重新登录后验证:
docker--versiondockerrun--rmhello-world如果
docker pull特别慢或被墙,参考文末「常见问题」配镜像加速。
第三步:生成配置值
部署 Waline 前,先把要填的值准备好。以下 5 个值需要你替换成自己的:
3.1 JWT_TOKEN —— 管理员密钥
这是 Waline 内部用来签发登录凭证的密钥,必须设,必须保密。
openssl rand-hex32输出类似a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6e1f2a3b4c5d6。把这个字符串记下来,后面要用。
不要用你别的密码,用
openssl rand生成的随机值。
3.2 SITE_NAME —— 网站名称
随便写,会显示在管理后台和邮件通知里。比如「XX 的博客」。
3.3 SITE_URL —— 博客地址
你的博客完整地址,带上https://。
3.4 SECURE_DOMAINS —— 安全域名
你的域名,不带https://。Waline 评论框允许嵌入的域名白名单。多个域名用逗号分隔。
3.5 AUTHOR_EMAIL —— 你的邮箱
收到新评论时会往这个邮箱发通知(需要配 SMTP,见后面)。
填完后的参考
| 变量 | 值 |
|---|---|
JWT_TOKEN | a1b2c3d4...(openssl rand 那串) |
SITE_NAME | 我的博客 |
SITE_URL | https://blog.example.com |
SECURE_DOMAINS | blog.example.com |
AUTHOR_EMAIL | user@example.com |
第四步:部署 Waline 后端
终于要开始部署了。以下操作全部在服务器上执行。
4.1 拉取镜像
dockerpull lizheming/waline:latest镜像大约 150MB,半分钟到一分钟能拉完。
4.2 创建数据目录
mkdir-p/opt/waline/data4.3 启动容器
把 3.1~3.5 准备好的值填进去,执行:
dockerrun-d\--namewaline\--restart=unless-stopped\-p127.0.0.1:8360:8360\-v/opt/waline/data:/app/data\-eTZ=Asia/Shanghai\-eSQLITE_PATH=/app/data\-eJWT_TOKEN=a1b2c3d4...\-e"SITE_NAME=我的博客"\-eSITE_URL=https://blog.example.com\-eSECURE_DOMAINS=blog.example.com\-eAUTHOR_EMAIL=user@example.com\lizheming/waline:latest每个参数的含义:
| 参数 | 作用 |
|---|---|
-d | 后台运行 |
--restart=unless-stopped | 服务器重启后自动启动容器 |
-p 127.0.0.1:8360:8360 | 只监听本机 8360 端口(不暴露公网,安全) |
-v /opt/waline/data:/app/data | 数据持久化 |
-e JWT_TOKEN=... | 管理员登录密钥 |
-e SITE_NAME/URL/DOMAINS | 站点信息 |
-e AUTHOR_EMAIL | 博主邮箱 |
关键提示:bash 续行符
\必须是该行最后一个字符,后面不能跟任何东西(包括空格和注释)。如果SITE_NAME含&等特殊字符,要用双引号包住整个-e "SITE_NAME=xxx"。
4.4 验证容器状态
dockerps|grepwaline看到Up字样说明容器在运行。也可以看日志:
dockerlogs waline--tail20正常的话最后一行类似ThinkJS 3.x is running at http://127.0.0.1:8360。
4.5 使用 Docker Compose(可选但推荐)
新建docker-compose.yml:
mkdir-p/opt/waline&&cd/opt/waline# docker-compose.ymlversion:'3'services:waline:container_name:walineimage:lizheming/waline:latestrestart:alwaysports:-127.0.0.1:8360:8360volumes:-./data:/app/dataenvironment:TZ:Asia/ShanghaiSQLITE_PATH:/app/dataJWT_TOKEN:a1b2c3d4...# ← 替换SITE_NAME:"我的博客"# ← 替换SITE_URL:https://blog.example.com# ← 替换SECURE_DOMAINS:blog.example.com# ← 替换AUTHOR_EMAIL:user@example.com# ← 替换IPQPS:5AKISMET_KEY:"false"启动:
dockerstop waline&&dockerrmwalinedocker-composeup-d第五步:Nginx 反代 + HTTPS
Waline 只监听了127.0.0.1:8360,外部访问不到。需要用 Nginx 反代到公网,并配上 HTTPS。
5.1 安装 Nginx 和 Certbot
sudoaptupdatesudoaptinstall-ynginx certbot python3-certbot-nginx5.2 创建临时 HTTP 站点
sudotee/etc/nginx/sites-available/waline<<'EOF' server { listen 80; server_name comment.example.com; # ← 替换:你的子域名 location / { proxy_pass http://127.0.0.1:8360; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header REMOTE-HOST $remote_addr; } } EOFsudoln-sf/etc/nginx/sites-available/waline /etc/nginx/sites-enabled/sudonginx-t&&sudosystemctl reload nginx5.3 Certbot 自动获取 SSL 证书
sudocertbot--nginx-dcomment.example.comCertbot 会自动申请证书、改 Nginx 配置、加 HTTP→HTTPS 跳转。证书 90 天有效,到期前自动续期。
5.4 验证
curlhttps://comment.example.com应该返回一段 JSON:
{"name":"Waline","version":"x.x.x",...}第六步:注册管理员
这一步必须立刻做,免得被别人抢注。
浏览器打开:
https://comment.example.com/ui/register输入邮箱和密码,点击注册。第一个注册的用户自动成为管理员。
注册后登录管理后台:
https://comment.example.com/ui第七步:前端接入
在你想显示评论框的位置加入以下代码:
<divid="waline"></div><scripttype="module">import{init}from'https://unpkg.com/@waline/client@v3/dist/waline.mjs';init({el:'#waline',serverURL:'https://comment.example.com',// ← 替换dark:'auto',lang:'zh-CN',wordLimit:500,pageview:true,emoji:['https://unpkg.com/@waline/emojis@1.2.0/qq','https://unpkg.com/@waline/emojis@1.2.0/tieba',],});</script>浏览量统计
阅读量:<spanclass="waline-pageview-count"data-path="/posts/hello-world"></span>次Waline 自动查找页面上所有.waline-pageview-count元素并填入计数。
常见博客框架接入
| 框架 | 在哪加代码 |
|---|---|
| Hugo | layouts/_default/single.html |
| Hexo | 主题的layout/_partial/comments.ejs |
| Jekyll | _layouts/post.html |
| VuePress | .vuepress/config.js |
| 纯 HTML | 每篇文章底部直接贴 |
第八步:邮件通知(可选但建议配)
不配邮件的话,有人评论你不知道。QQ 邮箱为例:
- QQ 邮箱 → 设置 → 账户 → POP3/IMAP/SMTP 服务 → 开启 SMTP → 获取授权码
- 添加环境变量:
-eSMTP_SERVICE=QQ\-eSMTP_USER=你的QQ号@qq.com\-eSMTP_PASS=授权码\-eSENDER_NAME=Waline通知\重启容器生效:
dockerrestart waline日常维护
# 升级dockercompose pull&&dockercompose up-d# Compose 方式dockerpull lizheming/waline:latest&&dockerstop waline&&dockerrmwaline# run 方式# 备份(SQLite 就是一个文件)cp-r/opt/waline/data /opt/backup/waline-$(date+%F)# 查看日志dockerlogs waline--tail50实战踩坑记录
- bash 续行符
\后不能跟注释—\必须是行末最后一个字符 - SITE_NAME 含
&必须加引号—-e "SITE_NAME=Code & Flower",否则&被 bash 解析为后台运行符 - SECURE_DOMAINS 必须包含管理后台域名— 只写博客域名的话,管理后台 API 返回 403
- SQLite 文件需要预初始化— 空文件不会自动建表,需要下载官方种子数据库
- 社交登录在国内可能 403— 用的代理服务不稳定,用邮箱注册就好
常见问题
评论一直转圈→ 99% 是serverURL填错了或 HTTPS 证书有问题。浏览器 F12 → Console 看报错。
管理后台打不开→ URL 路径是/ui,不是/ui/。首次访问应该去/ui/register注册。
Docker pull 太慢→ 配镜像加速:
sudotee/etc/docker/daemon.json<<-'EOF' { "registry-mirrors": [ "https://docker.xuanyuan.me", "https://docker.1ms.run", "https://docker.m.daocloud.io" ] } EOFsudosystemctl daemon-reload&&sudosystemctl restartdockerWaline 是我用过最省心的自建评论系统——一个容器、一个 SQLite 文件、几行配置就全搞定了。有问题欢迎在评论区交流,博客地址见主页。
