Setting up Immich
Background
I recently upgraded my Synology NAS to the DS923+, from the aged DS218play. Naturally, the next day Synology announced new models, but the DS923+ should still take care of me for at least 5 years. The old NAS will be put out to pasture as an off-site backup target.
Part of my reason for upgrading was to be able to add more than the piddly 1GB of RAM. I threw a 16GB OWC stick into the new NAS, so combined with the 4GB stick it shipped with I have 20GB of RAM. Let me tell you, 1GB is not enough in 2025 if you want to serve files in anything like a timely fashion.
Set-up
With the extra RAM and ability to run containers, I set up Portainer and then Immich. Portainer bugs you to upgrade to the business edition, which is annoying but doesn't seem to impede it much—I don't need the business features, so I can put up with the nags. Immich is what I hope to fully replace Google Photos with for me and my family. With Google cozying up to the fascist-in-chief, removing Google products from my life is becoming a higher priority, and Google Photos is one of the top two of their products that I use most often.
I copy/pasted the Immich compose file (and .env) into the Portainer web editor, and that worked fine stock. Where things got exciting was migrating my photos from Synology Photos, which I've been running in parallel to Google Photos. I planned to use the Immich CLI to upload the photos, which meant it would be easiest to run it from the container and mount the photos as a volume. Their current location, in my user directory, isn't an NFS share so it couldn't be mounted as a volume. I made a copy into a new NFS share, then made a mount in Portainer.
When I set up the NFS share, I gave the local hostname (not localhost
) as the host, since it would be accessed from a container on the same machine. I don't know if that's the best way to go about it, but the share didn't need to stick around and it was the only setting I changed.
Then I added the mount to stack. Here's the final compose for the stack:
#
# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose
#
# Make sure to use the docker-compose.yml of the current release:
#
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
#
# The compose file on main may not be compatible with the latest release.
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
volumes:
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
- photos:/usr/src/app/photos
env_file:
- stack.env
ports:
- '2283:2283'
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- model-cache:/cache
env_file:
- stack.env
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
volumes:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
healthcheck:
test: >-
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
echo "checksum failure count is $$Chksum";
[ "$$Chksum" = '0' ] || exit 1
interval: 5m
#start_interval: 30s
start_period: 5m
command: >-
postgres
-c shared_preload_libraries=vectors.so
-c 'search_path="$$user", public, vectors'
-c logging_collector=on
-c max_wal_size=2GB
-c shared_buffers=512MB
-c wal_compression=on
restart: always
volumes:
model-cache:
photos:
external: true
The environment variables are stock, except of course that I changed the Postgres password.
And finally, I had to run the Immich CLI in order to upload the assets. To do that, I opened up the console to the immich-server
container in Portainer.
$ immich login http://<my-hostname>:2283/api <my-key>
$ immich upload --ignore **/SYNPHOTO** --recursive photos/
I'm not entirely sure that the --ignore
flag worked the way I intended, since the syntax is a little unusual. I hoped to ignore the Synology Photos thumbnails, but worst case I'll write a script to clean them up manually.
For a brief time, I had 3 copies of my 800GB of photos on my NAS. Luckily, I had plenty of space for that, but it was still silly. If you're going straight from a Google Photos take-out, you could use immich-go instead.
I'd like to move my secrets into a secrets manager and then sync all of my configs to a git repo, probably on Codeberg and/or sr.ht. That's a problem for another day, though.
Wrap-up
I drafted this post a few days ago, and I think I hear my NAS finally cooling down. The CPU has been pegged to 100% for a couple days and the drives have been chugging. But I can already access the photos in Immich, and I'm loving the experience.