(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
- Make a backup of your current library and save a copy of the following database dump
- 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";
};
-
Stop NixOS Immich
systemctl stop immich-server.service immich-machine-learning.service
-
Stop Docker Immich. Leave your postgres container running
-
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
-
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
-
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.
- 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;
-
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
-
Start NixOS Immich
systemctl start immich-server.service immich-machine-learning.service
-
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.
This was great.
For my
sed
, I usedsed "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 anupload/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/
.