mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
3637 字
11 分钟
使用 Docker 和 Caddy 快速部署 Sillytavern
2026-07-28

0 前言#

搭建完 3x-ui 后,服务器还有些内存,于是想着部署一个云酒馆玩玩。在已经有一个稳定的公网 IP 的情况下,可以很轻松地部署一个安全的私人云酒馆,于是想写篇教程分享一下我的方案。
首先,一台 VPS 依旧是必要的。你可以把云酒馆部署在一个性能较好的建站机上,再用线路机拉它。也可以干脆都部署在线路机上,效果是一样的,服务器的最低配置是1核CPU、1g内存、10g硬盘。其次,需要一个域名,可以使用免费域名,只要能托管到 Cloudflare 上均可。
安全的云酒馆方案有很多,比如 tailscale 组网,比如用 zero trust 进行更严格的登录验证。本文介绍这种方案是因为作者已经搭建好了 3x-ui,且有使用网络代理的习惯,因此对我来说这是最安全最便捷的做法。

1 前期准备#

首先,你需要把域名托管到 Cloudflare 上,在你的域名上添加一条 A 记录,指向你服务器的 IP 地址,关掉 CDN 代理 alt text 然后,你需要一个固定的公网 IP 地址,如果你已经搭建过 3x-ui, 使用那个作为你的公网 IP 即可,使用酒馆的时候挂上梯子。不知道怎么做的看我的上一篇教程3x-ui搭建教程

2 安装酒馆#

如果你没有安装 docker,需要先安装。docker 的好处有很多,环境隔离、一键部署、数据迁移等等。

curl -fsSL https://get.docker.com | sudo sh

建立一个目录,存放酒馆

mkdir /opt/sillytavern && cd /opt/sillytavern

编写配置文件

nano docker-compose.yml

把以下配置信息复制进去

services:
sillytavern:
build: ..
container_name: sillytavern
hostname: sillytavern
image: ghcr.io/sillytavern/sillytavern:latest
environment:
- NODE_ENV=production
- FORCE_COLOR=1
- SILLYTAVERN_HEARTBEATINTERVAL=30
ports:
- "127.0.0.1:8000:8000"
volumes:
- "./config:/home/node/app/config"
- "./data:/home/node/app/data"
- "./plugins:/home/node/app/plugins"
- "./extensions:/home/node/app/public/scripts/extensions/third-party"
healthcheck:
test: ["CMD", "node", "src/healthcheck.js"]
interval: 30s
timeout: 10s
start_period: 20s
retries: 3
restart: unless-stopped

ctrl + o 保存,回车,ctrl + x 退出

一键拉起容器

docker compose up -d

酒馆已经安装好了,接下来我们修改酒馆的配置文件

nano /opt/sillytavern/config/config.yaml

可以用ctrl + w 快速搜索。首先,找到whitelistMode,把它修改成以下的样子,把你的公网 IP 添加进白名单

whitelistMode: true
# When enabled, whitelist will also verify IP in headers enabled in `forwardedHeaders` section.
enableForwardedWhitelist: true
# Whitelist of allowed IP addresses
whitelist:
- ::1
- 127.0.0.1
# docker 内部网段
- 172.16.0.0/12
# 你的公网 IP
- 你的公网 IP

就在下面一点点的位置,找到basicAuthMode,添加登录用的账号密码。把user和password改成你自己的。

# Toggle basic authentication for endpoints
basicAuthMode: true
# Basic authentication credentials
basicAuthUser:
username: "user"
password: "password"

找到 hostWhitelist

# Host whitelist configuration. Recommended if you're using a listen mode
hostWhitelist:
# Enable or disable host whitelisting
enabled: true
# Scan incoming requests for potential host header spoofing
scan: true
# List of allowed hosts. Do not include localhost or IPs, these are safe.
# Use a dot to create subdomain patterns.
# Examples:
# - example.com
# - .trycloudflare.com
hosts:
- tavern.你的域名

酒馆安全部分已经配置结束了,现在,只有白名单里面的 IP,才能通过你的域名,输入正确的账号密码访问酒馆

还有一些其它的配置:

  • lazyLoadCharacters: 把懒加载改成 true,提高酒馆启动速度
  • 把backups里面的numberOfBackups改成3,即每个聊天最多只能有 3 个备份,以免服务器硬盘爆炸。我的本地酒馆不限制备份,玩半年酒馆就超过10G了,大部分都是备份文件

修改完以后,依旧是ctrl + o 保存,回车,ctrl + x 退出
重启酒馆,让配置文件生效

docker compose restart

3 安装 Caddy#

现在,我们的酒馆在访问上已经足够安全了,只有你自己的公网 ip 能访问,不对外开放。但是,如果不通过 ssl 证书加密,中间人可以窃取你的明文数据,获取你的聊天记录、api 密钥等。所以,本节讲解如何通过 Caddy 配置反向代理,Caddy 会自动为你的域名申请证书,提供安全的 https 加密。
首先我们在 VPS 上安装 Caddy,以下是官方提供的 Ubuntu/Debian 部署流程:

sudo apt update && sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt install caddy -y

如果你的服务器有 ufw 或者安全组,开始 Caddy 配置前,请放行 80 端口和一个用于访问酒馆的端口,我用的是 8001,不用 443 是因为会和 reality 协议搭建的节点端口冲突。如果你没有在这台服务器上搭建网络代理,也可以直接用 443。

打开 Caddy 配置文件

sudo nano /etc/caddy/Caddyfile

把以下内容修改后添加到文件末尾

tavern.你的域名:8001 {
# 将流量反向代理到本地 Docker 跑的酒馆端口
reverse_proxy 127.0.0.1:8000
}

重载 Caddy

sudo systemctl reload caddy

可以检查一下有没有报错,证书申请成功没有

sudo systemctl status caddy

现在,在你开启网络代理,使用 VPS 的公网 IP 的情况下,可以通过 https://tavern.你的域名:8001 访问你的云酒馆了

4 数据备份#

本节介绍了如何在服务器上配置 Rclone,把酒馆数据定时备份到 Google Drive 上。Rclone 支持非常多种云盘,比如 One Drive,Cloudflare R2 等等,选择谷歌是因为它的免费额度给的相对较大,有 15 GB,备份酒馆是足够了,如果有学生会员甚至有 5T 的额度。

4.1 申请 API 密钥#

配置 Google Drive 的远程连接,需要填入 Client ID,其实也可以直接使用公共的 Client ID,但是速度会比较慢,而且谷歌在逐步停用/限制公用共享 Client ID,所以我们可以申请一个自己的。这部分申请还挺麻烦的,你也可以直接使用公共的,先用着再说,可以跳过此节。
首先访问谷歌控制台
https://console.cloud.google.com/

顶部搜索栏搜索Google Drive API
alt text

点击启用,这里我已经启用过了,然后点管理 alt text

创建凭证 alt text

alt text

邮箱用你的谷歌邮箱就行 alt text

alt text

alt text

选桌面应用,名称随便填 alt text

把凭证下载下来,里面有Client ID 和Client Secret,点击完成 alt text

发布应用,否则会限制访问,不需要验证应用,直接用就行 alt text

4.2 配置 Rclone#

在 VPS 上安装 Rclone

sudo -v ; curl https://rclone.org/install.sh | sudo bash

输入以下指令,进入配置:

rclone config

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q>

输入n,我们新建一个远程连接

Enter name for new remote.
name>

给这个配置起一个名字,这里我输入 gdrive

24 / Google Drive
\ (drive)
25 / Google Photos
\ (google photos)
26 / HTTP
\ (http)
27 / Hadoop distributed file system
\ (hdfs)
28 / HiDrive
\ (hidrive)
29 / Huawei Drive
\ (huaweidrive)
30 / ImageKit.io
\ (imagekit)

会显示非常多支持的存储类型,我这里 24 是 Google Drive,输入 24

Option client_id.
Google Application Client Id
Setting your own is recommended.
See https://rclone.org/drive/#making-your-own-client-id for how to create your own.
If you leave this blank, it will use an internal key which is low performance.
Enter a value. Press Enter to leave empty.
client_id>

如果你已经按照 4.1 节手动创建了客户端,可以直接打开下载的 json 文件,填入自己的Client ID。否则,直接回车留空,用公共的

Option client_secret.
OAuth Client Secret.
Leave blank normally.
Enter a value. Press Enter to leave empty.
client_secret>

同样,有自己的用自己的,没有就回车留空

Option scope.
Comma separated list of scopes that rclone should use when requesting access from drive.
Choose a number from below, or type in your own value.
Press Enter to leave empty.
1 / Full access all files, excluding Application Data Folder.
\ (drive)
2 / Read-only access to file metadata and file contents.
\ (drive.readonly)
/ Access to files created by rclone only.
3 | These are visible in the drive website.
| File authorization is revoked when the user deauthorizes the app. \ (drive.file)
/ Allows read and write access to the Application Data folder.
4 | This is not visible in the drive website.
\ (drive.appfolder)
/ Allows read-only access to file metadata but
5 | does not allow any access to read or download file content.
\ (drive.metadata.readonly)
scope>

权限限制,输入 1,给它完整的读写权限

Option service_account_file.
Service Account Credentials JSON file path.
Leave blank normally.
Needed only if you want use SA instead of interactive login.
Leading ~ will be expanded in the file name as will environment variables such as ${RCLONE_CONFIG_DIR}.
Enter a value. Press Enter to leave empty.
service_account_file>

回车留空

Edit advanced config?
y) Yes
n) No (default)
y/n>

输入n

Use web browser to automatically authenticate rclone with remote?
* Say Y if the machine running rclone has a web browser you can use
* Say N if running rclone on a (remote) machine without web browser access
If not sure try Y. If Y failed, try N.
y) Yes (default)
n) No
y/n>

这里是问我们登录认证的方式,VPS 上没有浏览器窗口,我们只能输入 n,在本地电脑上认证。

Option config_token.
For this to work, you will need rclone available on a machine that has a web browser available.
For more help and alternate methods see: https://rclone.org/remote_setup/
Execute the following on the machine with the web browser (same rclone version recommended):
rclone authorize “drive” “LpJpY27wpS18ImRyaRZlIn0”
Then paste the result.
Enter a value.

这里注意!它返回了一串命令rclone authorize “drive” “LpJpY27wpS18ImRyaRZlIn0”。记下来,我们需要在本地电脑上运行它。

如果你用的是 windows,打开你的 cmd,输入以下指令先安装 Rclone:

winget install Rclone.Rcloner

关闭当前窗口,打开一个新的 cmd 窗口

cmd 默认不走系统代理,我们先为这个窗口设置临时的代理变量。10808是v2ray的代理端口,如果你用的其它代理软件,替换成你自己。或者你可以直接打开梯子的 tun 模式。

$env:HTTP_PROXY="http://127.0.0.1:10808"
$env:HTTPS_PROXY="http://127.0.0.1:10808"

输入 VPS 上之前返回的指令,每个人的token不同,记得替换成你自己的:

rclone authorize "drive" "LpJpY27wpS18ImRyaRZlIn0"

随后,会跳转到浏览器上进行认证。如果你是用自己的客户端,因为没有验证会说有风险,在高级里面无视风险继续访问即可。
认证结束后,cmd 会返回一长串东西

Paste the following into your remote machine --->
你的token
<---End paste

把中间的 token 部分粘贴回 VPS,完成认证

Configure this as a Shared Drive (Team Drive)?
y) Yes
n) No (default)

输入 n,我们用的是个人云盘

Configuration complete.
Options:
- type: drive
- scope: drive
- token: {}
- team_drive:
Keep this “gdrive” remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d>

配置结束,输入 y 保存

Name Type
==== ====
gdrive drive
e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q>

上面可以看到配置好的远程连接,输入 q,退出配置

验证一下能不能访问你的云盘。

rclone lsd gdrive:

如果没有报错,就是配置成功了。

4.3 自动备份脚本#

创建一个脚本

nano /opt/sillytavern/st_backup.sh

把以下内容粘贴进去。这个脚本是哈基米写的,做了比较多的异常判断,如果还是不行,请拷打哈基米。
可以手动修改备份数量,改成适合你的。如果备份文件实在大,云盘空间告急,可以把云盘备份数量改成1

#!/usr/bin/env bash
# ==================== 配置区域 ====================
ST_ROOT_DIR="/opt/sillytavern"
LOCAL_BACKUP_DIR="/root/backups/sillytavern"
REMOTE_PATH="gdrive:SillyTavern_Backups"
#本地备份数量
LOCAL_KEEP_COPIES=1
#云盘备份数量
CLOUD_KEEP_COPIES=5
# ==================================================
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
ARCHIVE_NAME="st_backup_${TIMESTAMP}.tar.gz"
LOCAL_FILE="${LOCAL_BACKUP_DIR}/${ARCHIVE_NAME}"
mkdir -p "${LOCAL_BACKUP_DIR}"
echo "=================================================="
echo "[$(date)] -> 准备开始备份..."
# 1. 进入酒馆目录,如果失败则直接退出
if ! cd "${ST_ROOT_DIR}"; then
echo "[$(date)] -> 致命错误: 找不到目录 ${ST_ROOT_DIR}"
exit 1
fi
# 2. 停机
echo "[$(date)] -> 暂停 SillyTavern 容器..."
docker compose stop
# 3. 打包
echo "[$(date)] -> 开始打包酒馆核心数据卷与配置..."
tar -czf "${LOCAL_FILE}" data config plugins extensions docker-compose.yml
TAR_EXIT_CODE=$?
# 4.第一时间拉起
echo "[$(date)] -> 容器重新恢复..."
docker compose start
# 5. 校验打包文件
if [ $TAR_EXIT_CODE -ge 2 ]; then
echo "[$(date)] -> 致命错误: tar 打包发生严重错误 (退出码 $TAR_EXIT_CODE)!请检查日志。"
rm -f "${LOCAL_FILE}"
exit 1
fi
# 检查文件是否存在,并且体积是否大于 10KB
if [ ! -s "${LOCAL_FILE}" ] || [ $(stat -c%s "${LOCAL_FILE}") -lt 10240 ]; then
echo "[$(date)] -> 致命错误: 备份文件不存在或体积过小!可能磁盘已满。"
echo "[$(date)] -> 为保护云端历史备份不被脏数据替换,脚本已终止。"
rm -f "${LOCAL_FILE}"
exit 1
fi
if [ $TAR_EXIT_CODE -eq 1 ]; then
echo "[$(date)] -> 提示: tar 打包过程有警告 (通常是部分非关键目录不存在或文件被修改),但不影响核心数据。"
fi
# 6. 优先清理本地备份
echo "[$(date)] -> 清理本地多余备份 (仅保留最新 ${LOCAL_KEEP_COPIES} 份)..."
cd "${LOCAL_BACKUP_DIR}"
ls -1 st_backup_*.tar.gz 2>/dev/null | sort -r | tail -n +$((LOCAL_KEEP_COPIES + 1)) | xargs -r rm -f
# 7. 上传至 Google Drive
echo "[$(date)] -> 开始上传至 Google Drive..."
if rclone copy "${LOCAL_FILE}" "${REMOTE_PATH}" --drive-chunk-size 64M --transfers=1 -v; then
echo "[$(date)] -> 上传成功!"
else
echo "[$(date)] -> 错误: rclone 上传失败,请检查网络或授权。"
exit 1
fi
# 8. 清理云盘备份
echo "[$(date)] -> 清理 Google Drive 多余备份 (仅保留最新 ${CLOUD_KEEP_COPIES} 份)..."
rclone lsf --files-only "${REMOTE_PATH}" 2>/dev/null \
| grep '^st_backup_.*\.tar\.gz$' \
| sort -r \
| tail -n +$((CLOUD_KEEP_COPIES + 1)) \
| while read -r filename; do
# 规避 grep 匹配不到数据时 filename 为空导致误删的问题
if [ -n "$filename" ]; then
echo "[$(date)] -> 正在彻底删除云端过期备份: ${filename}"
rclone deletefile "${REMOTE_PATH}/${filename}" --drive-use-trash=false
fi
done
echo "[$(date)] -> Google Drive 自动化备份全流程顺利完成!"
echo "=================================================="

给脚本添加可执行权限

sudo chmod +x /opt/sillytavern/st_backup.sh

手动测试脚本能否正常运行

/opt/sillytavern/st_backup.sh

设置定时任务,自动备份

crontab -e

如果是第一次使用,它会让你选择编辑器模式,输入 1,使用 nano 即可,填入以下表达式:

0 21 * * * /opt/sillytavern/st_backup.sh >> /var/log/st_backup.log 2>&1

这个 cron 表达式的意思是每天 UTC 时间21点,即北京时间 5 点执行一次备份脚本。如果你的备份文件很大,每天都备份,服务器流量吃不消,也可以用下面这个每周一 5 点备份一次的 cron 表达式:

0 21 * * 0 /opt/sillytavern/st_backup.sh >> /var/log/st_backup.log 2>&1

这是在你服务器时区是 UTC 的情况下,才对的上时差。你可以输入 date 查看服务器的时区。让 AI 帮你编写更个性化的 cron 表达式。

4.4 数据恢复#

如果某天,你的服务器真的炸了(概率很低,但我真炸了一次,补偿了三个月),或者需要数据迁移,可以直接使用备份文件。
如果服务器里的数据还在,直接使用 /root/backups/sillytavern/ 里的本地备份就行。如果服务器彻底没了,去云盘下载最新的备份文件,用 SSH 客户端的文件传输功能手动上传到服务器。
假设你的备份文件已经放在了 /root/backups/sillytavern/ 目录:
同样先创建一个存放酒馆文件的目录

mkdir -p /opt/sillytavern

解压备份文件到该目录

tar -xzf /root/backups/sillytavern/你的备份文件名 -C /opt/sillytavern

进入目录

cd /opt/sillytavern

如果新服务器上没有docker需要先安装,然后一键拉起容器

docker compose up -d

你的所有角色、聊天记录、世界书、API 密钥设置、密码、甚至是安装过的第三方插件等等都会恢复。但是 Caddy 的配置文件不在备份范围内,需要再做一次第 3 节

5 读取日志#

这一节的实际意义不大。我们是通过 docker compose 部署酒馆的,在 VPS 上,输入

docker compose logs -f --tail 20

即可实时查看日志。
但是,我之前一直是在本地部署酒馆的,打开 termux 或者其它的命令行终端,就可以查看酒馆日志,查看报错信息,很方便。换成 VPS 后,有点不习惯,于是就找了一个通过 web 页面查看 docker 日志的轻量化项目,以下是效果预览: alt text 个人认为部署完以后,还是比去 VPS 敲命令看日志要方便的,还能看到内存占用什么的。当然,如果你没有看日志的习惯,或者觉得折腾这些没必要,可以无视此节。
大致流程依旧是通过 docker compose 部署,使用 caddy 反向代理。

依次执行以下命令,新建目录,存放配置文件

mkdir -p /opt/dozzle
cd /opt/dozzle
nano docker-compose.yml

把以下的配置信息粘贴进去

services:
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
restart: unless-stopped
environment:
- DOZZLE_AUTH_PROVIDER=simple
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./users.yml:/data/users.yml
- dozzle-data:/data
ports:
- "127.0.0.1:8088:8080"
volumes:
dozzle-data:

crtl + o 保存,回车,ctrl + x 退出

生成一个密码,作为你的登录密码。否则,外人如果知道你的网页,可以看到你的酒馆以及其它容器的日志。

docker run --rm amir20/dozzle generate 你的名字 --password "你的密码" > users.yml

拉起容器

docker compose up -d

我们接下来需要绑上域名
依旧先添加 A 记录
alt text

打开 Caddy 配置文件

nano /etc/caddy/Caddyfile

把以下内容添加到尾部

dozzle.你的域名:8001 {
reverse_proxy 127.0.0.1:8088 {
flush_interval -1
}
}

现在,在浏览器输入 https://dozzle.你的域名 就可以实时查看你的酒馆日志了。
alt text 输入设置好的账号密码
另外,如果你希望和酒馆一样,只允许你自己的公网 ip 访问,可以在 caddy 的配置文件里添加白名单,改成:

dozzle.你的域名:8001 {
# 1. 定义白名单规则:如果来访 IP 【不是】下面这些,就被标记为 @blocked
@blocked {
# 把下面的 IP 替换成你的公网 IP,可以写多个,用空格隔开
not remote_ip 192.168.1.100 114.114.114.114
}
# 2. 针对被标记为 @blocked 的访客,直接返回 403 报错
respond @blocked "Access Denied (IP not allowed)" 403
reverse_proxy 127.0.0.1:8088 {
flush_interval -1
}
}

我自己还配置了 SSO 登录,但那有些过于复杂了,不放在本教程。而且,说实话,在你配置了 IP 白名单的情况下,所有安全措施都是在防你自己,别人连看到你网页的机会都没有。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

使用 Docker 和 Caddy 快速部署 Sillytavern
https://blog.zhouheng31.top/posts/sillytavern/
作者
柊 ハル
发布于
2026-07-28
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录