Files
homelab-gitops/apps/immich

Immich on arschrock

Argo CD installs the upstream Immich chart directly; there is no homelab application/chart repository. The chart's upstream application release tag is selected in values.yaml. The Immich server and machine-learning workload are pinned to arschrock; only the existing /mnt/Bilder bcachefs library is host-local. Immich PostgreSQL and Valkey run separately in this namespace with Ceph-backed storage.

The local PV is retained and bound to /mnt/Bilder. It does not copy or move the photo library. The server has a read-only startup check for the bcachefs filesystem magic and expected upload directory, in addition to a node label that prevents scheduling until the host helper confirms the mount.

~/unmount.sh runs storage-offline.sh, waits for the Immich Pods and kubelet local volume mounts to disappear, unmounts the other bcachefs mounts, and then unmounts /mnt. If unmounting manually, run bash apps/immich/scripts/storage-offline.sh from this repository first and stop if it fails. After remounting /mnt, ~/mount_binds.sh runs storage-online.sh; it validates bcachefs and the Immich upload directory, forces fresh Pod mounts, and then restores the readiness label. These helpers assume the default context kubernetes-admin@kubernetes and refuse other contexts. No systemd hook controlling /mnt was found during migration setup, so a future systemd-based mount change must explicitly order these helpers before unmount and after mount.

The database operator creates its application password Secret automatically; the cleartext credential is not stored in Git. The initial restore preserves the source database's PostgreSQL 18.6 and pgvector extension versions. The shared Valkey instance is not copied wholesale: only keys identified as Immich-owned are imported, leaving all other applications' keys untouched.

Monitoring

The dashboard combines Immich's own metrics with container and CloudNativePG metrics. CloudNativePG's custom query reads an aggregate-only database view to show photos, videos, and Immich-reported storage by user GUID. It runs on the primary only. The exporter can read this view but not the underlying asset or user tables. After restoring the database from a backup, run bash apps/immich-postgresql/scripts/ensure-metrics-view.sh from the GitOps repository root to recreate the view and its grant if necessary. The storage figure comes from Immich's quotaUsageInBytes, not a filesystem scan.

The old Podman stack and host PostgreSQL must remain available as rollback sources until the new application, database, monitoring, and routes have been verified. Never run both Immich servers against /mnt/Bilder concurrently.

The migration dumps are retained with mode 0600 under /home/feedc0de/immich-app/backups/k8s-migration-20261022/. The source PostgreSQL database and shared Valkey keys were left intact. After the new instance begins accepting writes, a rollback must first stop the Kubernetes server and ML pods with bash apps/immich/scripts/storage-offline.sh, then dump the current Kubernetes database and restore it to the preserved host PostgreSQL before starting Podman. The new database stores the media root as /usr/src/app/upload; the old Compose file mounts it at /data, so change that mount to /usr/src/app/upload when restoring the new database. Do not restore the pre-migration dump after new writes, because it would discard them. Keep the Ceph-backed PostgreSQL/Valkey volumes and /mnt/Bilder untouched until rollback is no longer needed.