
最近在整理家里那台 NAS 和几台云主机上的文件共享方案时我又把Dufs 文件服务器翻出来重新梳理了一轮。Dufs 是那种用一次就会爱上的小工具Rust 写的编译出来就一个二进制文件不装运行环境、不依赖数据库扔到任意一台 x86/ARM 机器上都能跑默认 Web 界面干净但确实朴素。这次我顺手把dufs-material-assets 美化主题集成进去界面直接跳了一个档次手机浏览器上访问列表文件也舒服多了。这篇围绕 Dufs 的部署和主题美化展开二进制和 Docker 两条路都走一遍再分享实际部署中遇到的那些坑适合准备搭内网文件服务、NAS 文件管理或者临时给外部发文件链接的朋友参考。1. Dufs 的定位这就是为快速共享文件准备的轻量服务1.1 Dufs 到底解决了什么问题Dufs 的全称是 Dumb Utility File Server翻译过来就是傻瓜式文件服务器。它的核心诉求非常直接用一个最简单的办法把某个目录变成可以随时访问的文件服务。我们家用的 NAS 场景里SMB/NFS 虽然好用但手机端、同事的笔记本、临时访客访问起来并不方便要么装客户端要么折腾局域网发现。Dufs 跑起来之后浏览器打开 IP:5000 就能看到目录结构文件点一下就能下载支持续传还能直接在网页上拖拽上传。这种感觉比在一堆协议配置里打滚要清爽太多。它实际覆盖的场景大概是这几类给手机、平板提供一个不需要装 App 的网页文件入口把服务器上的构建产物、安装包快速分享给客户或同事给个链接即可需要 WebDAV 协议挂载远程目录方便本机同步和编辑一家人或者小团队共享文档、电影、照片但不想为了这点需求去部署一套完整的云盘系统。Dufs 在这些场景下非常能打。它内置 HTTP 访问和 WebDAV 支持自带基本认证还能按目录配置读写权限支持搜索、目录打包下载、Markdown 和 PDF 在线预览等功能。一个不到 10MB 的二进制文件干完这么多事很难不让喜欢折腾的人心动。1.2 和 nginx autoindex、filebrowser、miniserve 的取舍很多朋友可能会问我本来就有 nginx开个 autoindex 不也能看目录吗或者为啥不直接用 filebrowser我拿常见的几个方案做个对比方案优势劣势适合场景nginx autoindex性能好无需额外组件只读为主上传要单独配权限控制麻烦单纯对外静态下载Caddy file_server配 HTTPS 极简动态上传、删除功能弱只读站点miniserve单二进制简单功能过于基础权限/WebDAV 欠缺临时传文件filebrowser功能全面界面友好带数据库和完整用户体系偏重多用户管理场景Dufs单二进制轻量权限灵活内置 WebDAV界面默认朴素但可换主题轻量共享、NAS、临时分发我当时的选型逻辑很明确filebrowser 确实界面不错但它的用户系统和数据库对一台小 NAS 来说有点杀鸡用牛刀nginx autoindex 只读没问题可一旦需要上传、WebDAV 就麻烦起来。Dufs 正好卡在中间——不需要数据库不需要额外运行时但该有的文件操作能力都有。1.3 什么场景不建议用 Dufs我也得泼点冷水。Dufs 再轻量也不是万能的。如果你需要的是多个用户分角色管理每个人有自己的目录配额、操作审计、回收站和版本历史那 Dufs 就不太合适了这种需求老老实实上 Seafile 或者 Nextcloud 更稳。如果团队需要在线协同编辑 Office 文档Dufs 也干不了它只能做基础的 Markdown/PDF 预览。还有一点需要注意的是Dufs 的权限模型是路径 权限位比 filebrowser 灵活但也意味着精细到每个用户只见自己那一片目录时需要多写几条 auth 规则。好在多数个人场景根本用不到那么复杂的模型。总之Dufs 的定位就是轻量两个字。需求一旦超出轻量共享就不要硬上选型时清楚边界后面维护起来才不闹心。2. 基础部署二进制与 Docker Compose 两条路线一次跑通2.1 二进制安装下载、解压、最简启动Dufs 的部署方式非常简单因为它本身就是单文件。以 Linux x86_64 为例我从 GitHub Releases 页面下载对应压缩包wget https://github.com/sigoden/dufs/releases/latest/download/dufs-x86_64-unknown-linux-musl.tar.gz tar -zxvf dufs-x86_64-unknown-linux-musl.tar.gz sudo mv dufs /usr/local/bin/ dufs --version这里我特意选了 musl 静态编译版它在哪个发行版上都能直接跑不会出现 glibc 版本导致的兼容问题。如果你要部署到树莓派、电视盒子或者 RK3588 那类 ARM 设备上记得下载aarch64对应的包。最简启动就一条命令mkdir -p /srv/files dufs /srv/files --bind 0.0.0.0 --port 5000 --allow-all--bind 0.0.0.0表示监听所有网卡--port 5000是默认端口--allow-all相当于一次打开上传、删除、搜索所有权限。浏览器访问http://服务器IP:5000就能看到目录列表了。要注意的是--allow-all这种参数我一般在本地调试才用。真实环境我建议按需放开比如只开后台上传和搜索删除权限保持关闭避免误操作把目录清空。2.2 用 systemd 把 Dufs 托管为常驻服务手动敲命令跑起来的进程终端一关就没了。为了让它常驻我写了 systemd 单元文件这块是实际部署中很容易漏掉的一步。[Unit] DescriptionDUFS File Server Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple ExecStart/usr/local/bin/dufs /srv/files --bind 0.0.0.0 --port 5000 --assets /opt/dufs-assets --allow-upload --allow-search Restarton-failure RestartSec3 [Install] WantedBymulti-user.target把它保存到/etc/systemd/system/dufs.service然后执行sudo systemctl daemon-reload sudo systemctl enable --now dufs sudo systemctl status dufs这里的 ExecStart 我已经把--assets /opt/dufs-assets加进去了也就是后面第三节要讲的主题资源目录。实际部署时建议先把这一行加上免得服务跑起来后还要改配置重启两遍。2.3 Docker Compose 部署参数对应的完整清单如果你和我一样NAS 或者云主机上已经跑着一堆 Docker 容器那用 Docker Compose 统一管理更省心。下面是一个我实际在用的 compose 文件services: dufs: image: sigoden/dufs:latest container_name: dufs restart: unless-stopped ports: - 5000:5000 volumes: - ./files:/data - ./dufs-assets:/assets:ro command: - /data - --bind - 0.0.0.0 - --port - 5000 - --assets - /assets - --allow-upload - --allow-search这份配置里宿主机的./files目录对应容器内的/data./dufs-assets以只读方式挂载到/assets并通过--assets /assets告诉 Dufs 使用外部 UI 资源。之所以把 assets 单独挂载而不是打进镜像是因为主题资源更新时只需要替换宿主机目录不必重建容器。启动命令同样简单docker compose up -d docker compose logs -f dufs需要注意容器网络里绑定的 IP 指的是容器自己的网卡所以写0.0.0.0即可。真正对外生效的是ports这一段宿主机的 5000 端口会被转发到容器内。2.4 常用参数速查部署时要认清楚的几个选项Dufs 的参数不算多但每个都很关键。我把部署时最常用的几个整理成了一张速查表方便配置时对照参数作用常用示例--bind监听地址--bind 0.0.0.0--port监听端口--port 5000--root根目录的位置参数dufs /srv/files--auth认证规则可多次指定--auth admin:pass/:rw--assets自定义 Web UI 资源目录--assets /opt/dufs-assets--readonly全局只读不需要上传时使用--allow-upload允许上传按需开启--allow-delete允许删除慎用--allow-search允许搜索文件多了建议开--download-zip支持目录打包下载分发大目录时好用--webdav启用 WebDAV挂载网络磁盘用--hidden隐藏指定路径--hidden .git--log-file写日志到文件/var/log/dufs.log--tls-cert/--tls-key直接启用 HTTPS一般交给反代我建议第一次上手时不要用--allow-all从需求出发逐个放开权限对权限模型的理解也会更清楚。3. 集成 dufs-material-assets 主题原理、步骤与生效验证3.1 Dufs 支持自定义 UI 的机制--assets 到底做了什么先理解一件事Dufs 的 Web 界面本质上就是一组前端静态资源包括index.html、CSS、JS、图标等文件。这些资源在编译时被打包进了二进制里所以你第一次打开页面看到的那个朴素界面其实就是这组静态资源被 Dufs 读取后返回给浏览器的结果。--assets参数的作用是让 Dufs 启动时优先从外部目录读取同名资源如果外部目录里有index.html就直接用它如果没有才回落到内置资源。这就给了我们换肤的空间——只要准备一套符合 Dufs 页面逻辑的自定义前端资源就能彻底改变界面外观不需要改任何 Rust 代码。dufs-material-assets 这套主题就是这样工作的。它把 Dufs 默认的界面替换成 Material Design 风格列表变成了卡片式文件图标更清晰面包屑导航、搜索框、上传按钮的布局全部重排过还对移动端做了较好的适配。做 NAS 文件分享手机上访问频率其实挺高默认界面在小屏上显示得比较拥挤换这套主题后体验提升非常明显。3.2 下载并摆好 dufs-material-assets 资源目录获取主题资源的方式取决于项目的 Release 方式一般是从项目仓库的 Release 页面下载打包好的静态目录或者直接 clone 仓库。下载下来后我把资源解压到服务器上固定的位置mkdir -p /opt/dufs-assets tar -zxvf dufs-material-assets.tar.gz -C /opt/dufs-assets --strip-components1这里的关键一点是目录结构。Dufs 读取外部资源时找的是index.html 所在的那一层目录。所以解压完成后请检查一下ls -la /opt/dufs-assets正常情况下应该能直接看到index.html文件而不是套在里面一层文件夹里。如果看到的是一个名为dist或build之类的子目录那就需要把路径往下指一层指向真正包含index.html的那个目录。我见过不少朋友在这一步踩坑把--assets写到了上一级目录结果 Dufs 找不到index.html界面直接白屏。目录层级搞对后面就顺了。3.3 启动参数挂载与两种验证方式二进制部署时把 assets 路径加到启动命令里dufs /srv/files \ --bind 0.0.0.0 \ --port 5000 \ --assets /opt/dufs-assets \ --allow-upload \ --allow-search如果你用等已经写好 systemd 单元的版本直接重启服务即可sudo systemctl restart dufsDocker Compose 部署时我在前面的 compose 文件里已经带上了挂载和参数直接执行docker compose up -d就行。验证主题是否生效我一般用两种方式第一种命令行快速验证看返回的 HTML 里是否包含主题的特征内容curl -s http://127.0.0.1:5000/ | head -n 20如果返回的 HTML 里出现了 Material 风格特有的 class 名或者主题资源文件名就说明加载的是自定义资源而不是内置界面。第二种浏览器强制刷新。由于浏览器可能会缓存旧页面的 CSS/JS 文件按Ctrl F5或Cmd Shift R强制刷新一次看到卡片式界面基本就成功了。4. 认证、WebDAV 与 Nginx 反代把这台文件服务真正用起来4.1 账号认证与只读覆盖--auth 权限规则写法文件服务跑起来之后第一个要解决的问题就是权限。Dufs 的--auth参数支持按路径配置多组账号格式大致是用户名:密码路径:权限权限位包括读取、上传、删除等。例如dufs /srv/files --bind 0.0.0.0 --port 5000 \ --auth admin:ChangeMe/:rw \ --auth guest:guest123/public:r \ --allow-search这条命令里admin对整个根目录有读写权限guest账号只能访问/public目录且只有读取权限既不也能上传也不能删除。加上--allow-search后所有有读权限的用户都可以搜索可见范围内的文件。这里说一个容易误操作的地方如果--readonly存在所有写操作会被全局禁用这时候即使某个账号配置了w权限也无效。反过来如果你希望某些目录只读、某些目录可写那就不要用--readonly而是用不同账号对不同路径给不同权限位。这样设计的好处是公网访客账号可以只给r自己管理账号给rw从根上降低风险。4.2 开启 WebDAV把文件服务变成网络磁盘Dufs 原生支持 WebDAV这是一个我很看重的能力。在启动命令中加上--webdav文件服务就同时变成了一个网络磁盘dufs /srv/files --webdav --auth admin:ChangeMe/:rwLinux 客户端可以用 davfs2 挂载sudo apt install davfs2 sudo mkdir -p /mnt/dufs sudo mount -t davfs http://127.0.0.1:5000/ /mnt/dufsWindows 里直接在添加网络位置里填http://IP:5000或者https://域名/就能挂载。macOS 的 Finder 里按Cmd K输入服务地址即可。有了 WebDAV 之后Dufs 不只是浏览器里点着玩的工具了。我可以在本机上把 NAS 目录挂载成一个盘符IDE 直接打开远程文件编辑也能用脚本定期往里同步备份文件。文件内容变更后浏览器访问同一个地址看到的就是最新状态无需额外同步逻辑。4.3 Nginx 反向代理与 HTTPS对外暴露前的标准操作我不太推荐把 5000 端口直接暴露到公网一个习惯性做法是统一走 Nginx 反向代理把 TLS 终结在 Nginx 这一层。这样既不需要 Dufs 自己处理证书也方便以后做访问控制和统一入口。以下是我常用的 Nginx 站点配置server { listen 443 ssl; server_name files.example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; client_max_body_size 0; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }client_max_body_size 0这一项别漏了Nginx 默认只允许请求体最大 1MB如果不放开大文件上传就会直接报 413。实际场景中传几个 GB 的安装包很常见这个参数至关重要。证书获取可以用 Lets Encrypt配合 certbot 自动续期整体维护成本很低。反代配置好之后Dufs 端只需要监听127.0.0.1:5000就够了不要直接暴露在所有网卡上。5. 实测避坑记录主题白屏、大文件断传与安全底线5.1 主题不生效或白屏先按这个顺序排查集成主题看起来简单但我在实际操作中确实遇到过几次白屏和小问题这里把排查顺序列出来照着走基本能解决。第一确认--assets参数指向的目录直接包含index.html。这是最常见的原因层级错一层就会白屏。检查命令ls /opt/dufs-assets/index.html第二启动日志里有没有报错。二进制运行时直接看终端输出systemd 部署用journalctl -u dufs -n 50Docker 用docker logs dufs。如果 Dufs 告诉你找不到资源目录多半是路径拼错。第三浏览器缓存。旧界面的 CSS/JS 文件可能被浏览器缓存了强制刷新一次再判断。第四主题资源与 Dufs 版本的兼容性。一些新主题利用的 Dufs 内部接口字段如果在新版本里变了可能表现出白屏或者功能按钮点击无效。这时候看一下 dufs-material-assets 项目说明里支持哪一版本的 Dufs把 Dufs 锁定到指定版本即可。为了避免升级引起问题我在 systemd 或 compose 里都写死了具体镜像版本标签而不是用latest。5.2 大文件上传断传与 Docker 卷权限大文件上传遇到的坑绝大多数不在 Dufs 本身而在它前面的代理层。直连 5000 端口时Dufs 对上传大小基本没有限制但一旦走了 Nginx就必须处理我之前说的client_max_body_size。还有超时配置大文件上传耗时较长建议在 Nginx 里同时调大几个超时时间proxy_read_timeout 600s; proxy_send_timeout 600s;这样在弱网环境下传大文件不会因为读超时被 Nginx 主动掐断连接。另一个常见问题出现在 Docker 部署时容器内进程对挂载卷没有写权限。表现是网页上传按钮点了没反应或者报错提示无法创建文件。原因通常是宿主机./files目录的属主和容器内进程的用户不一致。解决办法很简单先把目录属主调整到与容器运行用户一致或者直接给目录放宽权限并保证容器能够写入sudo chown -R 1000:1000 ./files不同镜像的默认用户不一样最稳妥的办法是在项目文档里确认运行用户。如果容器跑不要求强隔离的家中场景直接在 compose 里user: root能让问题消失但公网环境下不建议这么干。还有一点--allow-delete我给所有在线用户都不开。实际上我远程管理时也不需要网页删除真要清理文件时 SSH 上去执行命令比误点删除安全太多。5.3 公网部署的安全底线清单最后聊一下安全。文件服务一旦暴露到公网就是攻击者的重点观察对象以下几条是我每次部署都会检查的清单。第一绝对不要直接dufs / --allow-all把整个文件系统挂出去。Dufs 的根目录应该是一个专门的共享目录里面只放需要对外暴露的内容。敏感文件即使在同一台机器上只要不在根目录里也不会被扫描到。第二使用--hidden把点文件和敏感子目录藏起来dufs /srv/files --hidden .* --hidden backup第三账号密码尽量用强密码并且每个场景单独建账号不要全世界共用一个 admin。--auth支持多账号给公网访客只读账号给自己读写账号这种方式比一刀切的全局密码要稳很多。第四启用日志记录。加上--log-file /var/log/dufs.log事后排查访问痕迹时非常有用。第五按时升级。Dufs 更新频率不算低安全修复和功能改进都在里面。升级前先看一眼 Release Notes重点确认没有破坏性变更再看一眼主题资源的兼容说明。我记得一次踩坑就是因为 Nginxclient_max_body_size没调整客户传一个 3GB 的数据库备份文件折腾了半天都失败一开始还怀疑是 Dufs 的 bug最后抓包才发现是反代层拦截了。所以排查问题时一定记得把链路完整看一遍不要只盯着 Dufs 本体。现在我这套 Dufs 文件服务器已经稳定跑了一段时间家里 NAS 上用 Docker Compose 管理端口固定 5000内网直接访问不去套认证云主机上的实例则反代 HTTPS只读开放一个专门目录其他路径全部隐藏。集成 dufs-material-assets 主题后手机端访问的频次明显变高了这大概就是界面改进带来的实际效果。如果你也打算把 Dufs 用起来我的建议是第一遍搭的时候就把主题 assets 单独放在一个固定目录和二进制、systemd 配置分开之后升级维护会轻松很多。