Skip to content

Instantly share code, notes, and snippets.

@V3ntus
Created September 25, 2024 03:47
Show Gist options
  • Save V3ntus/8f28c7965c085bb99a9b51904ebd8248 to your computer and use it in GitHub Desktop.
Save V3ntus/8f28c7965c085bb99a9b51904ebd8248 to your computer and use it in GitHub Desktop.
Migrating existing Immich to NixOS

(Original comment from scrumplex)

I was able to migrate my Docker Compose deployment. An issue I ran into was that file paths in the database were relative to immich's working directory, meaning that everything was prefixed with upload/. I was able to remedy this by replacing upload/ with my mediaLocation (which is also what the UPLOAD_LOCATION variable from my Compose deployment pointed to).

Note

This is what worked for my installation that is a few years old. I am not sure if newer installations behave differently. Some facts about my Docker Compose installation:

  • The database is called immich
  • The database user is called immich
  • My UPLOAD_LOCATION (docker mount path) is set to /media/immich-library
  1. Make a backup of your current library and save a copy of the following database dump
  2. Enable NixOS Immich and switch. This will start an empty instance of Immich but will create the database and database user for us.1 In my case it looked like this:
services.immich = {
  enable = true;
  mediaLocation = "/media/immich-library";
};
  1. Stop NixOS Immich

    • systemctl stop immich-server.service immich-machine-learning.service
  2. Stop Docker Immich. Leave your postgres container running

  3. Dump your database. The following command is going to dump it into Postgres' data directory, so it will be easy to access from your host system.

    • docker compose exec database pg_dump --user immich -f /var/lib/postgresql/data/dump.sql immich
  4. Fix unset search_path variable.2

    • sed -i "s#SELECT pg_catalog.set_config('search_path', '', false);#SELECT pg_catalog.set_config('search_path', 'public', false);#" </path/to/immich/compose>/postgres/dump.sql
  5. Replace upload/ path prefix.3 In my case I replace it with /media/immich-library.

    • sed -i "s#upload/#/media/immich-library#g" </path/to/immich/compose>/postgres/dump.sql

Warning

In cases where a file is somehow stuck in your <library>/uploads/ folder, the previous sed command will create an invalid path (i.e. upload/upload/... -> /media/immich-library//media/immich-library/...). Make sure to catch these cases if present. In my case there was a single file that was referenced like this in the assets table and I was able to fix it manually after the fact.

  1. Prepare NixOS database
sudo -u postgres psql immich
immich=# <paste following codeblock and exit>
DROP SCHEMA public CASCADE;
DROP SCHEMA vectors CASCADE;

CREATE SCHEMA public;

CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS vectors;
CREATE EXTENSION IF NOT EXISTS cube;
CREATE EXTENSION IF NOT EXISTS earthdistance;
CREATE EXTENSION IF NOT EXISTS pg_trgm;

ALTER SCHEMA public OWNER TO immich;
ALTER SCHEMA vectors OWNER TO immich;
GRANT SELECT ON TABLE pg_vector_index_stat TO immich;

ALTER EXTENSION vectors UPDATE;
  1. Import your dump. Make sure the file is readable. I moved it to a location that is readable by the postgres user.

    • sudo -u postgres psql immich -f </path/to/immich/compose>/postgres/dump.sql
  2. Start NixOS Immich

    • systemctl start immich-server.service immich-machine-learning.service
  3. Make sure you can actually view images on the web app.

If any of these steps fail, you should have your original (unmodified!) database as well as a backup of your media location.

1: As a precaution, you could make your existing Immich library read-only (i.e. chown -R root:root /media/immich-library) to avoid any modifications done by this empty installation of Immich.
2: Restoring a dump that uses Postgres earthdistance seems to fail if search_path isn't set to the target schema. See this StackOverflow comment
3: Perhaps you can inspect your database dump for this first. In my case every file reference started with upload/ (i.e. upload/thumbs/ instead of just thumbs/)

I hope this helps someone out there trying to get this working.

@oberon227
Copy link

This was great.

For my sed, I used sed "s#\tupload#\t/immich-data/photos#g" ./immich-fixed-search-path.sql > ./immich-final.sql

In this case, /immich-data/photos is where my library is (it was my UPLOAD_LOCATION on the container version). I'm searching for the tab character (\t) before the "upload" so that I don't catch the second "upload" in an upload/upload situation. I make sure to add the tab character back in on the replace side.

And for anyone who was like me and was confused by the use of # in the substitution, apparently you can use any character as a delimiter! It's just that most people use /.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment