云计算百科
云计算领域专业知识百科平台

Docker 部署 SFTPGo:把家用服务器变成安全文件交换站,外网临时收发不用开 NAS 后台

Docker 部署 SFTPGo:把家用服务器变成安全文件交换站,外网临时收发不用开 NAS 后台

SFTPGo 文件交换站封面:家庭服务器通过 cpolar HTTPS 安全临时收发文件,不暴露 NAS 后台

家里有一台小主机、办公室有一台闲置 mini PC,平时用来跑 Docker、备份照片、同步资料。偶尔遇到一个很现实的需求:外部同事要临时传一个大文件,或者你要给对方发一个安装包、设计稿、日志压缩包。

很多人的第一反应是:把 NAS 后台映射出去,或者临时开一个公网端口。

我不建议这么做。

NAS 后台里通常有存储管理、用户管理、套件管理、系统设置,一旦暴露到公网,风险和收益不成比例。更稳妥的做法是:单独部署一个文件交换服务,只给外部人员一个低权限账号,只能访问一个独立目录,用完就关账号、关隧道。

这篇就用 Docker 部署 SFTPGo,把它变成一个临时、安全、可控的文件交换站;需要外网访问时,再用 cpolar 临时映射 SFTPGo 的 WebClient 入口,而不是把整块 NAS 或管理后台暴露出去。

这套方案适合什么场景

适合:

  • 家用服务器、办公室小主机、迷你主机上临时收发文件;
  • 给外部同事开一个临时上传/下载账号;
  • 每个账号绑定独立目录,避免看到其他文件;
  • 不想让对方安装 SFTP 客户端,只想通过网页上传下载;
  • 不想开放 NAS 管理后台,只暴露必要的文件交换入口。

不适合:

  • 长期公开网盘;
  • 存放高度敏感资料;
  • 给陌生人开放匿名上传;
  • 把它当成完整 NAS 管理系统替代品。

SFTPGo 是一个文件传输服务器,支持 SFTP、FTP/S、WebDAV、HTTP WebClient 等能力。本文重点用它的 WebClient:外部同事打开网页,输入账号密码,就能上传或下载指定目录里的文件。

注意:SFTPGo 不等同于 NAS 后台。它更像一个“文件交换层”,适合做临时账号、目录隔离、权限控制;不要把它和群晖、威联通、TrueNAS 这类管理后台混在一起暴露。

整体流程

SFTPGo 与 cpolar 外网文件交换流程图:浏览器访问 WebClient 8081,管理端 8080 仅本机访问

本文会做 6 件事:

  • 在服务器上准备 SFTPGo 数据目录;
  • 用 Docker Compose 启动 SFTPGo;
  • 初始化管理员账号;
  • 创建一个低权限文件交换用户;
  • 用 WebClient 在本地验证上传和下载;
  • 用 cpolar 临时映射 WebClient,让外部同事访问测试。
  • 本文示例约定:

    • SFTPGo 管理入口:http://127.0.0.1:8080
    • SFTPGo WebClient 入口:http://127.0.0.1:8081
    • 本地文件目录:/srv/sftpgo/exchange
    • Docker 项目目录:/opt/sftpgo
    • 临时用户:partner01

    如果你的服务器没有 /srv 或 /opt 写入权限,可以换成当前用户目录,例如 ~/sftpgo。路径换了以后,下面命令里的路径也要一起换。

    第一步:准备本地目录

    先在服务器上创建项目目录、配置目录和文件交换目录:

    sudo mkdir -p /opt/sftpgo
    sudo mkdir -p /srv/sftpgo/config
    sudo mkdir -p /srv/sftpgo/exchange/partner01
    sudo chown -R 1000:1000 /srv/sftpgo
    cd /opt/sftpgo

    这里的 1000:1000 是 SFTPGo Docker 镜像默认使用的普通用户 UID/GID。这样容器内的 SFTPGo 进程可以正常读写挂载目录。

    目录含义:

    /opt/sftpgo # Docker Compose 文件目录
    /srv/sftpgo/config # SFTPGo 配置和内置数据
    /srv/sftpgo/exchange # 对外文件交换根目录
    /srv/sftpgo/exchange/partner01 # partner01 用户的独立目录

    这一步很关键。后面给外部同事开的账号,只绑定 /srv/sftpgo/exchange/partner01,不要绑定整块 NAS 目录,也不要绑定你的照片、备份、Docker 配置目录。

    第二步:编写 Docker Compose 文件

    在 /opt/sftpgo 下创建 docker-compose.yml:

    cd /opt/sftpgo
    sudo tee docker-compose.yml > /dev/null <<'EOF'
    services:
    sftpgo:
    image: drakkan/sftpgo:latest
    container_name: sftpgo
    restart: unless-stopped
    ports:
    – "127.0.0.1:8080:8080"
    – "127.0.0.1:8081:8081"
    environment:
    SFTPGO_HTTPD__BINDINGS__0__PORT: "8080"
    SFTPGO_HTTPD__BINDINGS__0__ADDRESS: "0.0.0.0"
    SFTPGO_HTTPD__BINDINGS__0__ENABLE_WEB_ADMIN: "true"
    SFTPGO_HTTPD__BINDINGS__0__ENABLE_WEB_CLIENT: "true"
    SFTPGO_HTTPD__BINDINGS__1__PORT: "8081"
    SFTPGO_HTTPD__BINDINGS__1__ADDRESS: "0.0.0.0"
    SFTPGO_HTTPD__BINDINGS__1__ENABLE_WEB_ADMIN: "false"
    SFTPGO_HTTPD__BINDINGS__1__ENABLE_WEB_CLIENT: "true"
    volumes:
    – /srv/sftpgo/config:/var/lib/sftpgo
    – /srv/sftpgo/exchange:/srv/sftpgo/exchange
    EOF

    这个 Compose 文件里有两个 Web 端口:

    • 8080:本机管理入口,用来创建用户、设置权限;
    • 8081:只启用 WebClient,不启用 Web 管理后台,用来临时映射给外部同事。

    并且两个端口都只绑定在 127.0.0.1:

    ports:
    – "127.0.0.1:8080:8080"
    – "127.0.0.1:8081:8081"

    这表示局域网里的其他机器不能直接访问这两个端口。需要外网临时访问时,我们只用 cpolar 映射 8081,不映射 8080。

    第三步:启动 SFTPGo

    执行:

    cd /opt/sftpgo
    sudo docker compose up -d

    查看容器状态:

    sudo docker compose ps

    正常会看到 sftpgo 处于运行状态。

    再看日志:

    sudo docker logs –tail=80 sftpgo

    本机测试 Web 入口:

    curl -I http://127.0.0.1:8080
    curl -I http://127.0.0.1:8081

    能返回 HTTP 响应头,就说明 Web 服务已经起来了。

    第四步:初始化管理员账号

    在服务器本机浏览器打开:

    http://127.0.0.1:8080

    第一次进入 SFTPGo Web Admin,会要求创建管理员账号。

    建议这样设置:

    • 管理员用户名不要用 admin;
    • 密码至少 16 位,包含大小写字母、数字、符号;
    • 管理员账号只自己使用,不发给外部同事;
    • 管理入口 8080 不做公网映射。

    初始化完成后,用管理员账号登录 Web Admin。

    第五步:创建临时文件交换用户

    进入 SFTPGo Web Admin 后,创建用户:

    Users -> Add user

    示例配置:

    Username: partner01
    Password: 使用随机强密码
    Status: Active
    Filesystem provider: Local filesystem
    Home dir: /srv/sftpgo/exchange/partner01

    权限建议按需求给,不要默认全开。

    如果对方只需要下载文件:

    Permissions: list, download

    如果对方需要上传文件:

    Permissions: list, upload, overwrite, create_dirs

    如果对方只是临时上传,不建议给删除权限。这样即使对方误操作,也不会把目录里的文件删掉。

    创建完成后,回到服务器确认目录权限:

    sudo chown -R 1000:1000 /srv/sftpgo/exchange/partner01
    sudo chmod -R u+rwX,g-rwx,o-rwx /srv/sftpgo/exchange/partner01

    chmod 这条命令的含义是:目录所有者可读写进入,组和其他用户无权限。它不是 WebClient 权限的替代品,而是本地文件系统层面的兜底。

    第六步:本地验证 WebClient 上传下载

    在本机打开 WebClient:

    http://127.0.0.1:8081

    用刚创建的用户登录:

    Username: partner01
    Password: 你给 partner01 设置的密码

    先做下载测试。

    在服务器里放一个测试文件:

    echo "hello from sftpgo" | sudo tee /srv/sftpgo/exchange/partner01/readme.txt > /dev/null
    sudo chown 1000:1000 /srv/sftpgo/exchange/partner01/readme.txt

    刷新 WebClient,应该能看到 readme.txt,点击可以下载。

    再做上传测试:

  • 在 WebClient 里点击上传;
  • 上传一个小文件,例如 test.txt;
  • 回到服务器检查文件是否落到目录里:
  • sudo ls -lah /srv/sftpgo/exchange/partner01

    如果文件能上传、能下载,这个临时文件交换账号就已经可用了。

    第七步:用 cpolar 临时映射 WebClient

    到这里,SFTPGo 只在本机可访问。外部同事还打不开。

    临时外网访问可以用 cpolar,把本地 8081 映射成一个公网 HTTPS 地址。重点是:只映射 WebClient 端口 8081,不要映射管理端口 8080,更不要映射 NAS 后台。

    如果服务器已经安装并登录 cpolar,直接执行:

    cpolar http 8081

    命令启动后,终端会显示一个公网访问地址,形式类似:

    https://xxxx.cpolar.top

    把这个地址发给外部同事,让对方使用 partner01 的账号密码登录。

    如果你更习惯用 cpolar Web UI,可以在服务器本机打开:

    http://127.0.0.1:9200

    然后创建 HTTP 隧道:

    协议:HTTP
    本地地址:127.0.0.1
    本地端口:8081

    创建后,在 cpolar 的隧道列表里复制公网地址。

    这里不要填 8080。8080 是管理入口,里面有用户管理和系统配置,不应该给外部人员访问。

    第八步:外部同事访问测试

    给外部同事发送三样东西:

    访问地址:https://xxxx.cpolar.top
    用户名:partner01
    密码:单独通过另一种渠道发送
    说明:只用于本次文件收发,用完会关闭

    建议不要把地址、用户名、密码放在同一条消息里。比如地址发 IM,密码电话或另一个聊天工具发。

    让对方测试:

  • 打开 cpolar 公网地址;
  • 进入 SFTPGo WebClient 登录页;
  • 输入 partner01 和密码;
  • 上传一个小文件;
  • 下载你提前放好的 readme.txt;
  • 你在服务器上确认文件是否出现。
  • 服务器端检查:

    sudo ls -lah /srv/sftpgo/exchange/partner01

    测试完成后,如果只是一次性收发文件,立刻做两件事:

  • 在 SFTPGo Web Admin 里禁用 partner01;
  • 停止 cpolar 隧道。
  • 如果是前台运行的 cpolar http 8081,在终端按:

    Ctrl + C

    如果是在 cpolar Web UI 创建的隧道,就在 Web UI 里停止对应隧道。

    安全边界:这几条不要省

    SFTPGo 文件交换安全边界图:只暴露 WebClient,使用强密码、临时账号、独立目录并用完关闭

    这套方案的安全感,来自“只暴露必要入口”和“只给必要权限”。不要因为它能跑通,就把边界放大。

    1. 不要映射整块 NAS

    不要把 SFTPGo 用户的 Home dir 设置成:

    /volume1
    /mnt/nas
    /srv
    /home
    /

    应该给每个外部人员单独建目录,例如:

    /srv/sftpgo/exchange/partner01
    /srv/sftpgo/exchange/customer-a
    /srv/sftpgo/exchange/project-x-upload

    2. 不要开放管理员后台

    本文把管理入口放在 8080,WebClient 放在 8081。cpolar 只映射:

    cpolar http 8081

    不要执行:

    cpolar http 8080

    3. 临时账号用完就禁用

    文件收发结束后,在 SFTPGo Web Admin 里把用户改成禁用状态。下次需要再启用,或者重新建一个新账号。

    4. 密码要强,最好单次使用

    不要用:

    123456
    password
    company2026
    partner01

    建议用密码管理器生成 16 位以上随机密码。

    5. 不要传高度敏感文件

    临时文件交换站适合传普通协作文件、安装包、日志、素材。涉及身份证、合同原件、财务数据、客户隐私、密钥文件时,不要直接用这种临时公网方式裸传。

    6. 用完关闭隧道

    cpolar 的价值在于“按需临时打开”。文件收发结束后就关闭隧道,不要把临时入口长期挂在公网。

    常见问题排查

    1. 容器启动失败

    先看状态:

    cd /opt/sftpgo
    sudo docker compose ps

    再看日志:

    sudo docker logs –tail=120 sftpgo

    常见原因:

    • 8080 或 8081 已被占用;
    • Compose 文件缩进错误;
    • /srv/sftpgo/config 没有写入权限;
    • Docker 服务没有启动。

    检查端口占用:

    sudo lsof -iTCP:8080 -sTCP:LISTEN
    sudo lsof -iTCP:8081 -sTCP:LISTEN

    如果端口被占用,把 Compose 里的宿主机端口换掉,例如把 8081 改成 18081,cpolar 也跟着映射新端口。

    修改后重启:

    cd /opt/sftpgo
    sudo docker compose down
    sudo docker compose up -d

    2. Web 页面打不开

    先在服务器本机测试:

    curl -I http://127.0.0.1:8080
    curl -I http://127.0.0.1:8081

    如果本机都打不开,问题在 SFTPGo 或 Docker,不在 cpolar。

    继续检查:

    sudo docker ps –filter name=sftpgo
    sudo docker logs –tail=80 sftpgo

    如果本机能打开,但局域网其他机器打不开,这是正常的。本文故意把端口绑定在 127.0.0.1,避免局域网直接访问。

    3. 登录失败

    检查 4 件事:

    • 用户名是否写错;
    • 密码是否复制时带了空格;
    • 用户状态是否 Active;
    • 是否用管理员账号登录了 WebClient,或用普通用户登录了 Web Admin。

    本文外部同事应该访问的是:

    http://127.0.0.1:8081

    公网时访问的是 cpolar 映射出来的 8081 地址。

    4. 目录权限不对

    如果 WebClient 登录后看不到文件,或者上传时报错,先看目录权限:

    sudo ls -ld /srv/sftpgo/exchange/partner01
    sudo ls -lah /srv/sftpgo/exchange/partner01

    重新设置目录归属:

    sudo chown -R 1000:1000 /srv/sftpgo/exchange/partner01
    sudo chmod -R u+rwX,g-rwx,o-rwx /srv/sftpgo/exchange/partner01

    然后重新登录 WebClient 测试。

    5. 外网地址打不开

    先确认本地 WebClient 能打开:

    curl -I http://127.0.0.1:8081

    再确认 cpolar 映射的是 8081:

    cpolar http 8081

    如果你用的是 cpolar Web UI,检查隧道配置:

    协议:HTTP
    本地地址:127.0.0.1
    本地端口:8081

    不要填错成 8080,也不要填成容器内部 IP。

    如果公网地址之前能打开,后来打不开,重新启动一次隧道并复制新的公网地址。免费随机地址会变化,不要继续使用旧地址。

    6. 上传失败

    上传失败通常有三类原因。

    第一类:SFTPGo 用户权限不够。

    在用户权限里确认至少包含:

    list, upload

    如果需要覆盖同名文件,再加:

    overwrite

    如果需要创建目录,再加:

    create_dirs

    第二类:本地目录不可写。

    执行:

    sudo chown -R 1000:1000 /srv/sftpgo/exchange/partner01
    sudo chmod -R u+rwX,g-rwx,o-rwx /srv/sftpgo/exchange/partner01

    第三类:文件太大或网络中断。

    先用 1MB 以下的小文件测试。如果小文件能上传,大文件失败,再检查浏览器、网络稳定性和服务器磁盘空间:

    df -h /srv/sftpgo/exchange

    7. 文件权限看起来异常

    通过 WebClient 上传的文件属于容器内运行用户,对应宿主机上通常显示为 UID 1000。

    查看:

    sudo ls -lah /srv/sftpgo/exchange/partner01

    如果你还要让宿主机上的其他服务读取这些文件,可以把后续处理脚本也放在同一用户权限下运行,或者在处理前调整属主。不要为了省事直接给整个目录 777。

    收尾:一次临时收发的标准动作

    一次外部文件交换结束后,我建议按这个顺序收尾:

    1. 确认文件已经收齐或发完
    2. 在 SFTPGo Web Admin 禁用临时用户
    3. 停止 cpolar 隧道
    4. 把文件从 exchange 目录转移到内部长期存储
    5. 清空临时目录

    清空临时目录前先确认路径:

    sudo find /srv/sftpgo/exchange/partner01 -maxdepth 1 -type f -print

    确认无误后再删除文件:

    sudo find /srv/sftpgo/exchange/partner01 -maxdepth 1 -type f -delete

    不要对不熟悉的目录执行 rm -rf,尤其不要在 NAS 挂载目录里随手复制删除命令。

    小结

    这套方案的核心不是“把文件服务暴露到公网”,而是把暴露范围压到最小:

    • SFTPGo 负责文件交换;
    • 每个外部人员一个低权限账号;
    • 每个账号一个独立目录;
    • WebClient 负责临时上传下载;
    • cpolar 只在需要时映射 WebClient;
    • 管理后台和 NAS 后台都不对外开放。

    如果只是临时给同事收发文件,这比直接开放 NAS 后台安全得多,也比临时搭一个共享目录更可控。

    你可以按本文先跑一遍本地流程,再开 cpolar 做外网测试。卡住的话,留言说清楚你卡在哪一步:Docker 启动、目录权限、账号权限、外网访问,还是上传失败。我会按你的报错和截图帮你逐项排查。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Docker 部署 SFTPGo:把家用服务器变成安全文件交换站,外网临时收发不用开 NAS 后台
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!