扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

用 Nginx 做文件服务器大材小用?试试 Dufs:相当于给你的服务器装上“网盘+搜索”

1小时前
181
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

大家好,我是 WeiyiGeek,一名深耕安全运维开发(SecOpsDev)领域的技术从业者,致力于探索DevOps与安全的融合(DevSecOps),自动化运维工具开发与实践,企业网络安全防护,欢迎各位道友一起学习交流、一起进步 ,若此文对你有帮助,一定记得点个关注⭐与小红星❤️或加入到作者知识星球『 全栈工程师修炼指南』,转发收藏学习不迷路  。

前言简述

由于 Ingress NGINX 将在2026年3月正式退役,因此,我们迫切需要寻找替代方案。在众多选项中,我们还是选择了 OpenResty 作为替代方案。OpenResty 是一个基于 NGINX 与 LuaJIT 的高性能 Web 平台,它通过将 NGINX 和 Lua 语言相结合,提供了强大的动态网页处理能力,并利用 Kubernetes 集群进行管理以及横向扩容。

此外,我们原本使用 Nginx 单独部署一个静态文件服务器,然后使用 Ingress NGINX 暴露在互联网中作为 CDN 回源服务器,先在由于使用 OpenResty 作为网关入口,所以就不需要再部署一个 Nginx 服务了,因此我们也需要寻找一个高性能的静态文件服务器,

通过在 Google 以及查阅相关资料后,我们发现了一个名为 Dufs 的独特实用文件服务器。它支持静态服务、上传、搜索、访问控制以及 WebDAV 等功能。值得一提的是,Dufs 是一个基于 Rust 语言开发的轻量级文件服务器,具有高性能和低资源消耗的特点,所以最终选择使用 Dufs 作为静态文件服务器,然后通过 OpenResty 作为反向代理,暴露给 CDN 作为回源服务器。

好了,话不多说,接下来将详细介绍如何在 Linux 二进制部署,以及在 Kubernetes 集群中部署 Dufs 作为静态文件服务器。

温馨提示:若文章代码块中存在乱码或不能复制,请联系作者,也可通过文末的阅读原文链接,加入知识星球中阅读,原文链接:https://articles.zsxq.com/id_3ezswe14oru4.html

0x01 dufs 基于 Rust 高性能静态文件服务器

dufs 是什么?

Dufs 是一个独特的实用文件服务器,使用 Rust 语言开发拥有高性能和低资源消耗特点,支持静态服务(前端项目),上传,搜索,访问控制,webdav 挂载,可以非常方便的管理(CURD)服务器上的文件。

dufs 主要特性:

    • 服务静态文件• 下载文件夹为zip文件• 上传文件和文件夹(拖放)• 创建/编辑/搜索文件• 可恢复/部分上传/下载• 访问控制• 支持https• 支持webdav• 支持api调用,方便curl使用

weiyigeek.top-Dufs文件服务器工具图

项目地址:https://github.com/sigoden/dufs/

dufs 快速上手

通过官方文档,我们可以快速上手使用 Dufs 作为静态文件服务器,可以通过以下命令快速启动 Dufs 服务:

# Binary 安装
mkdir /opt/dufs && cd /opt/dufs
wget https://github.com/sigoden/dufs/releases/download/v0.45.0/dufs-v0.45.0-x86_64-unknown-linux-musl.tar.gz 
tar -zxvf dufs-v0.45.0-x86_64-unknown-linux-musl.tar.gz
ls# dufs  dufs-v0.45.0-x86_64-unknown-linux-musl.tar.gz
ln -s /opt/dufs/dufs /usr/local/bin/dufs
dufs --version  # dufs 0.45.0
dufs /var/www/html/ -b 0.0.0.0 -p 5000 -A 

# 容器安装
docker run -v /var/www/html/:/www -p 5000:5000 --rm sigoden/dufs /www -A

 

语法参数

$ dufs --help
Usage: dufs [OPTIONS] [serve-path]
Arguments:
  [serve-path]  # 指定服务目录,默认为当前工作目录 .
Options:
  -c, --config <file>        # 指定配置文件路径
  -b, --bind <addrs>         # 指定网卡地址
  -p, --port <port>          # 指定服务端口 [default: 5000]
      --path-prefix <path>   # 指定路径前缀, e.g. /my-prefix
      --hidden <value>       # 指定隐藏目录, e.g. tmp,*.log,*.lock
  -a, --auth <rules>         # 指定认证及权限, e.g. user:pass@/dir1:rw,/dir2 ,可指定多个 -a 
  -A, --allow-all            # 允许所有操作权限
      --allow-upload         Allow upload files/folders
      --allow-delete         Allow delete files/folders
      --allow-search         Allow search files/folders
      --allow-symlink        Allow symlink to files/folders outside root directory
      --allow-archive        Allow download folders as archive file
      --enable-cors          Enable CORS, sets `Access-Control-Allow-Origin: *`
      --render-index         # 请求目录时提供index.html,如果找不到index.html,则返回404
      --render-try-index     # 请求目录时提供index.html,如果找不到index.html,则返回目录列表
      --render-spa           # 启用单页应用模式,即不渲染目录列表 (静态站点使用)
      --assets <path>        # 设置 assets 目录覆盖内置
      --log-format <format>  # 自定义日志格式,例如:'$time_local - $remote_addr "$request" $status'
      --log-file <file>      # 自定义日志文件路径,例如:/var/log/dufs.log
      --compress <level>     Set zip compress level [default: low] [possible values: none, low, medium, high]
      --completions <shell>  # 打印 Shell [possible values: bash, elvish, fish, powershell, zsh]
      --tls-cert <path>      # 指定证书路径,例如:/etc/ssl/certs/server.crt
      --tls-key <path>       # 指定密钥路径,例如:/etc/ssl/private/server.key
  -h, --help                 Print help
  -V, --version              Print version

在 --config 参数中,可以指定配置文件路径,配置文件参数如下:

serve-path: '.'
bind: 0.0.0.0
port: 5000
path-prefix: /dufs
hidden:
  - tmp
  - '*.log'
  - '*.lock'
auth:
  - admin:admin@/:rw
  - user:pass@/src:rw,/share
  - '@/'# According to the YAML spec, quoting is required.
allow-all: false
allow-upload: true
allow-delete: true
allow-search: true
allow-symlink: true
allow-archive: true
allow-hash: true
enable-cors: true
render-index: true
render-try-index: true
render-spa: true
assets: ./assets/
log-format: '$remote_addr "$request" $status $http_user_agent'
log-file: ./dufs.log
compress: low
tls-cert: tests/data/cert.pem
tls-key: tests/data/key_pkcs1.pem

在脚本/容器中还可通过环境变量进行配置,参数选项与环境变量(以 DUFS_ 前缀打头)对应关系如下:

[serve-path]                DUFS_SERVE_PATH="."
    --config <file>         DUFS_CONFIG=config.yaml
-b, --bind <addrs>          DUFS_BIND=0.0.0.0
-p, --port <port>           DUFS_PORT=5000
    --path-prefix <path>    DUFS_PATH_PREFIX=/dufs
    --hidden <value>        DUFS_HIDDEN=tmp,*.log,*.lock
-a, --auth <rules>          DUFS_AUTH="admin:admin@/:rw|@/"
-A, --allow-all             DUFS_ALLOW_ALL=true
    --allow-upload          DUFS_ALLOW_UPLOAD=true
    --allow-delete          DUFS_ALLOW_DELETE=true
    --allow-search          DUFS_ALLOW_SEARCH=true
    --allow-symlink         DUFS_ALLOW_SYMLINK=true
    --allow-archive         DUFS_ALLOW_ARCHIVE=true
    --allow-hash            DUFS_ALLOW_HASH=true
    --enable-cors           DUFS_ENABLE_CORS=true
    --render-index          DUFS_RENDER_INDEX=true
    --render-try-index      DUFS_RENDER_TRY_INDEX=true
    --render-spa            DUFS_RENDER_SPA=true
    --assets <path>         DUFS_ASSETS=./assets
    --log-format <format>   DUFS_LOG_FORMAT=""
    --log-file <file>       DUFS_LOG_FILE=./dufs.log
    --compress <compress>   DUFS_COMPRESS=low
    --tls-cert <path>       DUFS_TLS_CERT=cert.pem
    --tls-key <path>        DUFS_TLS_KEY=key.pem

 

在 --log-format 参数中日志格式可以使用以下变量及其效果展示,缺省情况下输出到控制台。

$remote_addr 	client address
$remote_user 	user name supplied with authentication
$request 	full original request line
$status 	response status
$http_ 	  arbitrary request header field. examples: $http_user_agent, $http_referer

$ dufs --log-format '$remote_addr "$request" $status'
# 2026-03-14T09:49:13+08:00 INFO - 10.20.172.103 "GET /css/style.css" 304

$ dufs --log-format '$remote_addr "$request" $status $http_user_agent'
# 2026-03-14T10:53:55+08:00 INFO - 127.0.0.1 "GET /" 200 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36

 

快速启动(开发测速环境)

# 缺省:以只读模式服务当前工作目录
dufs

# 允许所有操作,如上传/删除/搜索/创建/编辑.
dufs -A

# 直接运行,指定监听接口以及端口
./dufs /usr/local/nginx/html/ -b 10.20.172.213 -p 5000
Listening on http://10.20.172.213:5000/

# 或使用环境变量
export DUFS_PORT=8080
export DUFS_BIND=0.0.0.0
dufs /usr/local/nginx/html/

# 直接运行,指定监听 unix socket 接口
dufs -b /tmp/dufs.socket

# 或利用 Shell 脚本运行,示例脚本中指定了隐藏目录,指定认证规则,以及日志格式。
tee dufs_server.sh <<'EOF'
STATIC_DIR="/usr/local/nginx/html/"
HOST="0.0.0.0"
PORT="5000"
LOG_FILE="/var/log/dufs.access.log"
AUTH_RULES="admin:123456@/:rw"

dufs $STATIC_DIR 
  --bind$HOST 
  --port $PORT 
  --log-file $LOG_FILE 
  --log-format '$remote_addr "$request" $status' 
  --render-index 
  --render-try-index 
  --hidden '.*,*.lock,*.tmp,' 
  --auth $AUTH_RULES
EOF

weiyigeek.top-dufs文件服务器图

使用 systemd 管理启动(生产环境)

步骤 01. 创建 dufs 服务用户,创建并设置其相关目录, 作者将自己主页站点放在 /var/www/html/ 目录下。

# 创建 dufs 用户
useradd dufs --no-create-home --shell /usr/sbin/nologin

# 创建配置目录、工作目录、日志目录
mkdir -pv /etc/dufs
mkdir -pv /var/log/dufs
mkdir -pv /var/www/html/

# 将静态文件移动到工作目录(模拟)
cp -a /usr/local/nginx/html/* /var/www/html/

 

步骤 02.创建 /etc/dufs/config.yaml 并写入以下内容,设置了隐藏文件规则。

tee /etc/dufs/config.yaml <<'EOF'
serve-path: /var/www/html
bind: 0.0.0.0
port: 5000
path-prefix: /
hidden:
  - tmp
  - .git
  - '*.gitignore'
  - '*.log'
  - '*.lock'
auth:
  - user01:123456@/:rw
  - user02:123456@/css:rw,/js:rw
allow-all: false
allow-upload: true
allow-delete: true
allow-search: true
allow-symlink: true
allow-archive: true
allow-hash: true
# enable-cors: true
# render-index: true
render-try-index: true
# render-spa: true
# assets: ./assets/
log-format: '$remote_addr "$request" $status $http_user_agent'
log-file: /var/log/dufs/access.log
compress: low
# tls-cert: tests/data/cert.pem
# tls-key: tests/data/key_pkcs1.pem
EOF

# 权限设置
chown -R dufs:dufs /etc/dufs /var/log/dufs /var/www/html/

 

步骤 03.创建 /etc/systemd/system/dufs.service 文件,并写入以下内容。

tee /etc/systemd/system/dufs.service <<'EOF'
[Unit]
Description=Dufs Static File Server
After=network.target

[Service]
Type=simple
User=dufs
Group=dufs
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/dufs --config /etc/dufs/config.yaml
Restart=always
RestartSec=10

# 安全限制
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/log/dufs
ReadOnlyPaths=/var/www/html/data

[Install]
WantedBy=multi-user.target
EOF

步骤 04.重载 systemd 配置并使用其进行管理服务。

# 重新加载 systemd 配置文件,使之生效
sudo systemctl daemon-reload

# 开机自启用 systemd 服务
sudo systemctl enable dufs --now

# 启动&停止
sudo systemctl start|stop dufs

步骤 05.查看服务状态,如果服务正常使用浏览器访问 http://ip:5000 即可。

# 查看状态
sudo systemctl status dufs

# 查看日志
sudo journalctl -u dufs -f

# 访问日志
tail -f /var/log/dufs/access.log

weiyigeek.top-dufs使用实践图

dufs 容器化部署

由于我们业务都在 K8s 集群中运行,单独在一台物理机或者虚拟机中运行也不现实,所以这里也顺便演示一下如何在 K8s 集群中部署 dufs 服务,用于在流量高峰时开启 CDN 回源使用,流量低估时直接提供访问。

这里如何搭建 K8S 集群及相关知识就不赘述了,在作者知识星球全栈工程师修炼指南】中有详细介绍,有兴趣的看友可以去瞅瞅。

实践演示

步骤 01.从 Docker Hub 拉取 sigoden/dufs 镜像,或者在本地构建,可以看到镜像大小很小,仅有几兆左右,与 Nginx 镜像相比 dufs 镜像可以说是非常轻量级,当前最新版本为 v0.45.0。

docker pull sigoden/dufs:v0.45.0
docerk tag sigoden/dufs:v0.45.0 hub.weiyigeek.top/library/sigoden/dufs:v0.45.0
docker push hub.weiyigeek.top/library/sigoden/dufs:v0.45.0

weiyigeek.top-sigoden/dufs图

步骤 02.建议使用 Deployment 或者 Statesfulset 在容器中可使用环境变量进行配置。

# 创建名称空间kubectl create ns app# 部署清单tee dufs-deploy.yaml <<'EOF'apiVersion: v1kind: Servicemetadata:  name: web-cdn  namespace: app  annotations:    ops.k8s.io/name: web-cdn    ops.k8s.io/desc: 综合项目-存放公共CDN静态资源文件    ops.k8s.io/type: frontend-web    ops.k8s.io/url: https://cdn.weiyigeek.top    ops.k8s.io/git: https://git.weiyigeek.top/pub/web-cdn  labels:    app: web-cdn    type: web    role: frontendspec:  externalTrafficPolicy: Cluster  ports:  - name: http    port: 8080    protocol: TCP    targetPort: 8080  selector:    app: web-cdn    type: web    role: frontend  type: NodePort---apiVersion: apps/v1kind: StatefulSetmetadata:  name: web-cdn  namespace: app  annotations:    ops.k8s.io/name: web-cdn    ops.k8s.io/desc: 综合项目-存放公共CDN静态资源文件    ops.k8s.io/type: frontend-web    ops.k8s.io/url: https://cdn.weiyigeek.top    ops.k8s.io/git: https://git.weiyigeek.top/pub/web-cdn  labels:    app: web-cdn    type: web    role: frontendspec:  replicas: 1  selector:    matchLabels:      app: web-cdn      type: web      role: frontend  serviceName: web-cdn  template:    metadata:      annotations:        ops.k8s.io/name: web-cdn        ops.k8s.io/desc: 综合项目-存放公共CDN静态资源文件        ops.k8s.io/type: frontend-web        ops.k8s.io/url: https://cdn.weiyigeek.top        ops.k8s.io/git: https://git.weiyigeek.top/pub/web-cdn      labels:        app: web-cdn        type: web        role: frontend    spec:      affinity:        nodeAffinity:          requiredDuringSchedulingIgnoredDuringExecution:            nodeSelectorTerms:            - matchExpressions:              - key: kubernetes.io/os                operator: In                values:                - linux        podAntiAffinity:          preferredDuringSchedulingIgnoredDuringExecution:          - podAffinityTerm:              labelSelector:                matchExpressions:                - key: app                  operator: In                  values:                  - web-cdn              topologyKey: kubernetes.io/hostname            weight: 100      containers:      - name: app        image: hub.weiyigeek.top/library/sigoden/dufs:v0.45.0        imagePullPolicy: IfNotPresent        env:        - name: TZ          value: Asia/Shanghai        - name: DUFS_BIND          value: "0.0.0.0"        - name: DUFS_SERVE_PATH          value: "/var/www/html"        - name: DUFS_PORT          value: "8080"        - name: DUFS_PATH_PREFIX          value: "/"        - name: DUFS_RENDER_INDEX          value: 'true'        - name: DUFS_RENDER_TRY_INDEX          value: 'false'        - name: DUFS_RENDER_SPA          value: 'true'        - name: DUFS_LOG_FORMAT          value: '$remote_addr "$request" $status'        ports:        - containerPort: 8080          name: http          protocol: TCP        resources:          limits:            cpu: "2"            memory: 4Gi          requests:            cpu: "1"            memory: 512Mi        volumeMounts:        - mountPath: /var/www/html          name: workdir      imagePullSecrets:      - name: harbor-weiyigeek      initContainers:      - name: init-cdn        command:        - sh        - -c        - |          cp -a /app/* /work/        image: hub.weiyigeek.top/app/cdn:20260316132518-prod        imagePullPolicy: IfNotPresent        securityContext:          privileged: true        volumeMounts:        - mountPath: /work          name: workdir      restartPolicy: Always      terminationGracePeriodSeconds: 15      volumes:      - emptyDir: {}        name: workdirEOF# 部署kubectl apply -f dufs-deploy.yaml

最后,考虑到大家可能对 K8s 不是很熟悉,也整理一个 docker 运行示例,供参考。

$ docker run -d --name dufs_server -p 5000:5000 
  -e DUFS_SERVE_PATH="/var/www/html" 
  -e DUFS_BIND=0.0.0.0 
  -e DUFS_PORT="5000" 
  -e DUFS_PATH_PREFIX=/ 
  -e DUFS_HIDDEN=.git,*.tmp,*.log,*.lock,*.zip,*.tar.gz 
  -e DUFS_RENDER_INDEX=true 
  -e DUFS_RENDER_SPA=true 
  -e DUFS_LOG_FORMAT='$remote_addr "$request" $status' 
  -v /var/www/html:/var/www/html:ro 
  hub.weiyigeek.top/library/sigoden/dufs:v0.45.0

$ docker ps --filter name=dufs_server
CONTAINER ID   IMAGE                                         COMMAND       CREATED          STATUS          PORTS                                       NAMES
ae53ec0f96e3   hub.weiyigeek.top/library/sigoden/dufs:v0.45.0   "/bin/dufs"   31 seconds ago   Up 30 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   dufs_server

$ docker logs -f --tail 50 dufs_server

weiyigeek.top-docker 运行 dufs 图

至此,作者在 K8S 以及 Docker 中使用 dufs 搭建的静态资源服务就完成了,希望对大家有所帮助!如果有帮助请一定要关注我哟,后续将发布利用 OpenResty 反向代理作为 CDN 回源,学习更多运维开发知识!

加入:作者【全栈工程师修炼指南】知识星球

相关推荐