惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
H
Help Net Security
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
Jina AI
Jina AI
L
LangChain Blog
K
Kaspersky official blog
I
Intezer
Martin Fowler
Martin Fowler
爱范儿
爱范儿
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
Recorded Future
Recorded Future
人人都是产品经理
人人都是产品经理
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
CXSECURITY Database RSS Feed - CXSecurity.com
Spread Privacy
Spread Privacy
Simon Willison's Weblog
Simon Willison's Weblog
U
Unit 42
N
News and Events Feed by Topic
A
Arctic Wolf
G
GRAHAM CLULEY
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
F
Fortinet All Blogs
C
Cisco Blogs
美团技术团队
Vercel News
Vercel News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Hacker News: Front Page
T
Tailwind CSS Blog
I
InfoQ
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
P
Palo Alto Networks Blog
A
About on SuperTechFans
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
云风的 BLOG
云风的 BLOG
TaoSecurity Blog
TaoSecurity Blog
Google Online Security Blog
Google Online Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy & Cybersecurity Law Blog
H
Heimdal Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
O
OpenAI News
博客园 - Franky
Scott Helme
Scott Helme

Hyde Blog

Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog 关于我 关于我 Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog
Hyde Blog
Hyde · 2025-10-19 · via Hyde Blog

Twikoo评论 ​

部署方式 ​

官网:https://twikoo.js.org

Twikoo 支持多种部署方式:云函数,Vercel,私有部署、Docker.... 具体参见文档:https://twikoo.js.org/backend.html

‍ 最原始的方法,也就是直接在服务器上部署,步骤很简单:安装 node → 安装 tkserver → 启动。

sh

$ npm i -g tkserver

$ ln -s /opt/nodejs/node/bin/tkserver /usr/local/bin/tkserver

$ tkserver

然后就可以访问了,地址是:http://服务端IP:8080

Linux 服务器可以用 nohup tkserver >> tkserver.log 2>&1 & 命令后台启动。

提示

可能需要在云服务器上开启 8080 端口的防火墙

还是推荐用 Docker 来部署。我之前是用私有部署,几年后想升级 Twikoo,但是因为 node 版本太老了,导致升级失败... 然后试着升级 node,又是一堆报错...

Docker 部署 ​

sh

docker run --name twikoo -e TWIKOO_THROTTLE=1000 -p 8080:8080 -v ${PWD}/data:/app/data -d imaegoo/twikoo

docker-compose.yaml 内容:

yaml

version: "3"
services:
  twikoo:
    image: imaegoo/twikoo
    container_name: twikoo
    restart: unless-stopped
    ports:
      - 8080:8080
    environment:
      TWIKOO_THROTTLE: 1000
    volumes:
      - ./data:/app/data

自己实际部署:😜

  • 创建并启动一个名为 twikoo 的 Docker 容器

sh

docker run --name twikoo -e TWIKOO_THROTTLE=1000 -p 8426:8080 -v ${PWD}/data:/app/data -d imaegoo/twikoo

并在其中生成了一个 docker-compose.yaml 文件

sh

# 创建名为 `twikoo` 的目录
mkdir /root/twikoo
# 创建docker-compose.yaml 文件并添加以下内容
cat >>/root/twikoo/docker-compose.yaml <<EOF
version: '3'
services:
  twikoo:
    image: imaegoo/twikoo
    container_name: twikoo
    restart: unless-stopped
    ports:
      - 8426:8080
    environment:
      TWIKOO_THROTTLE: 1000
    volumes:
      - ./data:/app/data
EOF

# 进入该目录
cd /root/twikoo
# 检查 8080 端口是否已经被其他进程占用
netstat -antlp|grep 8080
# 启动twikoo镜像服务
docker-compose  up -d
[+] Building 0.0s (0/0)                                                                                                  docker:default
[+] Running 2/2
 Network twikoo_default  Created                                                                                                 0.0s
 Container twikoo        Started                                                                                                 0.0s
 [root@VM-4-16-centos twikoo]# docker ps -l
CONTAINER ID   IMAGE            COMMAND                   CREATED          STATUS          PORTS                                       NAMES
dc43659872fe   imaegoo/twikoo   "docker-entrypoint.s…"   56 minutes ago   Up 56 minutes   0.0.0.0:8426->8080/tcp, :::8426->8080/tcp   twikoo
[root@VM-4-16-centos twikoo]#

在私有部署的情况下,在你执行 tkserver 的时候,就会在当前目录创建:

  • data 文件夹:存放评论数据、配置等
  • tkserver.log:日志文件

因此,有必要在你自己指定的目录下启动 tkserver,方便后期的数据备份、日志分析等。

如果你使用的是 Docker,在上述命令里其实也用了 ${PWD}/data 来指定数据文件的目录,请自行选择。

sh

[root@VM-4-16-centos twikoo]# ls
data  docker-compose.yaml
[root@VM-4-16-centos twikoo]# ls data/
db.json  db.json.0  db.json.1  db.json.2
[root@VM-4-16-centos twikoo]#

HTTPS配置 ​

理论上这样部署,就完成后台的部分了,但鉴于我的网站用了 HTTPS,而 Twikoo 本身并不支持,因此还需要做反向代理

我这里配置 HTTPS 是用到cloudflare

  • 进入cloudflare,在【账户主页】找到您的域名点击进去(如果没有请添加域名),进去后找到 DNS 记录,添加二级域名
    • 类型:A
    • 名称:twikoo(自定义就行)
    • IPv4:填写服务器的 IP

image-20250215181017931.png

Nginx配置 ​

nginx

upstream twi {
   server peterjxl.com:8080; #你的域名+加端口
}

server {
    listen  443 ssl;
    server_name  twikoo.peterjxl.com; #子域名
    ssl_certificate  /opt/nginxrun/conf/cert/8852603_twikoo.peterjxl.com.pem;
    ssl_certificate_key /opt/nginxrun/conf/cert/8852603_twikoo.peterjxl.com.key;

    # ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers  HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM;
    ssl_prefer_server_ciphers  on;

    location / {
	proxy_pass http://twi;
    }
}
  • 自己实际配置

nginx

# 进入该目录
cd /etc/nginx/conf.d/
# 创建文件
vim twikoo.seasir.top.conf

[root@VM-4-16-centos conf.d]#  cat twikoo.seasir.top.conf
server {
    listen 80;
    server_name  twikoo.seasir.top;
    #配置https重定向
    return 301 https://$host$request_uri;
}

server {
    listen  443 ssl;
    server_name  twikoo.seasir.top;

    location / {
        proxy_pass http://云服务器ip:8080/; # 实际的后台路径
        client_max_body_size 100M;
        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;
    }

    access_log /var/log/nginx/photo.onedayxyy.cn.https.log;
}

# 用于测试 Nginx 配置文件的语法是否正确
nginx -t
  • 配置完成后需要重启 NGINX 服务

image-20250215182647730.png

前端配置 ​

  • 编辑 docs\.vitepress\config.ts文件或者前往查看博主Config配置,修改为如下代码:

ts

  comment: {
    // provider: "giscus",
    provider: "twikoo",
    options: {
      // twikoo 配置,官网:https://twikoo.js.org/
      envId: "填写您自己的twikoo域名",
      jsUrl: "https://cdn.staticfile.org/twikoo/1.6.42/twikoo.all.min.js",
    },
  },

运行验证 ​

Vercel 部署 ​

Twikoo 评论,需要部署前后端,包括数据库,操作略有复杂,但是不限制代码托管和服务托管,自定义程度更高。官方文档 https://twikoo.js.org/ ,非常详细,部署步骤如下:

建立数据库 ​

MongoDB AtLas 是 MongoDB Inc 提供的 MongoDB 数据库托管服务。免费账户可以永久使用 500 MiB 的数据库,足够存储 Twikoo 评论使用。

  • 申请 MongoDB AtLas 账号

  • 创建免费 MongoDB 数据库,区域推荐选择离 Twikoo 后端(Vercel / Netlify / AWS Lambda / VPS)地理位置较近的数据中心以获得更低的数据库连接延迟。如果不清楚自己的后端在哪个云服务器和地区,可选择 AWS / Oregon (us-west-2)和香港地区,该数据中心基建成熟,故障率低,且使用 Oregon 州的清洁能源,较为环保

  • Database Access 页面点击 Add New Database User 创建数据库用户,Authentication MethodPassword,在 Password Authentication 下设置数据库用户名和密码,建议点击 Auto Generate 自动生成一个不含特殊符号的强壮密码并妥善保存。点击 Database User Privileges 下方的 Add Built In RoleSelect Role 选择 Atlas Admin,最后点击 Add User

1756629719786.png

  • Network Access 页面点击 Add IP Address 添加网络白名单。因为 Vercel / Netlify / Lambda 的出口地址不固定,因此 Access List Entry 输入 0.0.0.0/0(允许所有 IP 地址的连接)即可。如果 Twikoo 部署在自己的服务器上,这里可以填入固定 IP 地址。点击 Confirm 保存

1756630088470.png

  • Overview 页面点击 Connect,连接方式选择 Drivers,并记录数据库连接字符串,请将连接字符串中的 <username>:<password> 修改为刚刚创建的数据库 用户名:密码,复制Mongodb连接字符串并妥善保管,后面部署需要用到!然后点击 Done

示例

mongodb+srv://数据库用户名:数据库密码@cluster0.d1vvzs3.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0

1756630344870.png

  • (可选)默认的连接字符串没有指定数据库名称,Twikoo 会连接到默认的名为 test 的数据库。如果需要在同一个 MongoDB 里运行其他业务或供多个 Twikoo 实例使用,建立加入数据库名称并配置对应的 ACL。 连接字符串包含了连接到 MongoDB 数据库的所有信息,一旦泄露会导致评论被任何人添加、修改、删除,并有可能获取你的 SMTP、图床 token 等信息。请妥善记录这一字符串,之后需要填入到 Twikoo 的部署平台里。

Vercel 部署 ​

  • 申请 Vercel 账号,点击以下按钮将 Twikoo 一键部署到 Vercel Deploy

Deploy

  • 进入 Settings - Environment Variables,添加环境变量 MONGODB_URI,值为前面记录的数据库连接字符串

1756631059285.png

  • 进入 Settings - Deployment Protection,设置 Vercel AuthenticationDisabled,并 Save

1756631162813.png

  • 进入 Deployments , 然后在任意一项后面点击更多(三个点) , 然后点击 Redeploy , 最后点击下面的 Redeploy 等待部署完成,部署完成即可

  • 进入 Overview,点击 Domains 下方的链接,如果环境配置正确,可以看到 “Twikoo 云函数运行正常” 的提示,说明部署成功!

1756631491236.png

域名配置 ​

  • 部署成功后,修改默认域名为你的子域名,需要去你的域名管理那上修改 DNS 解析。

1756631698889.png

前端配置 ​

  • 组件注册和teek内置二选一

路径

  • vitepress/config.ts
  • .vitepress/theme/components/Twikoo.vue
  • .vitepress/theme/components/TeekLayoutProvider.vue

(推荐)config.tsTwikoo.vuetwikoo.scssTeekLayoutProvider.vue

ts

  comment: {
    // provider: "giscus",
    provider: "twikoo",
    options: {
      // twikoo 配置,官网:https://twikoo.js.org/
      envId: "填写您自己的twikoo域名",
      //jsUrl: "https://cdn.staticfile.org/twikoo/1.6.42/twikoo.all.min.js",
      version: "1.6.44",
    },
  },

vue

代码请在源码自行获取:https://gitee.com/SeasirHyde/teek-hyde/blob/main/docs/.vitepress/theme/components/Twikoo/twikoo.scss

scss

代码请在源码自行获取:https://gitee.com/SeasirHyde/teek-hyde/blob/main/docs/.vitepress/theme/components/Twikoo/twikoo.scss

vue

<script setup lang="ts">
import Twikoo from './Twikoo.vue'
</script>

<template>
  <Teek.Layout>
    <template #teek-doc-after-appreciation-before>
      <!-- 评论组件 -->
      <Twikoo />
    </template>
  </Teek.Layout>
</template>

配置邮件 ​

  • 前后端都处理好后,界面就能正常展示了,但是我们还要处理下邮件功能。进入您的文章底部,找到评论区的设置,首次打开设置按钮后,会有设置密码框,设置一个复杂密码并记住。然后进入配置管理,选择邮件通知

  • 按照提示输入你的邮箱,邮箱授权码等即可。最后有个邮件测试,测试后,你能收到一封邮件,说明功能可用了

美化样式 ​

  • twikoo 配置面板里的插件页签,选择代码高亮主题 coy,代码复制插件 copyButton。

  • 自定义 css

.vitepress/theme/style/comment.scss

scss

.twikoo {
    .el-input-group__append,
    .el-input-group__prepend,
    .el-textarea__inner {
        border: 1px solid #dcdfe6;
        box-shadow: none;
    }
    .el-input-group__prepend {
        border-right: none;
    }
    .el-button--small {
        height: auto;
    }
    .el-textarea > .el-textarea__inner {
        min-height: 117px !important;
        border-radius: 8px;
        margin-top: 16px;
    }
    .tk-preview-container {
        border-radius: 8px;
    }
    .tk-comments-count {
        font-size: 14px;
        color: #666;
    }
    .tk-nick,
    .tk-replies .tk-nick-link {
        font-size: 15px;
        margin-right: 8px;
        color: #409eff;
    }
    .tk-tag {
        margin-right: 8px;
    }
    .tk-comments-container > .tk-comment {
        border: solid 1px #f3f4f6;
        border-radius: 1rem;
        padding: 24px;
        margin-top: 0;
        margin-bottom: 24px;
        transition: all 0.3s ease;
    }
    .tk-comments-container > .tk-comment:hover {
        box-shadow: 0 4px 12px var(--vp-c-brand-1);
    }
    .tk-replies-expand > .tk-comment {
        border-top: solid 1px #f7f7f7;
        padding-top: 24px;
    }
    .tk-content p {
        line-height: 1.6;
    }
    a:not(.tk-ruser):not(.tk-nick-link) {
        color: #3072b3;
        font-weight: 500;
        text-underline-offset: 2px;
    }
    a:not(.tk-ruser):not(.tk-nick-link):hover {
        color: #409eff;
    }
    /* 代码块 */
    div.code-toolbar {
        border-radius: 8px !important;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    }
    div.code-toolbar :not(pre) > code[class*="language-"],
    div.code-toolbar pre[class*="language-"] {
        background: #f5f5f5;
        border-radius: 8px;
    }
    div.code-toolbar pre[class*="language-"] {
        border-radius: 8px;
    }
    div.code-toolbar pre[class*="language-"]::before,
    div.code-toolbar pre[class*="language-"]::after {
        content: none;
    }
    div.code-toolbar pre[class*="language-"] > code {
        padding: 1em;
        border-left: 4px solid #409eff;
        border-radius: 8px;
    }
    div.code-toolbar > div.toolbar {
        z-index: 1;
        top: 8px;
        right: 8px;
    }
    div.code-toolbar > div.toolbar > .toolbar-item > button {
        display: none;
        padding: 0 6px;
        font-size: 12px;
        color: black;
    }
    div.code-toolbar:hover > div.toolbar > .toolbar-item > button {
        display: block;
    }
    .tk-admin-container {
        z-index: 1;
    }
}

.tk-avatar {
    background-color: #ffffff00;
}

.tk-avatar .tk-avatar-img {
    height: 41px !important;
}
.dark .twikoo {
    .tk-comments-container > .tk-comment {
        border-color: #454545;
    }
    .tk-comments-container > .tk-comment:hover {
        box-shadow: 0 4px 12px var(--vp-c-brand-1);
    }
    .tk-replies-expand > .tk-comment {
        border-color: #343434;
    }
    /* 代码块 */
    div.code-toolbar pre[class*="language-"] > code {
        filter: brightness(0.8);
    }
}
  • css 注入主题配置

docs\.vitepress\theme\styles\index.scss中添加配置

docs\.vitepress\theme\styles\index.scss

scss

@use "./comment.scss" as *; // 评论样式

参考文档 ​