6.0 KiB
Synology Photos API 来源与 Ubuntu 迁移候选
本功能从 NAS 的 Photos API 按需读取照片,不需要 NFS、SMB 或 /photos 文件挂载。NAS 原照片不复制整库到 Server。
已支持与边界
- 新来源类型
synology-photos,与local挂载目录明确分开。 - 共享空间
SYNO.FotoTeam、当前登录账号的个人空间SYNO.Foto;不是任意 NAS 用户的个人空间。 - 人物列表分批读取,照片按 ID 做 any 并集 / all 交集;无匹配时明确为空,不回退全库。
- 支持目录相对路径、递归开关、日期文件夹 / 标题、方向及现有质量筛选。
.表示所选空间根目录;路径以 Photos 返回的目录名为准,不是 Ubuntu 绝对路径。 - 图片使用经过实测的
Thumbnail.getv2、size=xl。原始文件名不代表下载的是原图。对 NAS 当前原图下载接口的探测被拒绝,原图下载未宣称支持。 - 照片枚举
Browse.Item.listv7,人物Browse.Person.listv3;每批 500 条,最多 100000 条,超过明确失败,界面目录上限仍由catalog_limit控制。不支持 NAS 未暴露或账号无权访问的相册。 - 旧
local来源保留挂载读取方式,不自动变成 API 来源。新建 / 编辑来源时可明确选择 API 类型。
安全与缓存
保持 HTTPS SHA-256 证书指纹校验,在同一 TLS socket 验证证书后才发送 SID。仅调用固定 API 与只读方法,不使用通用 RPC 转发、不跟随重定向。密码不持久化,会话文件保持 0600。会话过期返回明确重连提示;不保存密码以自动重登,也不对 NAS 原会话发 logout。权限不足与会话失效分开处理。
缓存为 /data/cache/synology-photos,默认总图片字节上限 256 MiB,可用 SYNOLOGY_PHOTOS_CACHE_BYTES 调整(环境配置最小 1 MiB),单张不超过应用 20 MiB 限制。只下载选中的图片。文件锁合并跨线程、跨进程下载,预留容量后写 0600 临时文件,完成长度核对及 Pillow 验证 / 解码后原子提交;超时、中断及无效数据清理临时文件,下次持锁读取清理进程异常退出遗留的 .part。按最近使用淘汰。缓存身份包含端点、会话摘要、空间、照片 ID、索引版本及缩略图缓存键,避免账号 / 空间混用。
容量上限针对图片和下载临时文件的逻辑字节,不含 SQLite、锁文件与文件系统元数据;并发串行缓存锁会等待正在进行的单张下载。网络 socket 超时 30 秒,流读取检查 90 秒期限,已阻塞的单次 socket 读取最多再等待其超时。
Ubuntu 候选配置
正式代码在 /home/developer/Documents/Projects/pigway-frame-flow 的 codex/synology-photos-api 分支开发,不能以迁移临时解包目录作为开发仓库。
候选文件:deploy/compose.ubuntu-photos-api.yml。外部 192.0.2.10:81,内部 18787,UID/GID 10333:10333,数据和配置固定为:
/srv/pigway/apps/pigway-frame-flow/data:/data/srv/pigway/apps/pigway-frame-flow/config:/config
无 /photos 绑定。create_host_path: false 防止在 T7 未挂载时悄悄创建目录;但仍需在启动前检查 findmnt -T /srv/pigway 的实际源设备。
.env 需从已确认的配置安全迁移,保留 Photos URL、证书 pin 与已有 Frame Flow / 相框鉴权;不要把密钥写入仓库。模板默认 KOKONNA_WRITE_ENABLED=false。创建 data/tmp,属主保持 10333:10333,TMPDIR=/data/tmp。Docker data-root 和 containerd root 也必须在 T7,不能仅检查 bind mount。
# 仅检查候选配置;不会启动应用。
FRAME_FLOW_IMAGE='<已验证的镜像标签>' docker compose -f deploy/compose.ubuntu-photos-api.yml config --quiet
完整构建使用根目录 Dockerfile。若使用 deploy/Dockerfile.runtime-update,必须指定已审核的基础镜像,构建步骤会检查依赖锁与基础镜像相同;不相同时必须完整构建。本次依赖未新增,已比对现有 0.1.8 基础镜像的锁文件。
旧来源转换与恢复
停止目标实例、复制数据、转换真实配置及切换部署均需另行授权,本次没有执行。
-
确认 T7 挂载,备份 NAS 原有完整
/data、/config、旧镜像及 Compose。SQLite 必须停服务后复制,或使用 SQLite backup API;不要只复制有活动 WAL 的主文件。 -
将备份恢复到上述 Server 目录,保持私密文件权限,创建
data/tmp。保留旧 NAS 备份直至切换验收。 -
对每个需要摆脱挂载的来源显式 dry run:
python scripts/migrate-photos-api.py --database /data/frameflow.db --source family # 已获授权、目标服务已停止时才执行: python scripts/migrate-photos-api.py --database /data/frameflow.db --source family --apply --service-stopped工具保持来源 ID、任务引用、人物空间、any/all、目录、方向及筛选设置,只修改来源类型并关闭旧本地
@eaDir预览开关;自动在同一数据目录生成 0600 SQLite 备份。转换不会验证该账号在 Photos 中是否可访问相同目录,必须再做真实只读预览。不要转换确实依赖挂载且 Photos 未收录的目录。 -
已获得单独授权后才停旧实例、以只读候选配置启动 Server,并逐个来源验收。没有授权前不执行
compose up或开启真实写入。 -
回退时停止 Server,恢复已备份的数据库和配置(停服务时处理对应 WAL/SHM),恢复旧来源类型与 NAS 原部署,保证只有一个实例有写权限。原 NAS 照片不受缓存或来源转换影响。
NFS 授权判断
API 来源的共享 / 个人空间取图已经可以完全不依赖 NFS,因此这条新取图链路不需要为 192.0.2.10 保留 DSM photo NFS 授权。但目前旧来源和待迁移配置没有全部切换验收,不能据此宣称迁移完成或旧本地来源已可脱离挂载。确认没有其他已批准用途后,可以单独授权删除该特定 NFS 规则;本次没有删除。
实际版本、镜像标识、通过 / 失败 / 未执行项见本任务验证记录。