KeePass 2 自建 WebDAV 方案经验分享

观前提醒

本教程非手把手教程,仅做为补充教程,意在记录与帮助像我一样的新手在从零开始接触 KeePass 的时候可能会遇到的问题。(也是我遇到的问题)。

以下内容将为我从零开始接触 KeePass 的视角与顺序(人称)描写

观前必看

前人栽树后人乘凉,您先需要阅读以下内容。
在以下内容中,我将默认您已经阅读过以下内容。

首先,您应该查看了以上内容,并进行了 KeePass 对应客户端的安装与汉化等一系列初始步骤。

(建议快速浏览一遍,看完有个大概了解,再把我这篇看了,再结合着实际操作)

对于我的使用场景,客户端我选择的是:

自建 WebDAV 方案

在众多推荐中对于多端同步,大家都使用的是坚果云作为 WebDAV 同步方案。

对于我来说,为了一个密码管理工具去注册一个坚果云的话,感觉有点不值当。

本着一切都要掌握在自己手中的折腾原则,最终我选择使用的是自建 WebDAV 服务的方案来解决多端同步的问题

其大体思路与KeePass 2 开源密码管理工具使用经验分享大佬的一致

具体来说是使用 nginx 配置功能完整的 webdav 服务器

(为什么不使用AList呢?因为我的机子是国内小:chicken:,AList似乎会被检测到涉诈,秉着宁可信其有不可信其无的想法遂放弃)

具体流程如下:

0. 拥有一台机可以用于自建 WebDAV

零、检查 Nginx/OpenResty 是否支持 WebDAV 模块

首先,你可以查看当前 Nginx 或 OpenResty 是否已经编译了 WebDAV 模块。

运行以下命令查看已编译的模块:

nginx -V

在输出中查找 --with-http_dav_modulenginx-dav-ext-module 相关字样,则证明已经支持webdav 服务,可以跳过以下一,二节。

否则说明你的 Nginx 没有启用 WebDAV 模块。需要重新编译 Nginx 或 OpenResty,并在编译时加入 WebDAV 模块:

--with-http_dav_module

一、安装必要的模块

为了使 WebDAV 工作,我们需要安装以下 Nginx 模块:

  • ngx_http_dav_module:Nginx 默认未启用的模块,支持 WebDAV 的基本方法(如 PUTDELETE 等)。
  • nginx-dav-ext-module:提供额外的 WebDAV 方法支持,例如 PROPFINDOPTIONSLOCKUNLOCK
  • headers-more-nginx-module:修复 iOS、Windows 在使用 COPYMOVE 方法时 URI 末尾缺少 / 的问题。
  • ngx_http_auth_basic_module:提供用户验证功能。

二、安装依赖及编译

2.1 安装 nginx-dav-ext-module 的依赖

nginx-dav-ext-module 依赖 libxml2libxslt,需要安装这些库**(以Debian 系统为例)**:

apt-get update
apt-get install libxml2-dev libxslt-dev

2.2 安装 OpenResty 的相关依赖

OpenResty 需要一些开发库来支持编译 Nginx 和相关模块:

apt-get install -y \
  build-essential \
  libpcre3-dev \
  zlib1g-dev \
  openssl \
  libssl-dev

2.3 下载 OpenResty 和 nginx-dav-ext-module

首先下载 OpenResty 和 WebDAV 扩展模块的源码:

# 代码仅供参考,版本请自行选择(当前选择版本为`1.19.9.1`)
# 下载 openresty
wget https://openresty.org/download/openresty-1.19.9.1.tar.gz
tar -zxvf openresty-1.19.9.1.tar.gz
cd openresty-1.19.9.1/

# 代码仅供参考,解压位置自行选择(当前解压位置在`/root/nginx-dav-ext-module`)
# 克隆 nginx-dav-ext-module 源码
git clone https://github.com/arut/nginx-dav-ext-module /root/nginx-dav-ext-module

2.4 (重新编译)编译 OpenResty 并启用 WebDAV 模块

如果您的机器已经存在 OpenResty 或 nginx 只需要重新编译并添加模块即可。

在解压的(原有的) OpenResty 目录下进行编译,确保启用 dav 相关模块:

# 代码仅供参考,无法直接运行
./configure --prefix=/opt/openresty/ --with-threads --with-http_ssl_module \
--with-http_v2_module --with-http_realip_module --with-http_addition_module \
--with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module \
--with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module\ --with-http_slice_module --with-http_stub_status_module --with-stream --with-stream_ssl_module\ --with-stream_ssl_preread_module  --with-http_flv_module  --with-http_mp4_module \
--with-http_sub_module  --with-http_slice_module  --with-http_stub_status_module \
--with-http_dav_module  --add-module=../nginx-dav-ext-module/

执行 makemake install

make
make install

三、配置 Nginx 的 WebDAV 模块

3.1 修改 Nginx 配置文件

参考配置:

server {
    listen 80;
    server_name 你的域名;

    # 强制 HTTP 重定向到 HTTPS
    if ($server_port !~ 443){
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    http2 on;
    listen [::]:443 ssl;

    server_name 你的域名;

    # SSL 配置[可选,不需要请删除该段]
    ssl_certificate    域名证书.pem;
    ssl_certificate_key  域名证书privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 设置 webdav 目录,注意 Nginx worker 用户对该目录需有读写权限,可自定义
    root /data/webdav/file;

    index index.html index.htm index.nginx-debian.html;

    # 认证方式
    auth_basic              realm_name;
    # 存放认证用户名、密码文件(确认有对应权限),位置可自定义
    auth_basic_user_file    /data/webdav/.credentials.list;
    location / {
      # 启用 WebDav 的一些关键字        
      dav_methods PUT DELETE MKCOL COPY MOVE;
      # 启用 WebDav 的一些扩展关键字用于支持应用访问
      dav_ext_methods PROPFIND OPTIONS;
      # 设置 WebDav 目录下新增文件的默认权限
      dav_access user:rw group:rw all:r;
      # 创建文件夹时自动创建路径上不存在的文件夹
      create_full_put_path  on;
      # 设置报文最大长度便于文件传输,这里为8MB
      client_max_body_size 8m;
      # 让 nginx 自动生成索引页面,避免 403 错误
      autoindex on;
    }

    # Mac挂载 webdav 后会自动写入很多文件,可以通过 nginx 配置屏蔽掉,保持 webdav 目录的干净
    location ~ \.(_.*|DS_Store|Spotlight-V100|TemporaryItems|Trashes|hidden|localized)$ {
      access_log  off;
      error_log   off;

      if ($request_method = PUT) {
        return 403;
      }
      return 404;
    }

    location ~ \.metadata_never_index$ {
      return 200 "Don't index this drive, Finder!";
    }
}

配置 SSL 的过程和绝大部分网站配置 SSL 的过程相同

3.2 设置 WebDAV 用户和密码

在配置文件中还添加了用户身份验证, nginx 通过读取认证文件(包含了用户名和密码)来在访问网站时验证客户身份,添加一个用户与密码的方法也很简单:

# 添加一个用户,userName 为示例用户名
echo -n 'userName:' | sudo tee -a /data/webdav/.credentials.list
# 设置用户的密码, passwd 为示例密码
openssl passwd -apr1 | sudo tee -a /data/webdav/.credentials.list

四、启动 OpenResty

检查 Nginx 配置文件:

nginx -t

如果没有错误,启动 Nginx:

nginx

注意开放端口与防火墙。

对应的服务器厂家端口防火墙,UFW,安装有面板的话对应面板的防火墙。

至此,配置完成后就可以使用了。

Windows 挂载

我选择使用的是 RaiDrive

设置好对应的配置即可。其中用户名、密码为 3.2 中设置的用户名、密码。

使用细节

多端同步方案

主要思路:远程数据库 + 触发器 实现每次保存一次远程数据库后同步一次远程数据库到本地备份。本地备份用于无网络情况下使用。

  1. KeePass 2 新建一个数据库,放置于一个通过 WebDav 协议同步备份的目录中,作为主要工作数据库

     以我本人为例,我将 WebDav 挂载在了 Z 盘符,结构如下:
    
Zdrive
├─ KPkey # 存放密钥文件(一般不建议和数据库文件存储在同一个目录,最好能隐藏起来或者放在移动设备中(但实际使用不现实,在能力范围内尽量保护好吧))
├─ KeePass # 存放数据库
└─ KeePass_Backup # 备份用

因此在KeePass 2 新建数据库时,选择的路径为:Z:\KeePass\XXX..kdbx

  1. 设置触发器
    利用触发器实现:每次保存远程数据库时,通过 WebDav 与远程数据库同步到本地备份。本地备份用于无网络情况下使用。
  • 运行程序,点击菜单栏的工具-触发器

工具-触发器

  • 在弹出的触发器列表窗口中点击添加,输入名称,下方的启用启动时打开默认勾选,只执行一次不勾选

  • 来到事件选项卡,点击添加事件,选择已保存数据库文件,下面的条件设置为包含、并输入 kdbx

  • 接下来打开条件选项卡

    • 新建一条条件,选择远程主机可以链接,并输入你的同步服务器域名,不带协议(不带 http://

    • 再新建另一个条件,条件选择字串,字串值为 {DB_BASENAME}(代表数据库名称的表达式),并根据实际情况设置具体条件,例如我只有一个数据库,所以选择的是 等于 数据库名

条件

  • 最后来到动作选项卡,这里共需建立三条动作

    逻辑为:关闭此触发器 → 执行同步 → 再开启触发器,主要是为了防止同步操作也被认定为保存数据库,再次触发此触发器,造成死循环

    • 第一条,选择更改触发器 开/关 状态,新状态为关闭

    • 第二条,选择执行命令行/网址,选择我给出的copy_files.bat 文件(在附录)

    • 第三条,选择更改触发器 开/关 状态,新状态为开启

动作

这样就实现了每次保存一次远程数据库后同步一次远程数据库到本地备份。本地备份用于无网络情况下使用。

主动备份

除了以上方案我还利用面板和 bat 脚本做了多重备案方案。以下给出参考。

  1. 计划任务实现服务器端定时备份,参考脚本内容:

         # 定义变量
         SOURCE_DIR="服务器端webdav根目录"
         BACKUP_DIR="服务器端预期备份目录"
         TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
         BACKUP_FILE="webdav_backup_$TIMESTAMP.tar.gz"
         # 检查备份目录是否存在,如果不存在则创建
         if [ ! -d "$BACKUP_DIR" ]; then
         mkdir -p "$BACKUP_DIR"
         fi
         # 压缩备份(这里假设你的结构与我一致,在根目录下存在 KPkey KeePass 两个目录,否则请自行修改)
         tar -czf "$BACKUP_DIR/$BACKUP_FILE" -C "$SOURCE_DIR" KPkey KeePass
         # 输出备份结果
         if [ $? -eq 0 ]; then
         echo "备份成功:$BACKUP_DIR/$BACKUP_FILE"
         else
         echo "备份失败"
         fi
    

    你可以使用 cron 等方式定期执行该 shell 脚本来备份。

  2. Windows 开机备份

    我将在服务器端备份的目录也设在 webdav 目录中,所以我还可以通过 Windows 的 dat 脚本再将对应的备份拷贝一份到本地其他目录备份。

    脚本参考如下:

    @echo off
    setlocal
    
    rem 定义源和目标目录
    set "SOURCE_DIR=Z:\KeePass_Backup(这是我的目录,换你自己的)"
    set "DEST_DIR=本机其他预期存放备份目录"
    
    rem 检查源目录是否存在
    if exist "%SOURCE_DIR%\*" (
       echo 发现备份文件,开始复制...
    
       rem 检查目标目录是否存在,如果不存在则创建
       if not exist "%DEST_DIR%" (
           mkdir "%DEST_DIR%"
           echo 创建目标目录:%DEST_DIR%
       )
    
       rem 遍历源目录中的每个文件
       for %%F in ("%SOURCE_DIR%\*") do (
           rem 检查目标目录中是否存在同名文件
           if not exist "%DEST_DIR%\%%~nxF" (
               echo 复制 %%~nxF 到 %DEST_DIR%
               copy "%%F" "%DEST_DIR%\" >nul
           ) else (
               echo 跳过 %%~nxF,目标文件已存在。
           )
       )
    
       echo 复制完成。
    ) else (
       echo 没有找到备份文件。
    )
    
    endlocal
    

    设置开机自启动:

    • Win + R 快捷键打开运行窗口
    • 输入 shell:Startup 确认
    • 放入原脚本的快捷方式
  3. KPSimpleBackup 自动备份数据库

    地址

温馨提示

如果您看到这里,建议您重新看一遍开头的文章噢,包括详细配置设置、插件推荐介绍都在里面了,我就不复述了,但也很重要!

附录

copy_files.bat 文件

copy_files.bat 文件
@echo off
start /min cmd /c (
    rem 定义源和目标路径
    set "SOURCE_DB=windows挂载的webdav映射路径中的数据库文件的路径"
    set "SOURCE_KEY=windows挂载的webdav映射路径中的密钥文件的路径"
    set "DEST_DB=本机预期存放备份的数据库文件的路径"
    set "DEST_KEY=本机预期存放备份的密钥文件的路径"

    rem 检查并创建目标目录
    if not exist "本机预期存放备份的数据库文件的目录" (
        mkdir "本机预期存放备份的数据库文件的目录"
    )
    if not exist "本机预期存放备份的密钥文件的目录" (
        mkdir "本机预期存放备份的密钥文件的目录"
    )

    rem 强制复制文件
    copy /Y "%SOURCE_DB%" "%DEST_DB%"
    copy /Y "%SOURCE_KEY%" "%DEST_KEY%"
)

exit
20 个赞

感谢你的分享

感谢大佬分享

1 个赞

好起来了,推荐第三方+自建一起使用,小规模自建总有风险

1 个赞

感谢大佬教程

折腾万岁,感谢大佬教程

感谢分享 :smiling_face_with_three_hearts: :smiling_face_with_three_hearts:

1 个赞

KeePass mark

感觉搞复杂了呀,我是 KeePass+群晖的WebDav。Windows只需要使用powershell命令修改下Windows的dav默认支持版本BasicAuthLevel为2即可。

Set-ItemProperty -Path “HKLM:\SYSTEM\CurrentControlSet\Services\WebClient\Parameters” -Name “BasicAuthLevel” -Value 2
Restart-Service WebClient

效果:
image
image

2步实现 多端密码同步。

1 个赞

前提是要有群晖或类似 NAS 产品,另外还要考虑是 NAS 的话还要搞到一个公网 IP 内网穿透吧tieba_125

由于我没有 NAS 所以主数据库直接丢云服务器上了,效果一样的。看个人喜好

另外 windows 系统确实可以用自带的 IIS 服务直接搭建 webav 服务。
这个 powershell 命令应该只是使电脑同时支持 http 和 https(因为一般直接用 ip 的话没有 SSL 证书配置 https),相当于已经到使用 Raidrive 客户端连接那部分了。