PsiTransfer 2.4.5 Docker Compose 部署指南

在 Docker 服务器上用 Compose 部署 PsiTransfer 2.4.5 一次性文件分享服务:镜像选型、数据持久化、环境变量与配置文件挂载、启动验证与运维命令,上传下载全链路实测通过。

PsiTransferNodejs文件传输文件分享自托管2026/11/01

PsiTransfer 2.4.5 Docker Compose 部署指南

目标:在一台 Linux 服务器上以 Docker Compose 部署 PsiTransfer 2.4.5 一次性文件分享服务,覆盖镜像选型、数据持久化、环境变量与配置文件挂载、启动验证与日常运维,最终完成「上传 → 下载 → 到期清理」全链路验证。已在 Ubuntu 24.04 LTS(x86_64)+ Docker 29.9.2 + Docker Compose v5.6.1 环境实测通过(2026-11-01)。

一、环境信息

  • 操作系统:Ubuntu 24.04.5 LTS(x86_64)
  • Docker:29.9.2(docker --version)
  • Docker Compose:v5.6.1(docker compose version)
  • 软件版本:PsiTransfer 2.4.5(官方镜像标签 2,对应最新稳定 2.x;GitHub Releases 最新稳定版 v2.4.5,2026-11-01 查询)
  • 服务器 IP:192.168.1.172(示例环境实际地址,下同)
  • 端口规划:宿主机 8130 → 服务 3000
  • 数据目录:/opt/psitransfer/(compose 文件、数据目录、配置文件同置)

二、镜像选型说明

PsiTransfer 官方在 Docker Hub 发布镜像 psitrax/psitransfer,无需本地构建。官方 README 声明的标签体系如下(来源:官方 README Quickstart,2026-11-01 查询):

标签对应版本建议
2最新稳定 2.x(本文溯源时为 2.4.5)生产推荐,自动获得 2.x 内最新补丁
latestmaster 分支构建跟随开发分支,不建议生产使用
1.1 / 1.0.0旧 1.x 主线仅存量迁移场景使用,新部署勿选

本文选用 psitrax/psitransfer:2。拉取镜像并确认大小:

docker pull psitrax/psitransfer:2
docker images psitrax/psitransfer

实测回显:

2: Pulling from psitrax/psitransfer
Digest: sha256:4424bc357699c15fb94d4d781509d92aa68786434c35804e0ba0a36d8900d10d
Status: Image is up to date for psitrax/psitransfer:2
docker.io/psitrax/psitransfer:2
REPOSITORY             TAG   IMAGE ID       SIZE
psitrax/psitransfer    2     4424bc357699   279MB

镜像内置信息(docker inspect 实测):

  • 运行时:Node v14.14.0;
  • 默认环境变量:NODE_ENV=production、PSITRANSFER_UPLOAD_DIR=/data;
  • 入口:docker-entrypoint.sh → node app.js,工作目录 /app,运行用户 node(UID 1000);
  • 内置语言包:英语(en)、德语(de)。

💡 技术拓展:文件分享类服务的容器化交付常见三种形态——「官方预构建镜像」(如本文 PsiTransfer、PicoShare)、「源码 + Dockerfile 本地构建」(如 goploader)、「单二进制直接运行」(如 miniserve)。官方预构建镜像升级只需 pull 新 tag 重启,运维成本最低,但要留意官方标签是否持续维护(PsiTransfer 2026 年仍在更新 2.x 系列)。本文采用官方预构建镜像形态。

三、前置条件

  1. 服务器已安装 Docker 与 Docker Compose 插件;
  2. 宿主机 8130 端口未被占用;
  3. 服务器可访问 Docker Hub(拉取镜像);受限网络环境可给 Docker 守护进程配置 HTTP 代理。

逐项验证:

docker --version
docker compose version
ss -ltn | grep 8130 || echo 'port 8130 free'

实测回显:

Docker version 29.9.2, build a82e528
Docker Compose version v5.6.1
port 8130 free

四、部署步骤

4.1 创建目录与数据目录属主

PsiTransfer 容器内以 UID 1000(用户 node)读写数据目录,宿主数据目录属主必须与之一致,否则启动后上传报权限错误(官方 README 明确提示「data volume needs UID 1000」):

mkdir -p /opt/psitransfer/data
sudo chown -R 1000:1000 /opt/psitransfer/data

4.2 编写 docker-compose.yml

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

name: psitransfer-2.4.5-stack

services:
  app:
    image: psitrax/psitransfer:2
    container_name: psitransfer-2.4.5-app
    environment:
      - NODE_ENV=production
      - PSITRANSFER_ADMIN_PASS=q1w2e3r4
    ports:
      - "8130:3000"
    volumes:
      - ./data:/data
      - ./config.production.js:/app/config.production.js:ro
    restart: unless-stopped

配置逐项说明:

  • name: psitransfer-2.4.5-stack:Compose 项目名,显式指定可避免多套部署同名项目互相覆盖;
  • image:官方镜像 2 标签,即最新稳定 2.x;
  • PSITRANSFER_ADMIN_PASS=q1w2e3r4:管理页 /admin 的访问口令;不设置该变量时 /admin 页面整体禁用(实测访问返回 404,见「十一、常见问题」);
  • "8130:3000":宿主 8130 映射容器 3000(服务固定监听 3000,可用 PSITRANSFER_PORT 修改容器内端口);
  • ./data:/data:数据目录挂载,镜像默认 PSITRANSFER_UPLOAD_DIR=/data 指向这里;
  • ./config.production.js:/app/config.production.js:ro:配置文件挂载(见「八、配置文件挂载」),NODE_ENV=production 时服务启动会加载该文件覆盖默认参数;
  • restart: unless-stopped:开机自启与异常退出自动拉起。

4.3 创建配置文件并启动

先写入最小配置文件(本例覆盖默认保留档与大小限制,按需修改):

// /opt/psitransfer/config.production.js
module.exports = {
  defaultRetention: "3600",
  maxFileSize: Math.pow(2, 20) * 5, // 5MB
  maxBucketSize: Math.pow(2, 30) * 1, // 1GB
};

启动并确认状态:

cd /opt/psitransfer
docker compose up -d
docker compose ps

实测回显:

 Container psitransfer-2.4.5-app Created
 Container psitransfer-2.4.5-app Starting
 Container psitransfer-2.4.5-app Started
NAME                    IMAGE                   COMMAND                  SERVICE   CREATED         STATUS         PORTS
psitransfer-2.4.5-app   psitrax/psitransfer:2   "docker-entrypoint.s…"   app       5 seconds ago   Up 4 seconds   0.0.0.0:8130->3000/tcp, [::]:8130->3000/tcp

4.4 启动日志与页面验证

查看服务日志:

docker logs psitransfer-2.4.5-app

实测回显:

PsiTransfer listening on http://0.0.0.0:3000

验证首页与前端配置接口:

curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://localhost:8130/
curl -s http://localhost:8130/config.json | python3 -m json.tool

实测回显:

HTTP 200
{
    "retentions": {
        "3600": "1 Hour",
        "21600": "6 Hours",
        "86400": "1 Day",
        "259200": "3 Days",
        "604800": "1 Week",
        "1209600": "2 Weeks",
        "2419200": "4 Weeks",
        "4838400": "8 Weeks",
        "one-time": "one time download"
    },
    "defaultRetention": "3600",
    "mailTemplate": "mailto:?subject=File Transfer&body=You can download the files here: %%URL%%",
    "requireBucketPassword": false,
    "maxFileSize": 5242880,
    "maxBucketSize": 1073741824
}

config.json 返回的正是前端上传页实际使用的运行时配置:保留档共 9 档(8 档时长 + 一次性下载)、默认保留 1 小时、单文件上限 5MB、单 bucket 上限 1GB——与 config.production.js 的覆盖值一致,说明配置文件挂载已生效。

浏览器访问 http://192.168.1.172:8130/ 即可打开上传页(首页 meta 标签自带 robots: noindex,nofollow,搜索引擎不会收录)。

五、数据持久化说明

全部状态收敛在 /opt/psitransfer/data/ 一个目录内,结构如下(实测):

data/
├── demo1234/                          # 每个 bucket 一个子目录(目录名=bucket ID)
│   ├── a20359ce-04a8-...              # 文件本体,文件名=上传时生成的 UUID key
│   ├── a20359ce-04a8-....json         # 该文件的元数据(名称、保留档、上传时间等)
│   └── ...
└── demosec/
    └── ...

实测验证持久化:上传文件 → 重启服务 → 文件仍可访问:

docker compose restart
docker compose ps

实测回显(重启后 bucket 与文件原样保留):

 Container psitransfer-2.4.5-app Stopping
 Container psitransfer-2.4.5-app Stopped
 Container psitransfer-2.4.5-app Started
NAME                    IMAGE                   COMMAND                  SERVICE   CREATED          STATUS         PORTS
psitransfer-2.4.5-app   psitrax/psitransfer:2   "docker-entrypoint.s…"   app       10 minutes ago   Up 2 seconds   0.0.0.0:8130->3000/tcp, [::]:8130->3000/tcp
du -sh /opt/psitransfer/data

实测回显:

124K	/opt/psitransfer/data

备份与迁移即「打包拷走这个目录」:

tar czf psitransfer-data-$(date +%F).tar.gz -C /opt/psitransfer data

⚠️ 注意:one-time(一次性)档的文件在首个下载完成后本体与元数据都会立即删除,因此备份只能保住「尚存」的文件;需要强留档的文件不要选 one-time 档。

六、环境变量表

PsiTransfer 的所有配置项都可通过 PSITRANSFER_ 前缀环境变量覆盖(服务端自动完成 PSITRANSFER_UPLOAD_PASS → uploadPass 的驼峰映射)。常用变量如下(默认值取自镜像内置 config.js,2026-11-01 实测核对):

环境变量对应配置项默认值说明
NODE_ENV运行环境production(镜像内置)决定加载 config.<NODE_ENV>.js
PSITRANSFER_PORTport3000HTTP 监听端口
PSITRANSFER_IFACEiface0.0.0.0监听网卡地址
PSITRANSFER_UPLOAD_DIRuploadDir/data(镜像内置)上传数据目录
PSITRANSFER_BASE_URLbaseUrl/反向代理子路径部署时改(如 /files/)
PSITRANSFER_ADMIN_PASSadminPassfalse(禁用 /admin)管理页口令,设置后 /admin 才可用
PSITRANSFER_UPLOAD_PASSuploadPassfalse(不设上传口令)站点级上传口令,客户端须带 x-passwd 头
PSITRANSFER_DEFAULT_RETENTIONdefaultRetention604800默认保留档(秒),需为 retentions 的键之一
PSITRANSFER_MAX_FILE_SIZEmaxFileSizenull(不限制)单文件上限(字节),超出返回 413
PSITRANSFER_MAX_BUCKET_SIZEmaxBucketSizenull(不限制)单 bucket 累计上限(字节)
PSITRANSFER_MAX_AGEmaxAge6480000(75 天)文件最长存活时间(秒),含从未被下载的 one-time 文件
PSITRANSFER_DEFAULT_LANGUAGEdefaultLanguageen界面语言(内置 en/de)
PSITRANSFER_SSL_PORTsslPort8443HTTPS 端口(需同时给 sslKeyFile/sslCertFile 才启用)
PSITRANSFER_FILE_DOWNLOADED_WEBHOOKfileDownloadedWebhooknull文件下载完成后 POST 通知的 URL
PSITRANSFER_FILE_UPLOADED_WEBHOOKfileUploadedWebhooknull文件上传完成后 POST 通知的 URL

💡 说明:环境变量与配置文件(config.production.js)的加载优先级是环境变量高于配置文件——服务先加载内置默认值,再叠加 config.production.js,最后用环境变量覆盖。三处都写的参数最终以环境变量为准。

七、配置参数说明

服务端配置共 20 余项,完整参数语义、类型转换规则(数字/数组/JSON 对象自动解析)与逐项实测验证见 《PsiTransfer 2.4.5 配置参数详解》。部署阶段最需要关注的是以下四个:

  1. adminPass:不设置则 /admin 管理页完全禁用(404);演示口令 q1w2e3r4 仅限测试环境,生产请替换为强口令;
  2. uploadPass:公网部署强烈建议设置,否则任何人都能向服务器写文件占用磁盘与带宽;
  3. maxFileSize / maxBucketSize:默认不限制,公网服务务必设置,防止单次上传塞满磁盘;
  4. retentions / defaultRetention:保留档既是界面下拉选项也是上传 API 的合法取值集合,defaultRetention 必须是 retentions 的键,否则前端默认值无法匹配。

八、配置文件挂载

相比环境变量,挂载 config.production.js 更适合大批量参数的一次性覆盖。加载机制(来自镜像内置 config.js 源码逻辑):NODE_ENV=production 时启动会尝试加载 /app/config.production.js 并 Object.assign 合并进默认配置。

本文 4.2/4.3 节的挂载实测结果:

  • 挂载前:defaultRetention=604800、maxFileSize=null、maxBucketSize=null(镜像默认);
  • 挂载后(4.4 节 config.json 回显):defaultRetention=3600、maxFileSize=5242880、maxBucketSize=1073741824。

三个覆盖值全部生效,验证了挂载路径正确性。注意两点:

  1. 配置文件内是 JavaScript(module.exports = {...}),可以用表达式(如 Math.pow(2, 20) * 5);
  2. 修改配置文件后需 docker compose restart 生效,再用 curl http://localhost:8130/config.json 复核实际生效值。

九、等价 docker run

不使用 Compose 时的等价启动命令:

docker run -d \
  --name psitransfer-2.4.5-app \
  -p 8130:3000 \
  -e NODE_ENV=production \
  -e PSITRANSFER_ADMIN_PASS=q1w2e3r4 \
  -v /opt/psitransfer/data:/data \
  -v /opt/psitransfer/config.production.js:/app/config.production.js:ro \
  --restart unless-stopped \
  psitrax/psitransfer:2

启动后同样输出 PsiTransfer listening on http://0.0.0.0:3000。长期运行仍建议用 Compose 管理(参数落盘、可版本化)。

十、常用运维命令

以下命令均在 /opt/psitransfer/ 目录下执行:

# 服务状态
docker compose ps

# 实时日志
docker compose logs -f

# 重启服务(修改 config.production.js 后)
docker compose restart

# 停止服务(数据保留)
docker compose down

# 升级到 2.x 最新(pull 后重建容器,数据不受影响)
docker compose pull && docker compose up -d

# 数据目录占用
du -sh /opt/psitransfer/data

docker compose pull && docker compose up -d 实测回显(本地已是最新时):

[+] Running 2/2
 ✔ app Pulled
   Container psitransfer-2.4.5-app Running

升级提示:2 标签会随官方发布移动,pull 前建议先在 GitHub Releases 确认新版本变更(尤其安全修复类);数据目录向后兼容,无需迁移操作。

十一、常见问题

Q1:/admin 打不开,返回 404?

这是预期行为而非故障:adminPass 未设置(或为 false)时管理页整体禁用。实测:去掉 PSITRANSFER_ADMIN_PASS 环境变量重启后 curl -o /dev/null -w '%{http_code}' http://localhost:8130/admin 返回 404;设置后重启返回 200。解决方案:在 compose 的 environment 中补上 PSITRANSFER_ADMIN_PASS=<你的口令> 后 docker compose up -d 重建。

Q2:上传接口返回 401/403?

设置了 PSITRANSFER_UPLOAD_PASS 后,所有上传请求(POST /files、PATCH /files)与 config.json 都要求携带 x-passwd 请求头:缺失返回 401 Unauthorized、口令错误返回 403 Forbidden(实测复现)。浏览器端会在上传页弹出密码输入框,API 调用端需自行加头。忘记口令时从 compose 环境变量或 config.production.js 中查看。

Q3:启动后上传报权限错误(EACCES)?

宿主数据目录属主不是 UID 1000 所致。执行 sudo chown -R 1000:1000 /opt/psitransfer/data 后重启。可用 ls -ln /opt/psitransfer/data 复核属主列显示为 1000 1000。

Q4:文件「下载一次就 404」是不是坏了?

不是。该文件上传时选择了 one-time(一次性下载)保留档,首个接收者下载完成后服务端立即删除文件本体与元数据(实测:下载返回 200 且带 Content-Disposition,再次请求同一 URL 返回 404)。需多次分发的文件请选择时长类保留档(1 小时~8 周)。

Q5:/data 目录下出现没有对应下载页的文件本体(孤儿文件)?

两种已知来源:其一,创建后从未传完的分块上传会残留一条 partial 元数据记录(文件本体可能为 0 或部分长度),直到 maxAge(默认 75 天)过期被清理;其二,one-time 文件下载完成(元数据已删)后若客户端继续对同一上传 ID 追加分块,会重建出无人引用的本体文件。运维上可定期核对 data/<sid>/ 内「有本体无 .json」的文件手动清理,或缩短 maxAge。

Q6:需要 HTTPS 怎么办?

两种路径:其一,前置 Nginx/Caddy 反向代理并终止 TLS(v2.3.0 起官方支持反向代理场景,子路径部署配合 PSITRANSFER_BASE_URL 使用);其二,服务端原生 TLS——同时配置 sslKeyFile、sslCertFile 与 sslPort,可用 forceHttps 强制跳转。公网部署建议走反向代理方案,证书续期与告警管理更成熟。

十二、参考链接