Debian 13 使用 Docker 自建WebDAV:轻量 WebDAV 服务端部署指南

最近折腾服务器的时候,我重新认真思考了一遍备份这件事。

事情的起因其实很简单。

2026 年 10 月 1 日,InfiniCLOUD 的 zeze 节点发生故障。公告地址:https://infini-cloud.net/en/news_20261001.html

我原本放在 InfiniCLOUD 里的数据,随着这次故障全部失去了访问能力。

InfiniCLOUD 官方最初公告显示,zeze 节点自 10 月 1 日 1:53(日本时间)起发生故障,受到影响的用户无法通过文件浏览器以及外部应用访问文件。到了 10 月 3 日,官方进一步说明,目标服务器存在多块存储盘之间的数据严重不一致,情况已经超过预设阈值,存储区域数据无法取回的可能性正在增加。由于如果继续在原环境中等待数据抢救,服务恢复可能需要数月,因此官方决定准备新的服务器和数据区域,并在迁移后继续并行进行数据抢救。

云存储可以用来存东西,但不要把云端存了一份直接等同于已经完成备份。

这次我没有再去找一个功能复杂的网盘,而是决定自己搭一个非常简单的 WebDAV 存储服务。

我的需求很明确:

给几个轻量服务器保存配置文件、数据库和服务数据;
支持标准 WebDAV,可以直接挂载或者通过程序上传;
Docker 部署,方便维护;
不希望额外开放一个公网端口;
有基础的账号密码认证;
再配合 Fail2ban,防止暴力破解;
整体尽量简单,搭好之后就不再折腾。
最终选择的是 hacdias/webdav 。

一、创建 WebDAV 目录

首先创建工作目录:

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

最终结构:

/opt/webdav/
├── docker-compose.yml
├── config.yml
└── data/

其中:

docker-compose.yml

负责 Docker 服务。

config.yml

负责 WebDAV 配置。

data/

则是真正存放备份文件的地方。

二、使用 Docker 部署

创建 Compose 文件:

写入:

services:
  webdav:
    image: ghcr.io/hacdias/webdav:latest
    container_name: webdav
    restart: unless-stopped

    ports:
      - "127.0.0.1:6065:6065"

    volumes:
      - ./config.yml:/config.yml:ro
      - ./data:/data

    command: ["-c", "/config.yml"]

    logging:
      driver: journald

启动:

cd /opt/webdav
docker compose up -d

查看:

docker ps

查看日志:

docker logs webdav

同时检查 journald:

journalctl CONTAINER_NAME=webdav -n 30 --no-pager

三、配置 WebDAV

创建:

nano /opt/webdav/config.yml

写入:

address: 0.0.0.0
port: 6065

tls: false

prefix: /

debug: false

directory: /data

permissions: CRUD

behindProxy: true

users:
  - username: backup
    password: "这里填写一个高强度随机密码"
    directory: /data
    permissions: CRUD

log:
  format: json
  colors: false
  outputs:
    - stderr

四、1Panel 配置反向代理

接下来在 1Panel 中创建网站。

域名:

dav.example.com

反向代理目标:

http://127.0.0.1:6065

然后申请 HTTPS 证书。

最终访问:

https://dav.example.com/

整个过程中,WebDAV 本身都不需要直接面对公网。


五、给 WebDAV 加上 Fail2ban

WebDAV 本身有账号密码认证,那么暴力破解自然也需要考虑。

这里直接使用 Fail2ban。

创建过滤器:

nano /etc/fail2ban/filter.d/webdav.conf

写入:

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*invalid password\s*\{.*"remote_address":\s*"<HOST>:\d+"\s*\}
            ^.*invalid username\s*\{.*"remote_address":\s*"<HOST>:\d+"\s*\}

ignoreregex =

然后创建 Jail:

nano /etc/fail2ban/jail.d/webdav.local

写入:

[webdav]

enabled = true

filter = webdav

journalmatch = CONTAINER_NAME=webdav

maxretry = 5
findtime = 600
bantime = 604800

banaction = nftables[type=allports]

ignoreip = 127.0.0.1/8 ::1

backend = systemd

这套配置的意思是:

10 分钟内失败 5 次
        ↓
触发封禁
        ↓
封 7 天

官方项目同样提供了 Docker + journald + Fail2ban 的配置思路。


六、检查 Fail2ban

修改完配置后,先测试:

fail2ban-client -t

确认没有错误后:

systemctl restart fail2ban

然后:

systemctl status fail2ban --no-pager

最后:

fail2ban-client status webdav

正常情况下会看到:

Status for the jail: webdav
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- Journal matches:  CONTAINER_NAME=webdav
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

其中:

Journal matches: CONTAINER_NAME=webdav

非常关键。

这说明 Fail2ban 已经成功监控到了 WebDAV Docker 容器的日志。


七、实际测试一次

部署完成后,可以故意输入错误密码几次进行测试。

访问:

https://dav.example.com/

故意输入错误密码。

然后查看:

journalctl CONTAINER_NAME=webdav -n 50 --no-pager

应该能看到:

invalid password

以及客户端 IP。

再执行:

fail2ban-client status webdav

确认失败次数已经被 Fail2ban 统计。

如果触发封禁,也可以手动解封:

fail2ban-client set webdav unbanip 你的公网IP

测试完成后,这部分基本就不用再动了。


八、最后

这次折腾 WebDAV,说到底并不是因为 WebDAV 有多么高级。

它甚至可以说是一个很普通、很简单的工具。

但我现在更在意的是:

数据在哪里?
有没有第二份?
第二份和第一份是不是分开的?
真正出问题的时候能不能恢复?

InfiniCLOUD 这次 zeze 节点故障,让我重新意识到:

“能访问”不等于“安全”,“存了一份”更不等于“有备份”。

所以这次干脆自己搭一个简单的 WebDAV 备份仓库。

至少从现在开始,我的重要服务数据不会再只依赖单一存储。

评论区
头像

本站已运行 ❤ 0天 00时 00分 00秒