Skip to content
twinkling.top服务ImmichEN
板型Pi 4B 8GB; on a 4GB board disable the ML container or faces will not be recognised
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

部署配方 · 媒体

Pi 4 上的 Immich:一个能熬过换手机的相册

Immich 补上了人们真正舍不得 Google Photos 的那部分:手机自动上传、能一直往下滚的时间线、可以分享的相册、还有人脸识别。它同时也是这台机架上最重的服务:四个容器,加一个需要官方镜像里拿不到的扩展的 Postgres。下面是能跑在 8GB Pi 4B 上的版本,包含两个能避免它把整个下午都耗在重跑机器学习流水线上的设置。

ghcr.io/immich-app/immich-server:v1.129.0 · 2026-09-07

Immich rack plate: board stack and host ports
服务参数
容器镜像ghcr.io/immich-app/immich-server:v1.129.0
宿主端口:2283/tcp
数据目录/srv/homelab/immich/library
内存预留1300 MB
CPU 上限1.5 vCPU (cpus: "1.5") — the machine learning container is the only reason it needs more than one
更新节奏monthly. Immich ships breaking changes with a migration script; read the release notes before pulling, and never skip a release that carries a migration
ARM 兼容arm64 native for both server and machine learning containers; CLIP and face models run on CPU and a Pi 4 spends about four seconds per new photo on them
端口映射与暴露面
宿主容器proto暴露用途
:22832283tcp仅局域网web UI, the phone apps and the upload API

部署步骤

  1. 按各容器的要求建好四个目录

    服务端以自己的 uid 写入,Postgres 需要 999,机器学习缓存目录只要存在即可。Postgres 的属主搞错,容器会一直重启,日志里是一行权限错误。

    run
    sudo mkdir -p /srv/homelab/immich/{library,db,model-cache}
    sudo chown -R 1000:1000 /srv/homelab/immich/library
    sudo chown -R 999:999 /srv/homelab/immich/db
  2. 把数据库密码生成到 env 文件里

    这套里每个容器都从 compose 的环境变量读同一个密码。生成一次、之后再也不手打,是让它们保持一致的唯一办法。

    run
    echo "IMMICH_DB_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=')" >> /srv/homelab/.env
    chmod 600 /srv/homelab/.env
  3. 先起数据库,等健康检查通过

    服务端启动时会执行数据库迁移。对着一个还在初始化的数据库启动它,会得到看起来像数据库损坏的迁移错误。

    run
    cd /srv/homelab/immich && docker compose up -d immich-db immich-redis
    until docker exec immich-db pg_isready -U immich; do sleep 2; done
    docker compose up -d
  4. 建好家人账号,然后关闭注册

    用注册表单创建的第一个账号会成为管理员。把其他人加完,再去管理设置里关掉注册——一次点击,实例就对陌生人关上了门。

    run
    # 管理 -> 设置 -> 用户设置 -> 关闭「注册」
    # 然后在 管理 -> 用户 -> 创建用户 里逐个建账号
  5. 分阶段导入,并且盯着温度

    被动散热的 Pi 4 在大批量导入时会冲到 80 度并开始降频,结果导入变得更慢。第一次导入时看着温度,考虑先加个风扇。

    run
    vcgencmd measure_temp
    docker stats --no-stream immich-server immich-ml

四个容器,各自花掉多少

这套包含一个服务端、一个带向量扩展的 Postgres、一个 Redis 队列,以及一个机器学习工作进程。在树莓派上,需要认真考虑的是机器学习那个:它给每张新照片做 CLIP 向量和人脸检测要花大约四秒 CPU 时间,手机上传二十张无所谓,第一次导入四万张就很痛苦。

容器内存职责能不能砍掉
immich-server1.1 GBAPI、网页界面、缩略图、转码不能
immich-db400 MB带 vectorchord 和 pgvecto.rs 的 Postgres不能
immich-redis45 MB缩略图与机器学习的任务队列不能
immich-ml峰值 700 MBCLIP 搜索与人脸识别能,代价是没有搜索和人脸

第一次导入才是难关

开着机器学习导入四万张照片,Pi 4 大约要两天后台时间,期间板子发烫、上面其它服务都变慢。分阶段做要好得多:先关掉机器学习导入,等缩略图和元数据跑完,再在夜里开启机器学习,让它分批把库过一遍。

任务并发设置是让这件事变得可忍受的关键。默认值是按有富余核心的服务器定的;在派上把缩略图和机器学习的并发都设成 1,机架其它部分才不会跟着卡。

shell
docker exec -it immich-server immich-admin list-jobs
# 然后在管理界面:设置 -> 任务设置 -> 缩略图生成 / 智能搜索
# 并发设为 1,并且手动启动任务,别让它自己排队

为什么数据库不能用官方 Postgres 镜像

Immich 的智能搜索把图像向量存成向量类型,并按余弦距离查询。这需要 vectorchord 和 pgvecto.rs 扩展,而官方 postgres 镜像里没有,所以项目自己发布了一个镜像。换成朴素的 postgres:16,你会得到一个能启动、上传也正常、但一跑智能搜索就报错的服务端。

同样的原因,这个数据库也不是能随手搬到托管服务上的东西。数据卷留在本地固态盘,pg_dump 的备份例程也要留着。

shell
docker exec immich-db psql -U immich -d immich -c '\dx'
# 列表里应该能看到 vectorchord 和 vectors 两个扩展

存储布局与外部媒体库的问题

默认情况下 Immich 会把每次上传复制进它自己的媒体库目录,并按用户和日期组织。这是对的默认行为:文件归它管,数据库是唯一事实来源。

外部媒体库则是指向 NAS 上已有目录、就地索引。手里已经有一份 300GB 照片目录的人想要的就是这个,而且它确实能用——但那个目录必须以只读挂载,否则 Immich 会按它自己的结构去移动和重命名文件,而你对那套结构本来是有想法的。

shell
# 外部媒体库挂载,故意设成只读
      - /mnt/nas/photos-archive:/mnt/photos-archive:ro

compose 文件

整份文件放在 /srv/homelab/immich/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:v1.129.0
    container_name: immich-server
    restart: unless-stopped
    ports:
      - "2283:2283/tcp"
    environment:
      TZ: Asia/Shanghai
      DB_HOSTNAME: immich-db
      DB_USERNAME: immich
      DB_PASSWORD: ${IMMICH_DB_PASSWORD}
      DB_DATABASE_NAME: immich
      REDIS_HOSTNAME: immich-redis
      IMMICH_MACHINE_LEARNING_URL: http://immich-ml:3003
    volumes:
      - /srv/homelab/immich/library:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      immich-db:
        condition: service_healthy
    networks: [rack]

  immich-ml:
    image: ghcr.io/immich-app/immich-machine-learning:v1.129.0
    container_name: immich-ml
    restart: unless-stopped
    volumes:
      - /srv/homelab/immich/model-cache:/cache
    networks: [rack]

  immich-redis:
    image: redis:7.4-alpine
    container_name: immich-redis
    restart: unless-stopped
    networks: [rack]

  immich-db:
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
    container_name: immich-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: immich
      POSTGRES_PASSWORD: ${IMMICH_DB_PASSWORD}
      POSTGRES_DB: immich
    volumes:
      - /srv/homelab/immich/db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U immich"]
      interval: 10s
      timeout: 5s
      retries: 6
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 建完家庭成员的账号后关闭注册,任何人找到这个网址也进不来
  • 上传只在局域网内或通过 WireGuard 进行,不做端口转发
  • 数据库只在容器网络内监听,完全不发布端口
  • 机器学习容器不发布端口,除首次启动下载模型外不需要外网

备份方案

媒体库就是一棵结构可读的普通目录,每晚用 rsync 同步到 NAS,再由 NAS 负责异地备份。数据库要单独用 pg_dump 导出——没有它,相册、人脸、以及文件与日期之间的对应关系都会丢失,媒体库就退化成一堆命名正确但毫无组织的文件。

上线后验证

  • 手机 App 上传的照片几秒内出现在时间线里,并且生成了缩略图
  • 智能搜索一个明显的词比如「狗」能出结果,说明向量扩展和机器学习进程都在工作
  • 每晚的 pg_dump 能恢复到临时库里,且素材条数一致
  • 磁盘上的媒体库目录里是能读懂的年份文件夹,即使没有数据库这些文件也是可用的

踩过的坑

  • 把官方发布的 Postgres 镜像换成通用镜像,智能搜索一跑就会报扩展错误,而界面上没有任何地方会告诉你「数据库镜像不对」。
  • 在大库的第一次导入时就开机器学习,会让这台派当两天的暖风机。先导入,后索引。
  • 把外部媒体库挂成可写,就是人们某天早上醒来发现归档被重新整理的原因。挂成只读,让 Immich 去索引而不是去管理。
  • 视频转码设置默认开启硬件加速,而树莓派在多数编码格式上并没有对应的硬件。保持软件转码并把并发调低,比和预设较劲省事。

硬件与选型问答

Pi 4 真的够跑 Immich 吗,还是该交给 NAS?
8GB 的 4B 能处理五到八万张的家庭库,前提是分阶段导入、机器学习并发保持为 1。x86 的 NAS 会更快也更凉快,但那也意味着你的照片库和备份存在同一台机器上。
第一次导入到底要多久?
缩略图和元数据:Pi 4 上大约每分钟两百张,四万张约三个半小时。开启机器学习后,整个库每张再加约四秒,这就是「两天」这个数字的来源。
能不能一边继续用 Google Photos?
可以,而且头一个月就应该这样。两边同时跑,并行上传到 Immich,等你能从 Immich 里真正恢复一张照片、确认备份可用之后,再取消另一个订阅。这次迁移可不是按人们以为的方向能回头的。