将 docs/ 根目录下的 nginx 相关文档统一移动到 docs/nginx/ 子目录, 提高文档组织性和可维护性。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
688 lines
15 KiB
Markdown
688 lines
15 KiB
Markdown
# Nginx WebDAV 模块完整指南
|
||
|
||
## 1. WebDAV 模块概述
|
||
|
||
### 1.1 模块简介
|
||
|
||
`ngx_http_dav_module` 是 Nginx 的文件管理自动化模块,通过 WebDAV (Web Distributed Authoring and Versioning) 协议支持远程文件操作。
|
||
|
||
### 1.2 主要用途
|
||
|
||
- 文件上传与管理
|
||
- 远程文件编辑
|
||
- 目录结构创建
|
||
- 文件复制与移动
|
||
- 简单的文件服务器
|
||
|
||
### 1.3 编译要求
|
||
|
||
该模块**不会默认构建**,需要在编译时显式启用:
|
||
|
||
```bash
|
||
./configure --with-http_dav_module
|
||
```
|
||
|
||
### 1.4 支持的 HTTP 方法
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `PUT` | 上传/创建文件 |
|
||
| `DELETE` | 删除文件或目录 |
|
||
| `MKCOL` | 创建目录 (Make Collection) |
|
||
| `COPY` | 复制文件或目录 |
|
||
| `MOVE` | 移动文件或目录 |
|
||
|
||
> **注意**:Nginx WebDAV 模块仅支持上述 5 种方法。需要其他 WebDAV 方法(如 PROPFIND、PROPPATCH、OPTIONS、LOCK、UNLOCK)的客户端将无法与此模块配合工作。
|
||
|
||
---
|
||
|
||
## 2. 指令详解
|
||
|
||
### 2.1 dav_methods
|
||
|
||
启用指定的 HTTP 方法。
|
||
|
||
**语法:**
|
||
```nginx
|
||
dav_methods off | PUT | DELETE | MKCOL | COPY | MOVE ...;
|
||
```
|
||
|
||
**默认值:** `off`
|
||
|
||
**上下文:** `http`, `server`, `location`
|
||
|
||
**说明:**
|
||
- `off` - 禁止此模块的所有方法
|
||
- 可以指定一个或多个方法
|
||
- 未列出的方法将被禁止
|
||
|
||
**示例:**
|
||
```nginx
|
||
# 仅启用 PUT 和 DELETE
|
||
dav_methods PUT DELETE;
|
||
|
||
# 启用全部支持的方法
|
||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||
|
||
# 禁用所有 WebDAV 方法
|
||
dav_methods off;
|
||
```
|
||
|
||
---
|
||
|
||
### 2.2 create_full_put_path
|
||
|
||
允许创建所有必需的中间目录。
|
||
|
||
**语法:**
|
||
```nginx
|
||
create_full_put_path on | off;
|
||
```
|
||
|
||
**默认值:** `off`
|
||
|
||
**上下文:** `http`, `server`, `location`
|
||
|
||
**说明:**
|
||
- WebDAV 规范通常要求目标目录必须已存在
|
||
- 设置为 `on` 时,PUT 请求可以自动创建路径中的所有中间目录
|
||
- 对于深度嵌套的文件上传非常有用
|
||
|
||
**示例:**
|
||
```nginx
|
||
# 允许 PUT /files/a/b/c/file.txt 自动创建 a/b/c/ 目录
|
||
create_full_put_path on;
|
||
```
|
||
|
||
---
|
||
|
||
### 2.3 dav_access
|
||
|
||
设置新创建的文件和目录的访问权限。
|
||
|
||
**语法:**
|
||
```nginx
|
||
dav_access users:permissions ...;
|
||
```
|
||
|
||
**默认值:** `user:rw`
|
||
|
||
**上下文:** `http`, `server`, `location`
|
||
|
||
**权限格式:**
|
||
```
|
||
user:permissions # 文件所有者权限
|
||
group:permissions # 组权限
|
||
all:permissions # 所有用户权限
|
||
```
|
||
|
||
**权限值:**
|
||
- `r` - 读
|
||
- `w` - 写
|
||
- `x` - 执行(目录为进入)
|
||
|
||
**示例:**
|
||
```nginx
|
||
# 默认:用户可读写
|
||
dav_access user:rw;
|
||
|
||
# 用户读写,组读,其他用户只读
|
||
dav_access user:rw group:r all:r;
|
||
|
||
# 用户完全权限,组读执行,其他无权限
|
||
dav_access user:rwx group:rx all:;
|
||
|
||
# 多组权限
|
||
dav_access group:rw all:r;
|
||
```
|
||
|
||
---
|
||
|
||
### 2.4 min_delete_depth
|
||
|
||
设置 DELETE 操作允许删除的最小路径深度。
|
||
|
||
**语法:**
|
||
```nginx
|
||
min_delete_depth number;
|
||
```
|
||
|
||
**默认值:** `0`
|
||
|
||
**上下文:** `http`, `server`, `location`
|
||
|
||
**说明:**
|
||
- 用于防止意外删除重要目录
|
||
- 路径深度计算以 `/` 分隔的元素数量
|
||
- 请求 URI 的元素数量必须 >= 设定值才能执行 DELETE
|
||
|
||
**示例:**
|
||
```nginx
|
||
# 至少需要 4 层深度才能删除
|
||
min_delete_depth 4;
|
||
|
||
# 允许删除:DELETE /users/00/00/name (4 层)
|
||
# 禁止删除:DELETE /users/00/00 (3 层)
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 配置示例
|
||
|
||
### 3.1 基础文件共享服务器
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name dav.example.com;
|
||
|
||
location / {
|
||
# 根目录
|
||
root /data/www;
|
||
|
||
# 临时文件目录(与根目录同一文件系统以获得最佳性能)
|
||
client_body_temp_path /data/client_temp;
|
||
|
||
# 启用 WebDAV 方法
|
||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||
|
||
# 允许创建中间目录
|
||
create_full_put_path on;
|
||
|
||
# 设置文件权限
|
||
dav_access group:rw all:r;
|
||
|
||
# 限制写操作的访问
|
||
limit_except GET {
|
||
allow 192.168.1.0/24;
|
||
deny all;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 只读文件服务器(带选择性上传)
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name files.example.com;
|
||
|
||
# 公共只读区域
|
||
location /public/ {
|
||
root /data/files;
|
||
dav_methods off; # 禁止写操作
|
||
autoindex on; # 启用目录列表
|
||
}
|
||
|
||
# 受限上传区域
|
||
location /uploads/ {
|
||
root /data/files;
|
||
dav_methods PUT DELETE;
|
||
dav_access user:rw;
|
||
|
||
# 仅允许特定 IP 上传
|
||
limit_except GET {
|
||
allow 10.0.0.0/8;
|
||
deny all;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 支持深度目录的上传服务
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name upload.example.com;
|
||
|
||
location /storage/ {
|
||
root /data/storage;
|
||
|
||
dav_methods PUT DELETE MKCOL;
|
||
create_full_put_path on; # 自动创建嵌套目录
|
||
dav_access user:rw group:r;
|
||
|
||
# 防止删除顶层目录
|
||
min_delete_depth 3;
|
||
|
||
# 限制请求体大小
|
||
client_max_body_size 100M;
|
||
|
||
# 限制写操作
|
||
limit_except GET PUT {
|
||
allow 192.168.0.0/16;
|
||
deny all;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.4 带认证的 WebDAV 服务
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name secure-dav.example.com;
|
||
|
||
location / {
|
||
root /data/secure;
|
||
|
||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||
create_full_put_path on;
|
||
dav_access user:rw;
|
||
|
||
# HTTP 基本认证
|
||
auth_basic "WebDAV Access";
|
||
auth_basic_user_file /etc/nginx/.dav_passwd;
|
||
|
||
# 限制客户端大小
|
||
client_max_body_size 500M;
|
||
}
|
||
}
|
||
```
|
||
|
||
生成密码文件:
|
||
```bash
|
||
htpasswd -c /etc/nginx/.dav_passwd username
|
||
```
|
||
|
||
### 3.5 带 SSL 的 WebDAV 服务器
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name dav.example.com;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl;
|
||
server_name dav.example.com;
|
||
|
||
ssl_certificate /etc/nginx/ssl/dav.crt;
|
||
ssl_certificate_key /etc/nginx/ssl/dav.key;
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
|
||
location / {
|
||
root /data/www;
|
||
|
||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||
create_full_put_path on;
|
||
dav_access user:rw group:r all:r;
|
||
|
||
client_max_body_size 1G;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 客户端使用指南
|
||
|
||
### 4.1 使用 curl
|
||
|
||
```bash
|
||
# 上传文件(PUT)
|
||
curl -T localfile.txt http://dav.example.com/remotefile.txt
|
||
|
||
# 创建目录(MKCOL)
|
||
curl -X MKCOL http://dav.example.com/newdir/
|
||
|
||
# 删除文件(DELETE)
|
||
curl -X DELETE http://dav.example.com/file.txt
|
||
|
||
# 复制文件(COPY)
|
||
curl -X COPY -H "Destination: http://dav.example.com/copy.txt" \
|
||
http://dav.example.com/original.txt
|
||
|
||
# 移动文件(MOVE)
|
||
curl -X MOVE -H "Destination: http://dav.example.com/moved.txt" \
|
||
http://dav.example.com/original.txt
|
||
|
||
# 带认证上传
|
||
curl -T file.txt -u username:password \
|
||
http://dav.example.com/file.txt
|
||
|
||
# 查看文件内容(GET)
|
||
curl http://dav.example.com/file.txt
|
||
|
||
# 列出目录内容(需要客户端支持 PROPFIND)
|
||
curl -X PROPFIND http://dav.example.com/
|
||
```
|
||
|
||
### 4.2 使用 cadaver(命令行 WebDAV 客户端)
|
||
|
||
```bash
|
||
# 安装
|
||
# Debian/Ubuntu
|
||
apt-get install cadaver
|
||
# macOS
|
||
brew install cadaver
|
||
|
||
# 连接
|
||
cadaver http://dav.example.com/
|
||
|
||
# cadaver 常用命令
|
||
dav:> ls # 列出目录
|
||
dav:> cd directory # 进入目录
|
||
dav:> put file.txt # 上传文件
|
||
dav:> get file.txt # 下载文件
|
||
dav:> mkdir newdir # 创建目录
|
||
dav:> rm file.txt # 删除文件
|
||
dav:> mv old new # 移动/重命名
|
||
dav:> quit # 退出
|
||
```
|
||
|
||
### 4.3 使用 GNOME Nautilus(文件管理器)
|
||
|
||
1. 打开 Nautilus 文件管理器
|
||
2. 按 `Ctrl+L` 或选择"其他位置"
|
||
3. 输入地址:`dav://dav.example.com/`
|
||
4. 输入凭据(如需要)
|
||
5. 可像本地文件夹一样操作
|
||
|
||
### 4.4 挂载为本地文件系统(Linux)
|
||
|
||
使用 davfs2:
|
||
|
||
```bash
|
||
# 安装
|
||
apt-get install davfs2
|
||
|
||
# 挂载
|
||
mount -t davfs http://dav.example.com/ /mnt/webdav
|
||
|
||
# 或使用 /etc/fstab 自动挂载
|
||
http://dav.example.com/ /mnt/webdav davfs user,noauto 0 0
|
||
```
|
||
|
||
### 4.5 Windows 资源管理器
|
||
|
||
1. 打开"此电脑"
|
||
2. 右键 -> "添加网络位置"
|
||
3. 输入:`http://dav.example.com/`
|
||
4. 完成向导
|
||
|
||
或使用 `net use`:
|
||
```cmd
|
||
net use * http://dav.example.com/
|
||
```
|
||
|
||
### 4.6 macOS Finder
|
||
|
||
1. Finder -> "前往" -> "连接服务器"
|
||
2. 输入:`http://dav.example.com/`
|
||
3. 点击"连接"
|
||
|
||
---
|
||
|
||
## 5. 与 Lolly 项目的关系
|
||
|
||
### 5.1 Lolly 项目概述
|
||
|
||
Lolly 是一个用 Go 编写的高性能 HTTP 服务器/代理工具,提供:
|
||
- 灵活的路由和重写规则
|
||
- 中间件支持
|
||
- 反向代理功能
|
||
- 性能分析工具(pprof)
|
||
|
||
### 5.2 与 Nginx WebDAV 的对比
|
||
|
||
| 特性 | Nginx WebDAV | Lolly |
|
||
|------|--------------|-------|
|
||
| 协议支持 | WebDAV (有限) | 标准 HTTP |
|
||
| 配置方式 | 声明式配置 | Go 代码 |
|
||
| 扩展性 | 需重新编译 | 热插拔中间件 |
|
||
| 性能分析 | 第三方模块 | 内置 pprof |
|
||
| 学习曲线 | 低 | 中(需 Go 基础) |
|
||
|
||
### 5.3 建议与集成方案
|
||
|
||
#### 方案一:Nginx + Lolly 组合架构
|
||
|
||
```
|
||
客户端 -> Nginx (WebDAV/静态文件) -> Lolly (动态请求/代理)
|
||
```
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name example.com;
|
||
|
||
# WebDAV 文件存储
|
||
location /dav/ {
|
||
root /data/storage;
|
||
dav_methods PUT DELETE MKCOL;
|
||
create_full_put_path on;
|
||
dav_access user:rw group:r;
|
||
}
|
||
|
||
# 动态请求代理到 Lolly
|
||
location /api/ {
|
||
proxy_pass http://localhost:8080;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# 静态文件由 Nginx 直接服务
|
||
location /static/ {
|
||
root /data/www;
|
||
expires 30d;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 方案二:Lolly 实现类似 WebDAV 功能
|
||
|
||
如需在 Lolly 中实现类似 WebDAV 的文件上传功能,可参考以下思路:
|
||
|
||
```go
|
||
// 概念示例 - 实际实现请参考 Lolly 代码
|
||
router.PUT("/files/*filepath", func(c *gin.Context) {
|
||
filepath := c.Param("filepath")
|
||
fullPath := "/data/storage/" + filepath
|
||
|
||
// 创建中间目录(类似 create_full_put_path on)
|
||
os.MkdirAll(path.Dir(fullPath), 0755)
|
||
|
||
// 保存上传的文件
|
||
c.SaveUploadedFile(file, fullPath)
|
||
|
||
// 设置权限(类似 dav_access)
|
||
os.Chmod(fullPath, 0644)
|
||
|
||
c.Status(http.StatusCreated)
|
||
})
|
||
|
||
router.DELETE("/files/*filepath", func(c *gin.Context) {
|
||
filepath := c.Param("filepath")
|
||
fullPath := "/data/storage/" + filepath
|
||
|
||
// 检查深度(类似 min_delete_depth)
|
||
depth := len(strings.Split(filepath, "/"))
|
||
if depth < 4 {
|
||
c.JSON(http.StatusForbidden, gin.H{"error": "path too shallow"})
|
||
return
|
||
}
|
||
|
||
os.Remove(fullPath)
|
||
c.Status(http.StatusNoContent)
|
||
})
|
||
```
|
||
|
||
#### 方案三:Lolly 作为 WebDAV 后端代理
|
||
|
||
```nginx
|
||
location /webdav/ {
|
||
# 认证和限流在 Nginx 层处理
|
||
auth_basic "WebDAV";
|
||
auth_basic_user_file /etc/nginx/.passwd;
|
||
|
||
# 限流
|
||
limit_req zone=webdav burst=10;
|
||
|
||
# 代理到 Lolly
|
||
proxy_pass http://localhost:8080;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header Destination $http_destination;
|
||
}
|
||
```
|
||
|
||
### 5.4 选择建议
|
||
|
||
| 场景 | 推荐方案 |
|
||
|------|----------|
|
||
| 简单文件共享 | Nginx WebDAV |
|
||
| 需要复杂业务逻辑 | Lolly |
|
||
| 高性能静态文件 | Nginx |
|
||
| 需要自定义协议扩展 | Lolly |
|
||
| 快速部署 | Nginx WebDAV |
|
||
| 深度集成应用 | Lolly |
|
||
|
||
---
|
||
|
||
## 6. 性能优化建议
|
||
|
||
### 6.1 文件系统建议
|
||
|
||
**强烈推荐**:临时目录和数据目录使用**同一文件系统**。
|
||
|
||
```nginx
|
||
location / {
|
||
root /data/www; # 数据目录
|
||
client_body_temp_path /data/client_temp; # 临时目录(同文件系统)
|
||
|
||
dav_methods PUT DELETE;
|
||
}
|
||
```
|
||
|
||
**原因:**
|
||
- 同文件系统:文件上传使用 `rename()` 系统调用(原子操作,极快)
|
||
- 不同文件系统:文件上传需要 `copy + delete`(慢,占用双倍空间)
|
||
|
||
### 6.2 客户端大小限制
|
||
|
||
```nginx
|
||
# 限制上传文件大小,防止资源耗尽
|
||
client_max_body_size 100M;
|
||
|
||
# 调整缓冲区
|
||
client_body_buffer_size 128k;
|
||
```
|
||
|
||
### 6.3 超时设置
|
||
|
||
```nginx
|
||
# WebDAV 操作可能需要较长时间
|
||
client_body_timeout 300s;
|
||
send_timeout 300s;
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 故障排查
|
||
|
||
### 7.1 常见问题
|
||
|
||
| 问题 | 可能原因 | 解决方案 |
|
||
|------|----------|----------|
|
||
| 405 Method Not Allowed | 方法未启用 | 检查 `dav_methods` 配置 |
|
||
| 403 Forbidden | 权限不足或 IP 限制 | 检查 `dav_access` 和 `limit_except` |
|
||
| 409 Conflict | 目录不存在 | 设置 `create_full_put_path on` |
|
||
| 423 Locked | 文件被锁定 | Nginx 不支持锁,换客户端 |
|
||
| 500 Internal Error | 路径过深或循环 | 检查 `min_delete_depth` |
|
||
|
||
### 7.2 启用调试日志
|
||
|
||
```nginx
|
||
error_log /var/log/nginx/error.log debug;
|
||
```
|
||
|
||
查看日志:
|
||
```bash
|
||
tail -f /var/log/nginx/error.log | grep dav
|
||
```
|
||
|
||
### 7.3 验证配置
|
||
|
||
```bash
|
||
# 测试配置文件语法
|
||
nginx -t
|
||
|
||
# 重新加载配置
|
||
nginx -s reload
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 完整配置模板
|
||
|
||
```nginx
|
||
# /etc/nginx/conf.d/webdav.conf
|
||
server {
|
||
listen 80;
|
||
server_name dav.example.com;
|
||
|
||
# 访问日志
|
||
access_log /var/log/nginx/webdav_access.log;
|
||
error_log /var/log/nginx/webdav_error.log;
|
||
|
||
# 客户端限制
|
||
client_max_body_size 500M;
|
||
client_body_buffer_size 128k;
|
||
client_body_timeout 300s;
|
||
send_timeout 300s;
|
||
|
||
location / {
|
||
# 根目录
|
||
root /data/webdav;
|
||
|
||
# 临时目录(与根目录同文件系统)
|
||
client_body_temp_path /data/webdav_tmp;
|
||
|
||
# 启用 WebDAV 方法
|
||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||
|
||
# 允许自动创建中间目录
|
||
create_full_put_path on;
|
||
|
||
# 文件权限设置
|
||
dav_access user:rw group:r all:r;
|
||
|
||
# 防止误删顶层目录
|
||
min_delete_depth 2;
|
||
|
||
# HTTP 基本认证
|
||
auth_basic "WebDAV Repository";
|
||
auth_basic_user_file /etc/nginx/.webdav_passwd;
|
||
|
||
# 访问控制
|
||
limit_except GET {
|
||
# 允许内网
|
||
allow 192.168.0.0/16;
|
||
allow 10.0.0.0/8;
|
||
allow 127.0.0.1;
|
||
# 拒绝其他
|
||
deny all;
|
||
}
|
||
|
||
# 目录列表(可选)
|
||
autoindex on;
|
||
autoindex_format html;
|
||
autoindex_localtime on;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 参考资源
|
||
|
||
- [Nginx 官方文档 - ngx_http_dav_module](https://nginx.org/en/docs/http/ngx_http_dav_module.html)
|
||
- [WebDAV RFC 4918](https://tools.ietf.org/html/rfc4918)
|
||
- [cadaver 客户端](http://www.webdav.org/cadaver/)
|
||
- [davfs2 - Linux WebDAV 挂载](http://savannah.nongnu.org/projects/davfs2/)
|