由于immich更新频繁,本文部分信息可能随时过时。

从接触 NAS 的一开始,我选择的就是正版。群晖 DS220+ 带给我的不止是原汁原味的DSM 系统、官方完善的售后服务,更是能在硬件方面免去对装机一窍不通的我自行捣腾带来的风险和烦恼。可使用一段时间下来发现,DS220+ 双核 CPU 的性能并不足以满足我日常使用,内存只支持增加到 10G,双盘位也不方便扩容。

220+遗照
220+遗照

硬件不足尚是我财力问题,可软件也有些不顺心意(也是我自己的问题)

举些栗子。需要登录群晖账号才能使用的 QuickConnect,只是 NAS 刚到手时用过,碍于带宽太窄,搞定了公网后就关掉了;一些 Business 套件尽管功能强大,但没有使用场景,也就没机会体验。没有账号限制的 Synology Drive,本以为可以替代 OneDrive 省一笔费用,可发现只能扫描用户 home 目录下的文件,并不能随心所欲当成网盘用,再加上家庭网络波动等各方面均体验不佳,和深度融合进系统的 OneDrive 根本没法比,没几天也放弃了。

此外,还有自带的 DDNS、Nginx 反向代理,在找到平替后也都弃用了。更不用提早就被 emby、qBittorrent 取代的 Audio Station、Video Station 和 Download Station……到最后,唯一离不开的,就只剩下 WebDAV 和备份用的 Cloud Sync 了。

如果不是太多应用不能删,这个页面的图标会更少
如果不是太多应用不能删,这个页面的图标会更少

所以前段时间终于下定决心,卖掉了陪伴我接近两年的 DS220+。

大概是我维护博客期间养成的坏习惯,才会对 DSM 挑三拣四。相比使用不知道数据保存在什么地方的套件,我更偏爱一些可控程度高的开源程序。我愈发怀疑自己是否有必要使用 DSM,而不是一个能跑 Docker 的纯粹的 Linux 系统。

因此,在购买 R730XD、卖掉 DS220+、改用 PVE 安装虚拟机 DSM、硬件规格提升了不知道多少个档次之后,我决定寻找一些可以取代 NAS 上某些套件的开源程序。这次先对 Synology Photos 下手,换成声名远扬的 immich

为什么之前没有尝试?其实是测试了的,但 220+ CPU 太拉内存太小,有点跑不动 immich……

准备

在开始前,不妨先考虑一下为什么要换 immich,而不是继续使用 Synology Photos。避免做无用功。

就我个人而言,有如下几点原因:

  1. iPhone 的相册十分强大,人脸、地图、OCR 之类的功能应有尽有。我也开通了 iCloud 备份照片,用不上 Synology Photos 的大多数功能;
  2. 在黑群中运行 Synology Photos,人脸识别功能需要额外进行修复(但操作并不复杂,可以忽视);
  3. Photos 和 Drive 一样,限制了照片保存的位置。个人相册在 /home/Photos 目录下,不能随心所欲地设置保存路径;共享相册需要新建 /photo 共享文件夹,不能直接使用现有文件夹,很不优雅;
  4. 同上,Synology Photos 也不支持读取保存在其他位置的图片或视频。

还有一点是我换用 immich 后才发现的。DSM 在创建图片索引的同时,会生成不同规格的缩略图。这些缩略图被直接保存在图片同级目录下的不可见的 @eaDir 文件夹中。视原图片大小而定,可能会有同时生成 B、L、M、S、XL 五份不同大小的缩略图。

虽然 @eaDir 文件夹在 NAS 上不可见,SMB 挂载到 PC 也看不到,Cloud Sync 也不会把这个文件夹同步到云端,可它确实是真实存在着的。因此在执行某些操作的时候,比如直接在 Shell 中复制包含图片的文件夹,就会连带着把缩略图一块复制走。

使用 immich cli 上传时发现的……
使用 immich cli 上传时发现的……

综上所述,我不会再考虑使用 Synology Photos。

另一方面,虽然没有能力完全遵循「备份321」的原则,我也会将 iPhone 上的图片备份到 NAS 上,然后再通过 Cloud Sync 备份到云端,比如 OneDrive 或百度网盘——也就需要一个能在 NAS 上预览图片的工具。

如此考虑之后,选择了比较知名的免费的 immich。

Immich 是开源在 Github 上的一款自托管相册应用,功能与 Synology Photos 类似,但更人性化、自定义程度也更高。目前更新频繁,bug 修复快,最新版本已支持简体中文,安装步骤也大幅精简,可以说,现在就是上车 immich 的最好时机。

你可能会推荐收费的 mtphotos,在撰写本文的期间试用了下,确实还不错。支持以文件夹显示图库,方便查看收藏的图,很多方面确实符合国人使用体验。但国产……你懂的。再说,我觉得一人之力比不上开源社区的力量。

安装

这里推荐使用 imagegenius/immichcompose.yml 安装 immich,这是基于原 immich 镜像的一体化版本。数据文件被调整为挂载到 /config,可自定义运行用户的 GID/UID,还内置了用于 AI 识别的 immich-microservices 服务,安装时只需配置一个 immich 本体、一个缓存程序 Redis,以及数据库程序 PostgreSQL 即可。

官方 immich 的最新版本也将 immich-microservices 内置在了 immich 主程序中,因此目前两者除了运行用户和挂载路径外,几乎没有区别。

在安装之前,需要先创建以下文件夹:

  • config 文件夹:挂载到 immich 内 /config 目录下,存储 immich 基本数据
  • photos 文件夹:挂载到 immich 内 /photos 目录下,存储上传的照片
  • 其他外部文件夹:挂载到 immich 内 /import 目录下,用以扫描其他位置下的照片
  • database 文件夹:挂载到 PostgreSQL 内 /var/lib/postgresql/data 目录下,存储数据库

接着,确认运行 immich 的用户 id。群晖主用户一般是 1026:100 ,如果不确定,可以使用该用户登录 SSH 终端后输入 id username 查询。例如我的群晖用户名是 mikusa

$ id mikusa
uid=1026(mikusa) gid=100(users) groups=100(users),101(administrators),65537(docker)

那么,PUID 的值就是 1026PGID 的值就是 100。指定运行用户 user 的值就是 1026:100

随后,再创建一个 PostgreSQL 数据库密码。例如在 1password 的随机密码网页上随机生成一个。越复杂越好。

创建完需要的文件夹后,找个文件夹,比如 immich,在其中新建 compose.yml 文件,复制下方的配置并修改相应的环境变量,保存。

这个 compose.yml 文件直接复制保存即可,环境变量可以在后续的 .env 中修改。
services:
# immich本体:
  immich:
    image: ghcr.io/imagegenius/immich:latest
    container_name: immich
    environment:
      ## 常规部分
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      ## PostgreSQL部分
      - DB_HOSTNAME=immich_database
      - DB_USERNAME=postgres
      - DB_PASSWORD=${DB_PASSWORD} #PostgreSQL密码,注意修改
      - DB_DATABASE_NAME=immich
      ## Redis部分
      - REDIS_HOSTNAME=immich_redis
      - DB_PORT=5432 #默认
      - REDIS_PORT=6379 #默认
      - REDIS_PASSWORD= #默认
      ## 机器学习部分
      - MACHINE_LEARNING_GPU_ACCELERATION= #默认
      - MACHINE_LEARNING_HOST=0.0.0.0 #默认
      - MACHINE_LEARNING_PORT=3003 #默认
      - MACHINE_LEARNING_WORKERS=1 #默认
      - MACHINE_LEARNING_WORKER_TIMEOUT=120 #默认
    volumes:
# 假设 compose.yml 路径为 /volume1/docker/immich/compose.yml
# config 文件夹与 compose.yml 在同一级目录
# 那么可以直接使用 ./config 代表 /volume1/docker/immich/config
      - ./config:/config
      - ${PHOTOS_LOCATION}:/photos
      # - ${IMPORT_LOCATION}:/import #按需启用
    ports:
      - ${IMMICH_PORT}:8080 #暴露端口
    # devices:
    #   - /dev/dri:/dev/dri #英特尔硬件加速,根据实际情况启用
    restart: unless-stopped
    networks:
      - immich ##加入immich网络

# 这个容器需要一个外部应用程序单独运行才能单独运行。
# 默认情况下,数据库的端口是开放的,部署时要小心。
# 但被 mikusa 关掉了,有需要请自行打开。
# Redis缓存:
  immich_redis:
    image: redis
    container_name: immich_redis 
    # ports:
    #   - 6379:6379 #不暴露端口
    restart: unless-stopped
    networks:
      - immich ##加入immich网络

# PostgreSQL数据库:
  immich_database:
    image: tensorchord/pgvecto-rs:pg14-v0.2.0
    container_name: immich_database
    user: ${PUID}:${PGID}
    # ports:
    #   - 5432:5432 #不暴露端口
    environment:
      - TZ=${TZ}
      - POSTGRES_PASSWORD=${DB_PASSWORD} #PostgreSQL密码,注意修改,与上方配置需一致
      - POSTGRES_USER=postgres
      - POSTGRES_DB=immich
    volumes:
      - ./database:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - immich ##加入immich网络

networks:
  immich: ##自动创建immich网络,仅immich内部可用
    driver: bridge
由于我没有显卡,如果想启用 Nvidia 硬件加速的话,需要参考官方文档

接着,由于有不少共用的环境变量,因此改为使用 .env 文件方便修改变量。在 compose.yml 同级目录下创建名为 .env 的环境变量文件,填入以下内容:

IMMICH_PORT=8080 #immich暴露在外的端口,默认为8080,如与现存端口冲突请修改
PHOTOS_LOCATION=./photos #相册挂载路径,根据实际情况修改
#IMPORT_LOCATION=./import #外部存储库,如需启用,请先修改compose.yml对应挂载路径
PUID=1000 #用户UID
PGID=1000 #用户GID
TZ=Asia/Shanghai #时区
DB_PASSWORD=From_Himiku.com_By_mikusa #修改此处的数据库密码
请根据自己的实际情况修改环境变量。

随后使用 docker compose up -d 启动,最终的目录结构应该是这样的:

immich
├── compose.yml
├── config
│   └── machine-learning
├── database
├── import
└── photos
    ├── encoded-video #转码视频
    ├── library #图库
    ├── thumbs #缩略图
    ├── profile #用户头像,难以置信immich竟然给头像单独创建了文件夹
    └── upload #上传文件夹

如果按照官方教程的话,到这里就算结束了。但还记得我上面说过什么吗?我需要将照片通过 Cloud Sync 备份到其他云服务商。若是相册挂载路径直接使用 ./photos 或是 /volume1/homes/mikusa/Photos,在备份的时候就会连着把 librarythumbsuploadprofileencoded-video 都同步到云端去。可能你会说:「那我备份的时候选择只备份 library 就好了啊」,确实是这样没错(艹,写到这我才想起来 Cloud Sync 是可以选择备份文件夹的啊,我是沙比),但你也可以一劳永逸,把 photos 内的所有文件夹都手动挂载到别的地方,或者数据保留在 docker 文件夹内,照片保存在指定的图片文件夹中(妈妈,这个人还在嘴硬)

比如这样:

      - ./upload/encoded-video:/photos/encoded-video
      - ./upload/thumbs:/photos/thumbs
      - ./upload/upload:/photos/upload
      - ./upload/profile:/photos/profile
      - /volume1/homes/mikusa/Photos/immich:/photos/library #内部存储库
      - /volume1/homes/mikusa/Photos/pixiv:/import/pixiv #外部存储库

这样备份的时候,直接选择 /volume1/homes/mikusa/Photos 就可以,不用担心会把缩略图什么的都备份上去。(我和我最后的倔强,握紧双手绝对不放……)

接下来访问 ip:8080,就可以进入 immich 的配置界面了!

配置

反向代理

如果需要使用域名,有两种方案:nginx 反代 和 caddy 反代。这一步是不是该放在安装环节里来着?

nginx 麻烦的多。你需要配置一堆针对大文件上传的策略(SSL部分省略):

server {
    server_name immich.example.org;

    # 允许上传大文件
    client_max_body_size 50000M;

    # Set headers
    proxy_set_header Host $http_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;

    # enable websockets: http://nginx.org/en/docs/http/websocket.html
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;

    # set timeout
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    send_timeout 600s;

    location / {
        proxy_pass http://<immich_ip>:2283;
    }
}

caddy 就简单了,一共三行:

immich.example.org {
    reverse_proxy http://<immich_ip>:2283
}

这样,你就可以使用 https://immich.example.org 访问你的 immich 啦!

初始引导

虽然 immich 已经支持了简体中文,但初始引导界面还有不少未汉化完全的地方,且目前无法自行选择语言(可能后续更新会支持)。所以这里简单讲解一下引导设置的过程。

第一步,创建账户。安装完 immich 启动后的第一个用户默认是管理员账户。依次填入邮箱、密码以及昵称,点击 注册 按钮完成账户注册。

随后会要求使用刚创建的账户密码登录。假如你设完密码就给忘了,那就只能删掉重来了。

第二步,主题设置。按照提示设置程序的主题,目前只有日/夜两种模式可选。

第三步,存储模板配置。这个功能默认是关闭的,根据官方文档中关于《存储模板的实现方式》的解释,开启后可以自定义图片存储结构。适合文件夹强迫症用户。

以本文将图片挂载到 /photos 文件夹为例。不论你是否启用存储模板,/photos 文件夹中都会生成如下文件夹:

  • profile:用户个人资料图片
  • thumbs:存储缩略图
  • encoded-video :存储转码视频
  • upload:存储上传的图片,启用存储模板后,这个文件夹会变成临时中转站
  • library:启用存储模板后,图片会从 upload 移动至此

假如没有启用存储模板,即默认设置的状态下,图片会保存在 /photos/upload/<userID> 文件夹中,userID 可以在账户设置 -> 账户 -> 用户 ID 中找到,这个 ID 为字符串且唯一。

如果启用了存储模板,所有图片会被自动任务移动到 /photos/library/<userID> 文件夹中。这个 userID 和上面的情况一样,都是唯一的字符串。但管理员可以为用户额外设置存储标签(管理员有一个默认的 admin 存储标签。),该标签被设置后将会代替 <userID>。也就是说,图片会被保存到 /photos/library/admin 文件夹。

接着选择自己喜欢的存储模板。我选择的是 {{y}}/{{MM}}/{{dd}}/{{filename}},即最终图片会被保存在结构为 /2022/02/03/IMAGE_56437.jpg 的文件夹中。

存储模板设置完成后点击确认,即可进入 immich 的用户主界面。

修改语言

immich 现已支持中文!

不过不知道现在是不是设置完就按浏览器语言自动切换成简中了,假设不是,你可以参考下面的动图设置成中文。设置倒也不难:

  1. 点击右上角头像
  2. 点击 account setting 账户设置
  3. 在 app setting 应用设置中修改 language 语言为 chinese 简体中文

安装模型

Immich 是支持使用描述文字搜索图片的,但默认的机器学习模型是 ViT-B-32__openai,这个模型并不支持中文。好在官方提供的模型中,有一个 XLM-Roberta-Large-Vit-B-16Plus 可以使用中文搜索。

模型体积十分庞大,请自备代理方便下载。

首先,安装 Git LFS 以使 Git 支持下载超大型仓库。

Windows 可以下载安装包安装,或使用 scoop 一键安装:

scoop install git-lfs

群晖 NAS 就有些复杂了,需要手动安装 Git LFS。

登录 SSH 终端后,下载 LFS 安装文件:

wget https://github.com/git-lfs/git-lfs/releases/download/v3.5.1/git-lfs-linux-amd64-v3.5.1.tar.gz

解压后进入文件夹,执行安装命令:

tar -zxvf git-lfs-linux-amd64-v3.5.1.tar.gz
cd git-lfs-3.5.1
sudo ./install.sh

随后启用 Git LFS:

git lfs install

输出以下提示即可:

$ git lfs install
Git LFS initialized.

接着,进入 immich 存放模型的文件夹。

本文使用的 imagegenius/immich 将模型放在了 /config/machine-learning/models/clip 文件夹中,因此:

cd /volume1/docker/immich/config/machine-learning/models/clip

拉取模型:

git clone https://huggingface.co/immich-app/XLM-Roberta-Large-Vit-B-16Plus

下载完成后,在 immich 设置中修改机器学习使用的 CLIP 模型。

在任务中重新完整执行一遍智能搜索。

这样不管是英文还是中文,都可以搜索到结果了。

上传

一切准备完毕,就该充实图库了。

上传图片无非两种方式:网页 / app 端直接上传,或本地使用 immich CLI 命令行上传。网页 / app 端不作演示,这里重点说一说命令行上传。

在本地有大量图片需要上传,但又想通过 immich 上传的时候自动过滤重复图片(immich 上传图片时会计算哈希值,雷同的图片或视频会自动跳过),就可以使用 immich CLI 上传图片。

首先需要确保 PC 或 NAS 上安装了 npm

Windows11 可以使用系统自带的 winget 一键安装 npm:

winget install OpenJS.NodeJS

或使用 scoop:

scoop install nodejs

或下载安装包手动安装。

群晖 NAS 可以在套件中心中安装 Node.js 套件,即可使用 npm。

随后安装 immich CLI:

npm i -g @immich/cli

安装完毕后,键入 immich 当有如下内容输出:

$ immich
Usage: immich [options] [command]

Command line interface for Immich

Options:
  -V, --version                       output the version number
  -d, --config-directory <directory>  Configuration directory where auth.yml will be stored (default:
                                      "C:\\Users\\mikusa\\.config\\immich\\", env: IMMICH_CONFIG_DIR)
  -u, --url [url]                     Immich server URL (env: IMMICH_INSTANCE_URL)
  -k, --key [key]                     Immich API key (env: IMMICH_API_KEY)
  -h, --help                          display help for command

Commands:
  login|login-key <url> <key>         Login using an API key
  logout                              Remove stored credentials
  server-info                         Display server information
  upload [options] [paths...]         Upload assets
  help [command]                      display help for command

接着,在 immich 设置中创建一个 api key 备用。

回到终端中,使用 immich login <url> <key> 的格式连接到 immich,例如:

immich login http://192.168.31.3:8080 eeffggssssseIxxxxxxxyucxxxccTvvvsswwee

有如下提示输出即代表登录成功:

$ immich login login http://192.168.31.3:8080 eeffggssssseIxxxxxxxyucxxxccTvvvsswwee
Logging in to http://192.168.31.3:8080
Logged in as mail@email.com
Wrote auth info to /home/mikusa/.config/immich/auth.yml

随后就可以直接上传图片了:

immich upload file1.jpg file2.jpg

也可以上传一整个文件夹。默认不包括子文件夹,如需上传包含子文件夹的文件夹,需加上 --recursive

immich upload --recursive directory/

如果只是想测试,可以加上 --dry-run 看看会发生什么:

immich upload --dry-run --recursive directory/

使用 --skip-hash 跳过哈希检测,在确定没有重复图片的前提下:

immich upload --skip-hash --recursive directory/

使用 --album 根据文件夹名称自动创建相册:

immich upload --album --recursive miku/

或使用 --album-name 上传到指定相册:

immich upload --album-name "初音未来" --recursive miku/

immich 支持使用 glob 模式跳过上传某些特定名称的图片。例如 --ignore **/Raw/** 将跳过上传名为RAW 的文件夹:

immich upload --ignore **/Raw/** --recursive directory/

或者跳过指定后缀:

immich upload --ignore **/Raw/** **/*.tif --recursive directory/

这样就能在上传经过群晖生成缩略图的文件夹时,跳过 @eaDir 文件夹了。不过我还没测试过。

具体操作还是要多看看官方文档

使用

外部图库

挂载外部图库到 immich 后,再在设置中简单配置一下,就可以管理外部图片。

一开始 immich 是不支持删除外部图库中的图片的,但最近解除了这个限制。配合下面的重复图片检测工具,可以做到删除外部图库外的重复文件。

例如我有个专门的 pixiv 文件夹,而手机有时候会下载重复的图片,可以在重复图片检测后删掉手机中的备份,保留外部图库中的图片。

创建外部图库就不演示了,现在有汉化,很好操作。

探索

其实是探索地点,不过地点是拼音显示的。

地图

定位会走代理。

收藏

相册

工具

工具中目前只有一个重复图片检测,可以快速检测重复项并择一删除。该功能还在不断优化更新中。

如果觉得扫出来的重复图片不够多,可以在任务里重新完整地扫描一遍。

回收站

回收站中的项目将在30天后被永久删除。

客户端

在 immich 的 github 页面下载安卓客户端,或是在 App Store 搜索 immich 安装 iOS 客户端。

这玩意应该不用我教了吧?备份手机相册的时候,可以选择具体相册备份,或是直接选择 Recent 备份所有图片。

不过这里的提示「单击选中,双击取消」其实是指「单击选中,双击排除」。

其他

Homepage

如果有在使用 homepage,有一个小组件供使用。

services.yaml 内加入以下配置:

    - immich:
        icon: immich.png
        href: https://photos.example.com
        widget:
          type: immich
          url: https://photos.example.com
          key: YOUR_IMMICH_KEY

隐藏许可入口

最近更新了个非常显眼的许可入口,官方声称只是鼓励用户捐赠,并不会在功能上有任何限制。

这价格……就算我有心捐赠,也捐赠不起啊……
这价格……就算我有心捐赠,也捐赠不起啊……

好在可以自定义css 屏蔽掉。在右上角管理 -> 设置 -> 主题设置中,粘贴以下自定义 css

.license-status {
    display: none !important;
}

总结

经过我这一番长篇大论,你觉得 immich 看起来怎么样?我是感觉不错。安卓手机开启备份,苹果手机上也能看到图片,就是不能安卓手机删除备份自苹果手机的图片后,联动删除苹果手机上的图片。但目前我实现了利用 OneDrive 实现全平台删除备份自 Windows 设备上的图片,综合体验起来还是不错的。

所以,有兴趣就来试试吧!可以在动手前看看 官方demo

参考