【实用的开源工具】webdav:一个轻量的 WebDAV 文件服务器

阅读约 10 分钟
【实用的开源工具】webdav:一个轻量的 WebDAV 文件服务器

「实用的开源工具」系列:我只收集值得用的开源项目,写清楚它能做什么、怎么部署、有哪些坑,并在文末标明出处。内容整理自官方文档,核对日期 2026-10-31,具体版本以官方为准。命令和配置都摘自官方 README、Dockerfile 和 Compose 文件,本文没有做实机测试,请先在测试环境里走一遍。

项目信息卡

项目说明
名称webdav(仓库 hacdias/webdav)
做什么官方描述是“简单、独立的 WebDAV 服务器”:把一个目录通过 WebDAV 协议提供出去,支持多用户、按用户设置目录和读写权限
许可证MIT
仓库github.com/hacdias/webdav
最近版本v5.17.3(2026-10-30 发布,查询于 2026-10-31)
维护状态仍在维护:仓库未归档,最近一次推送 2026-10-31,最新版本一天前刚发布;SECURITY.md 写明 5.x 是受支持的版本,低于 5.x 不再支持
运行方式单个程序(可用二进制、go install、Homebrew 或 Docker),默认端口 6065,用一个配置文件(YAML、JSON 或 TOML)
镜像ghcr.io/hacdias/webdav 和 Docker Hub 的 hacdias/webdav
注意它只是 WebDAV 服务端。README 里没有提到网页上传、分享链接这类“网盘界面”,只有可选的目录列表页(listing)。名字相近的 File Browser(filebrowser/filebrowser)是另一个项目,本文不涉及

它能做什么

  • WebDAV 服务:支持常见的 WebDAV 方法,如 PROPFIND、PUT、MKCOL、COPY、MOVE、LOCK 等。可以用支持 WebDAV 的客户端去访问;具体哪些软件、怎么配,官方 README 没有写,需要看各客户端的说明。
  • 多用户:在配置里列出用户,使用 Basic 认证。每个用户可以有自己的目录和权限。
  • 细粒度权限:权限分 C(创建)、R(读)、U(更新)、D(删除),默认只有 R;还可以用 rules 针对路径或正则单独设置。
  • 多目录:directories 可以把多个目录作为虚拟根目录下的条目展示。
  • HTML 目录列表:开启 listing 后,用浏览器访问一个目录会看到列表页,而不是 WebDAV 的 XML。
  • CORS、HSTS、TLS:都可以通过配置开启。
  • 部分更新:支持兼容 SabreDAV PATCH 扩展的部分文件更新,细节见官方 README。

适合的场景:想要一个小而简单、能被手机、电脑、各种同步工具当作远程存储来用的服务,不想装一个很重的全家桶。

不适合的场景:你想要带网页界面的上传、预览、分享链接。这个项目不是干这个的。

部署

先建目录:

bash
mkdir -p /opt/webdav/data && cd /opt/webdav

第 1 步:生成密码哈希

官方的配置示例里有明文密码,但同时提示可以用 bcrypt 加密的密码,并且程序自带 webdav bcrypt 命令来生成。用 Docker 的话可以这样(bcrypt 子命令接收一个密码参数,输出哈希):

bash
docker run --rm hacdias/webdav:v5.17.3 bcrypt '你的密码'

输出的哈希形如 $2y$10$...。写进配置时前面要加 {bcrypt},见下面的例子。注意密码会留在 shell 历史里,这是通用的注意点,用完可以清掉历史。

第 2 步:写配置文件

/opt/webdav/config.yml。键名取自官方 README 的完整示例,我只留下需要的几项:

yaml
address: 0.0.0.0
port: 6065

# 容器里要监听所有地址,对外的访问范围由 Docker 的端口绑定控制
directory: /data

# 默认权限:只读。想让用户能写,在用户处覆盖
permissions: R

# 在反向代理后面时设为 true,日志里记录的是 X-Forwarded-For 的最后一项
behindProxy: true

users:
  - username: alice
    password: "{bcrypt}$2y$10$把这里换成上一步生成的哈希"
    permissions: CRUD

说明:

  1. 没有 users 就没有认证。 官方说明:配置里检测到用户才会启用 Basic 认证,否则不做任何认证。所以一定要写用户。
  2. permissions 默认 R(只读),可以组合 C、R、U、D,不区分大小写。
  3. directory 是用户能访问的目录;如果用户自己配置了 directory,则用用户的。上面这个路径是容器里的路径,对应下面映射的 ./data。
  4. 配置文件支持 YAML、JSON、TOML。官方还说明:顶层键用 camelCase,嵌套在某个部分里的键用 snake_case。

第 3 步:Compose 文件

官方仓库里有 compose.yml,但里面的镜像是 webdav:test(本地测试用),不能直接照抄。下面的结构参考它和 README 里的 docker run 命令,保存为 /opt/webdav/compose.yaml:

yaml
services:
  webdav:
    image: hacdias/webdav:v5.17.3
    container_name: webdav
    restart: unless-stopped
    command: ["-c", "/config.yml"]
    ports:
      - "127.0.0.1:6065:6065"
    volumes:
      - ./data:/data
      - ./config.yml:/config.yml:ro

对应官方 README 里的 docker run 写法是:

bash
docker run \
  -p 6065:6065 \
  -v ./config.yml:/config.yml:ro \
  -v ./data:/data \
  ghcr.io/hacdias/webdav -c /config.yml

几点说明:

  • 镜像标签:README 的示例是 latest,并说明可以用具体标签固定版本,也可以用 main 跟随开发分支。我写 v5.17.3,是因为在 Docker Hub 上能查到这个标签;用之前请自己再确认,并按需换成更新的版本。
  • 官方 compose.yml 里还有一行 security_opt(label=type:container_runtime_t)。我没有放进示例里,因为我没找到官方对它的说明。
  • 端口绑定到 127.0.0.1,交给反向代理对外。

启动:

bash
docker compose up -d
docker compose logs -f webdav

第一次使用

  1. 想在浏览器里看一眼,可以先在 config.yml 里加上 listing:
yaml
listing:
  enabled: true

重启容器后,用浏览器访问 http://127.0.0.1:6065/(远程服务器可以先用 SSH 端口转发),输入用户名和密码,应该就能看到目录列表。官方说明:开启后,对目录的 GET 请求会返回 HTML 列表,而不是 PROPFIND 的响应。

  1. 想验证 WebDAV 本身是否正常,可以用 curl 发一个 PROPFIND 请求。这是 WebDAV 协议的通用用法,不是官方文档里的示例:
bash
curl -u alice -X PROPFIND -H "Depth: 1" http://127.0.0.1:6065/

返回 XML 列出目录内容,就说明服务在工作。

  1. 然后在你喜欢的 WebDAV 客户端里填服务地址、用户名和密码。各客户端的操作官方没有讲,这里不展开。

反向代理(Nginx)

官方 README 有专门的反向代理说明,核心是:要转发正确的头,否则会出现 502;同时 COPY 和 MOVE 请求带的 Destination 头里有完整域名,需要改写成只剩路径。官方的 Nginx 示例,我换成了本文的端口和域名,并补上 443:

nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name dav.example.com;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    # Nginx 默认只允许 1M 的请求体,上传大文件会失败,按需调大(通用做法,非官方提示)
    client_max_body_size 1G;

    location / {
        proxy_pass http://127.0.0.1:6065;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;

        # 让 COPY 和 MOVE 能正常工作:把 Destination 改写成只含路径
        set $dest $http_destination;
        if ($http_destination ~ "^https?://[^/]+(?<path>/.*)$") {
            set $dest $path;
        }
        proxy_set_header Destination $dest;
    }
}

官方 README 里还有 Caddy 的示例,思路相同。

挂在子路径下

如果不想用单独的域名,而是 example.com/webdav:官方要求不要在代理里去掉子路径,因为 PROPFIND 的响应里带完整路径,客户端会拒绝不在自己请求范围内的条目。做法是把路径原样转发,并在配置里设:

yaml
prefix: /webdav

Nginx 用 location /webdav { ... },并且 proxy_pass 后面不要带路径,否则前缀会被替换。请求路径和 Destination 头都要带前缀,缺了会得到 400 Bad Request。

更新与卸载

更新:改 compose.yaml 里的版本标签(先确认新标签存在),然后:

bash
cd /opt/webdav
cp -a data data.bak-$(date +%F)    # 通用做法:升级前先备份,里面是你的文件
docker compose pull
docker compose up -d

先看一下 Releases 的更新说明。

卸载:

bash
cd /opt/webdav
docker compose down

这只会删除容器。data 目录就是你的文件本身,config.yml 是用户配置,确认不再需要时才手动删除:

bash
rm -rf /opt/webdav/data    # 不可恢复,确认后再执行

踩坑清单

  1. 没写 users 就是不设防。 官方说明:只有配置了用户才会启用 Basic 认证,否则没有认证。如果端口又对外开放,任何人都能按默认权限访问。
  2. 默认权限只有读。 permissions 默认 R。上传、新建、改名失败,先看用户的权限有没有 C、U、D。还有两个细节:LOCK 算写操作,对已存在路径需要 U、对不存在路径需要 C;COPY 或 MOVE 覆盖已有文件需要 U,覆盖整个目录则需要对该目录及其下所有路径有 D。
  3. 别用明文密码。 官方示例里为了演示有明文,实际请用 {bcrypt} 开头的哈希。官方发布说明里还提到:格式不对的 bcrypt 哈希会在启动时被拒绝,所以复制哈希时别漏字符。
  4. Basic 认证走 HTTP 就是明文。 这是通用知识:务必走 HTTPS,要么在反向代理上加证书,要么用官方支持的 tls、cert、key 让程序自己提供 TLS。
  5. HSTS 头只在程序自己处理 TLS 时才有效。 官方注释写明:在代理后面,请在代理上设置这个头。
  6. 反向代理漏了头会 502,漏了 Destination 改写会让复制和移动失败。 照上面的配置写。官方 README 里的示例端口是 8080,别忘了换成 6065。
  7. 子路径不能让代理去掉。 需要 prefix 配合,请求路径和 Destination 都要带前缀,否则返回 400 Bad Request。
  8. rules 的匹配顺序和细节容易搞错。 官方说明:规则从后往前匹配,第一个匹配到的生效,所以靠后的规则优先;rulesBehavior 默认是 overwrite,也就是用户自己有规则时,会覆盖全局规则,而不是追加;regex 规则是按字面匹配的,^/secret/ 不会匹配 /secret 本身,要写 ^/secret(/|$)。
  9. 大小写不敏感或特殊文件系统上,别指望 rules。 官方说明:程序启动时会探测所在目录的文件系统是否区分大小写;在 Windows 上,一些会被系统当成别的文件的名字(含 \、:,以点或空格结尾,设备名如 CON,8.3 短名等)会直接返回 400。Linux 上的 FAT32 盘和 Docker Desktop 里挂载的 Windows 目录也可能出现短名问题,官方建议在这些位置不要依赖 rules,或者在卷上关闭 8.3 短名。
  10. 容器默认以 root 运行。 我读了官方 Dockerfile,其中没有 USER 指令,基础镜像是 scratch,所以进程应该是 root,在 ./data 里创建的文件属主也是 root。这是我从 Dockerfile 推断的,官方没有明说;想改用普通用户可以尝试 Compose 的 user:,但官方文档没写过这种用法,需要自己验证。
  11. CORS 带凭据不能用 *。 要用 credentials: true 时,allowed_hosts 要写具体来源,因为浏览器不接受带凭据又允许任意来源。不涉及浏览器里的网页访问就不用开 CORS。
  12. 防暴力破解。 官方 README 提供了 Fail2Ban 的过滤器和 jail 示例,用 Docker 时要配合 --log-driver journald 和 --name webdav。如果服务暴露在公网,建议配置。
  13. Docker 发布的端口会绕过 ufw 之类的防火墙。 所以示例绑定到 127.0.0.1,由 Nginx 对外。这是 Docker 的通用行为,不是这个项目特有的。
  14. 它不是备份工具。 这是通用提醒:通过 WebDAV 误删文件和直接在服务器上删除一样不可恢复,重要数据请另做备份。

出处

想要类似的东西?网站、Telegram 机器人、运维工具,说说你的需求。
发布需求

有想法或问题?去留言板留言 →