笔者今天在使用 Next Chat 聊天时,突然想到聊天数据应该是可以备份的,在设置里面发现它仅支持 WebDAV 和没听说过的 UpStash 两种文件协议,而笔者使用的其它软件又广泛支持前者进行备份同步。于是今天便来捣腾 WebDAV 服务并实现数据备份。
Docker 部署 WebDAV 服务
一旦使用上了 Docker,就再也不想回去那种将服务运行在机器本体上的时代了。笔者首选使用 Docker 部署 WebDAV 服务,在 Docker Hub 以 webdav
为关键词搜索,有如下结果:

笔者尝试了下载量和收藏数最高的 bytemark/webdav
,但发现设置了挂载目录后无法正常上传文件,仔细阅读说明文档才看到,必须要将宿主机的挂载目录设置为写死的 /srv/dav
,意味着如果想要用其它目录来存放 WebDAV 里的文件的话,还需要额外添加一个软链接。这样的限制感觉笨笨的,很不优雅,于是找了找它的 Github 仓库,发现作者在写完这个镜像,发了一篇部署文档后就再没有更新了,代码也就停留在了 2018 年。也许 WebDAV 协议已经相当稳定了,但是笔者还是想要找一个稍微好一点的 WebDAV 服务。
接着,笔者尝试在 Github 上以 webdav
为关键词搜索,发现了关联度和星标均为最高,并且活跃更新的 hacdias/webdav
。它针对不同用户组的权限管理能力非常强,笔者很喜欢。但笔者遇到的一个问题是:将本地的 local/path/to/data
目录关联给容器的 /data
目录后,同步的数据仍然被放置在了容器的根目录里,导致无法持久化备份文件。这也许是当前版本的 Bug,也有可能是没配置对的原因,总之笔者又着眼于找下一个 WebDAV 镜像去了。
最后,笔者尝试了 Docker Hub 上目前下载量和收藏数均为第二的 ugeek/webdav
,没有上述的问题,满足了笔者的需要。笔者在 MacOS 系统上部署 WebDAV 服务,因此要拉取它的 arm64
版本:
docker pull ugeek/webdav:arm64
运行 WebDAV 容器:
docker run --name webdav \
--restart=unless-stopped \
-p 3180:80 \
-v $HOME/WebDAV/data:/media \
-e USERNAME=YOUR_USERNAME \
-e PASSWORD=YOUR_PASSWORD \
-e TZ=Asia/Shanghai \
-e UDI=1000 \
-e GID=1000 \
-d ugeek/webdav:arm64
笔者将 WebDAV 服务暴露在宿主机的 3180 端口,将数据持久化存储在 $HOME/WebDAV/data
目录下。访问 127.0.0.1:3180
,输入用户名和密码,即可看见当前 WebDAV 服务中包含的文件列表(当然此时为空)。
通过 frp 将内网的服务暴露给公网服务器上,再通过配置公网服务器的 Nginx 配置,现在笔者的 WebDAV 服务就可以通过域名 https://webdav.towind.fun
访问了!
图形界面管理 WebDAV
用 Postman 来对 WebDAV 里的文件做 CRUD 显然不符合实际需要。在这一章节,笔者将分别通过 Windows 和 AList 来连接 WebDAV 服务,方便以后实际的管理与使用。
Windows 挂载 WebDAV
笔者的 WebDAV 服务由 SSL 加密,因此需要首先配置 Windows Web Client 的身份验证级别,即在“运行”里输入 regedit
打开注册表编辑器,找到 Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters
,修改其中键 BasicAuthLevel
的值为 2
。

笔者翻阅有关 Windows 系统连接 WebDAV 服务的官方文档发现,BasicAuthLevel
默认值为 1
的时候就已经对 SSL 加密的连接启用身份验证了,但笔者仅在其值为 2
的时候能顺利连接上。暂且蒙在鼓里。
右键“我的电脑”,选择“选择映射网络驱动器”,输入 WebDAV 的地址,再输入用户名和密码即可连接到服务:

这样,就可以在 Windows 系统上,像管理其它本地文件一样管理 WebDAV 里的文件了!
AList 挂载 WebDAV
笔者之前在 Docker 上部署了 AList 服务,它也支持连接并管理 WebDAV 服务。这一切尤为简单,只需要在“管理 - 存储”页面添加 WebDAV 驱动,输入账号和密码即可连接:

回到主页,WebDAV 服务就顺利地挂载到了指定的路由上。这样,就可以随时随地通过浏览器访问 AList,管理 WebDAV 里的文件了!
备份应用数据到 WebDAV
备份 Obsidian 笔记到 WebDAV
笔者使用 Obsidian 同步多端的笔记,过去使用 OneDrive 来同步笔记的数据,现在就可以迁移到 WebDAV 上了。只需要安装插件市场里的三方插件 Remotely Save,配置 WebDAV 即可:

点击同步按钮,笔记数据就光速保存到 WebDAV 上啦!相比 OneDrive,使用 WebDAV 同步的速度要显著更快,源于少走了不少鉴权和请求接口罢。
备份 Next Chat 数据到 WebDAV
笔者撰写此文时使用的 Next Chat 版本为 v2.15.8
。
尽管在设置中它提供了同步配置和聊天记录到 WebDAV 的能力,但无论怎么配置也无法成功同步数据,翻看好多 Issues 和相关的帖子才终于理出来要如何使用。
Next Chat 设计为 Web 端使用,部署时需要配置环境变量 WHITE_WEBDAV_ENDPOINTS
以添加 WebDAV 服务白名单。官方构建版本仅对一些常见 WebDAV 服务域名开了白名单,但像笔者这样的自建 WebDAV 服务自然是不可能在名单内。因此需要手动部署一个属于自己的 Next Chat 的 Web 版本,在环境变量中为 WebDAV 服务开放白名单。这样,在同步数据时,使用自建站点的域名作为代理服务器就可以了。
参考部署 Next Chat 到 Vercel 的官方文档,部署自己的 Next Chat 站点,将 WHITE_WEBDAV_ENDPOINTS=https://webdav.towind.fun
作为构建环境变量:

现在,笔者自建的 Next Chat 站点便允许被作为请求 https://webdav.towind.fun
的代理服务器了。
配置云同步,检查可用性,成功在 WebDAV 的根目录下创建了文件夹 chatgpt-next-chat
:

尝试初次同步 Next Chat 的数据:首先发出请求检查 WebDAV 里是否包含云端数据,响应值为 404 Not Found,符合预期;接着将备份的数据上传到 WebDAV,服务端响应 502 Bad Gateway:

查看 Nginx 错误日志:
tail -n 10 /var/log/nginx/error.log
...
[error] 2107#2107: *36701359 client intended to send too large body: 1663429 bytes, client: xxx.xx.xxx.xxx, server: webdav.towind.fun, request: "PUT /chatgpt-next-web/backup.json HTTP/2.0", host: "webdav.towind.fun"
可知 Nginx 拒绝了包含超过设定大小数据的请求,那么只需要将设定的大小放开一点就好。编辑对应的 Nginx 配置,例如设置允许的最大请求体为 50M
:
server {
server_name webdav.towind.fun;
client_max_body_size 50M;
}
再次尝试同步 Next Chat 的数据,成功上传到 WebDAV:

未来无论在什么客户端使用 Next Chat 时,都可以同步配置数据和聊天记录了!
参考文章
在“Windows 挂载 WebDAV”章节里,笔者主要参考了《Windows 挂载 WebDAV》这篇博客,解决了挂载异常的问题。
在“备份应用数据到 WebDAV”章节里,笔者主要参考了《终于拿下了NextChat的WebDAV云同步,我感觉我又行了》和《【拉跨,但能用了】NextChat 的 WebDAV 云同步。。》这两篇帖子。