Immich self-hosting: wymagania i aktualizacja
Analiza zużycia 6 GB RAM oraz błędu pgvecto.rs w wersji v3. Dowiedz się, jak uniknąć błędu exit 137 i poprawnie skonfigurować port 2283 pod HTTPS.
Cel projektu
Immich to usługa do samodzielnego hostowania kopii zapasowych zdjęć i filmów — pełna alternatywa dla Google Photos. Posiada aplikację mobilną, która przesyła bibliotekę zdjęć w tle, oś czasu, albumy, rozpoznawanie twarzy oraz wyszukiwanie oparte na uczeniu maszynowym, które lokalizuje obiekty takie jak "beach" lub konkretne osoby bez konieczności ręcznego tagowania. Usługa działa na własnym serwerze VPS, pliki źródłowe pozostają na dysku, a dane nie są skanowane w celach marketingowych.
Instalacja polega na uruchomieniu czterech kontenerów za pomocą pliku Docker Compose dostarczonego przez projekt. Proces ten zajmuje dziesięć minut. Pozostała część przewodnika dotyczy problemów technicznych: kontener machine-learning zużywa dużo pamięci RAM na słabszych maszynach, pliki źródłowe szybko zajmują miejsce na dysku, aplikacja mobilna wymaga szyfrowanego połączenia (nie obsługuje protokołu HTTP) oraz częste zmiany w kodzie (breaking changes) mogą spowodować, że nieostrożny docker compose pull uniemożliwi uruchomienie bazy danych. Prawidłowa konfiguracja tych czterech elementów zapewnia stabilność systemu Immich. Zignorowanie ich spowoduje problemy podczas eksploatacji.
Wymagania wstępne i znane problemy
- RAM: oficjalna dokumentacja zaleca minimum 6 GB i rekomendowane 8 GB — przyjmij, że 4 GB plus swap to absolutne minimum. Kontenery
immich-serveroraz Postgres zużywają mało zasobów. Kontenerimmich-machine-learningjest najbardziej obciążający — ładuje modele CLIP oraz face-recognition do pamięci RAM w celu budowy indeksów wyszukiwania; na maszynie z 2 GB system operacyjny może przerwać proces (OOM killer). Należy dodać swap nawet przy 4 GB RAM. - Dysk: rozmiar musi uwzględniać całą bibliotekę oraz zapas. Oryginalne pliki są kopiowane w całości, dodatkowo Immich generuje miniatury i podglądy (ok. 10–20% dodatkowego miejsca). Kolekcja zdjęć o rozmiarze 200 GB wymaga wolumenu 300 GB. Postgres zajmuje relatywnie mało miejsca.
- CPU: każdy nowoczesny VPS z KVM jest odpowiedni, jednak uczenie maszynowe (ML) na CPU działa wolno. Indeksowanie smart-search dla dużego importu może trwać wiele godzin w tle. Jest to zjawisko normalne; proces nie wymaga jednostki GPU.
- Nazwa domeny skierowana na adres VPS. Aplikacja mobilna wymaga połączenia HTTPS, dlatego zalecane jest użycie reverse proxy. Jest to konfiguracja analogiczna do instancji self-hosted Nextcloud z Docker, TLS i backupami — Immich jest odpowiednikiem tego serwera plików dla zdjęć.
- Zainstalowane Docker oraz plugin Compose — Docker Engine wraz z pluginem Compose v2 z oficjalnego repozytorium apt, zgodnie z instrukcją w naszym przewodniku po podstawach Docker Compose.
Krok 1: Dodaj swap przed innymi operacjami
Najczęstszą przyczyną awarii Immich na małych instancjach VPS jest proces OOM-kill w kontenerze ML. Należy najpierw zapewnić jądru systemu dodatkową pamięć.
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -hfree -h powinien teraz wyświetlać linię Swap: o wartości 4.0Gi. Nie zwiększy to prędkości ML, ale zapobiegnie wyłączaniu kontenera podczas indeksowania na maszynach z 4 GB RAM.
Step 2: Pobierz oficjalny plik compose oraz env — użyj oryginalnych plików, a nie kopii
Immich przypisuje konkretne wersje usług oraz, co kluczowe, obraz bazy danych w dostarczanych plikach. Nie należy traktować pliku compose z bloga (w tym tego) jako źródła prawdy. Należy pobrać zasoby wydania (release assets):
sudo mkdir -p /opt/immich && cd /opt/immich
sudo wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
sudo wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.envPochodzą one z oznaczonego wydania, więc referencje obrazów są zgodne. Plik compose definiuje cztery usługi. Warto znać ich przeznaczenie przed rozpoczęciem konfiguracji:
immich-server(ghcr.io/immich-app/immich-server, kontenerimmich_server) — API oraz interfejs webowy, nasłuchujące na porcie2283. Montuje pliki przesłane w lokalizacji/data.immich-machine-learning(ghcr.io/immich-app/immich-machine-learning, kontenerimmich_machine_learning) — wyszukiwanie CLIP oraz rozpoznawanie twarzy. Przechowuje modele w wolumeniemodel-cache. Usługa ta wymaga dużej ilości pamięci RAM.database(kontenerimmich_postgres) — Postgres z rozszerzeniem wektorowym VectorChord, które obsługuje wyszukiwanie podobieństwa. Tag obrazu jest przypisany za pomocą skrótu digest bezpośrednio w pliku compose, na przykładghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:.... Starsze instalacje używałypgvecto.rs; wsparcie dla tego rozwiązania zostało usunięte w Immich v3.0, zatem każda nowa instalacja używa VectorChord. Nigdy nie należy ręcznie edytować tego tagu.redis(kontenerimmich_redis) — instancja Valkey/Redis obsługująca kolejki zadań.
Krok 3: Konfiguracja .env — lokalizacja zdjęć i bazy danych
Otwórz .env i ustaw cztery parametry. Wszystkie ustawienia poniżej zaznaczonej linii pozostają bez zmian.
# Where original uploads are stored on the host
UPLOAD_LOCATION=/opt/immich/library
# Where the Postgres data lives. NEVER put this on an NFS/network share.
DB_DATA_LOCATION=/opt/immich/postgres
# "v3" is a floating tag that tracks the latest v3.x. Pin a full tag like
# v3.0.2 instead — then you upgrade on purpose, not by surprise.
IMMICH_VERSION=v3.0.2
# Change this to a long random string. Letters and digits only.
DB_PASSWORD=REPLACE_WITH_A_LONG_RANDOM_STRING
# Set your timezone so timestamps and "on this day" line up
TZ=Europe/London
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immichDwie zasady zapobiegające problemom. UPLOAD_LOCATION musi wskazywać na duży dysk — jeśli później zostanie podłączony wolumen danych, należy od początku ustawić tutaj ścieżkę montowania tego wolumenu, ponieważ późniejsza zmiana wymaga przenoszenia miniatur i aktualizacji ścieżek zasobów. DB_DATA_LOCATION musi znajdować się na dysku lokalnym: baza Postgres na zasobach NFS lub SMB ulega uszkodzeniu, co jest wyraźnie wskazane w dokumentacji. Użycie wyłącznie liter i cyfr w DB_PASSWORD pozwala uniknąć błędów związanych z ucieczką znaków (escaping) w ciągach połączeń.
Step 4: Pierwsze uruchomienie i tworzenie użytkownika admin
cd /opt/immich
sudo docker compose up -d
sudo docker compose psPoprawny wynik to cztery kontenery, wszystkie w stanie running, a docelowo healthy:
NAME STATUS
immich_machine_learning Up (healthy)
immich_postgres Up (healthy)
immich_redis Up (healthy)
immich_server Up (healthy)Pierwszy up pobiera kilka gigabajtów obrazów, należy odczekać. Postęp można monitorować za pomocą sudo docker compose logs -f immich-server; po zakończeniu procesu serwer loguje informację o nasłuchiwaniu na porcie 2283. Następnie należy otworzyć http://YOUR_SERVER_IP:2283 w przeglądarce. Podczas pierwszej wizyty wyświetli się kreator Getting Started — pierwsze utworzone konto otrzymuje uprawnienia administratora. Należy ustawić silne hasło; konto to zarządza ustawieniami serwera, użytkownikami oraz konfiguracją ML, która będzie wymagana w przyszłości.
Krok 5: Aplikacja mobilna i kopia zapasowa w tle
Zainstaluj "Immich" ze sklepu App Store lub Play Store. Na ekranie logowania wymagany jest Server Endpoint URL. Należy wpisać pełny adres URL wraz z protokołem, na przykład https://photos.example.com (aplikacja automatycznie dodaje /api). Zaloguj się na nowo utworzone konto, następnie otwórz ekran Backup w aplikacji, wybierz albumy do zabezpieczenia (zazwyczaj Camera i Screenshots) i włącz funkcję Background backup. System iOS ogranicza procesy działające w tle — przesyłanie danych w trybie foreground odbywa się zawsze, natomiast w trybie background odbywa się tylko wtedy, gdy system na to pozwoli.
To najczęstszy powód problemów, dlatego przed próbą konfiguracji aplikacji należy zapoznać się z Krokiem 6.
Krok 6: HTTPS przez reverse proxy — oraz zasada pełnego adresu URL
Aplikacja mobilna wymaga protokołu HTTPS. Należy umieścić reverse proxy przed portem 2283 i tam zakończyć sesję TLS. W przypadku korzystania z wielu kontenerów, najbardziej przejrzystym rozwiązaniem jest Traefik z automatycznym TLS dla wielu aplikacji Docker. Jeden blok etykiet (label) przekierowuje photos.example.com do kontenera immich-server i automatycznie pobiera certyfikat. W przypadku wyboru nginx, instrukcja Let's Encrypt z Certbot i nginx pozwala uzyskać certyfikat oraz blok proxy_pass http://127.0.0.1:2283;. Dla Immich kluczowa jest jedna konfiguracja proxy: należy zwiększyć limit rozmiaru przesyłanych plików, ponieważ nagrania wideo z telefonu są duże. W nginx parametrem tym jest client_max_body_size 50000M; wewnątrz bloku server — domyślna wartość 1 MB powoduje odrzucenie przesyłania wideo z błędem 413 Request Entity Too Large.
Zasada wymuszana przez aplikację: punkt końcowy musi być dostępny i w praktyce musi korzystać z HTTPS. Używanie adresów http:// lub bezpośredniego adresu IP bez numeru portu powoduje błąd "the app cannot reach the server" — szczegóły opisano poniżej jako konkretny rodzaj błędu.
Step 7: Biblioteki zewnętrzne a przesyłanie plików — importowanie istniejącej struktury zdjęć
Istnieją dwa sposoby dodawania zdjęć do Immich, które nie są tożsame.
- Uploads to zasoby zarządzane przez Immich. Aplikacja lub uploader webowy kopiuje plik do
UPLOAD_LOCATION. Immich może zmieniać ich nazwy, przenosić je oraz usuwać. - External libraries to importy w trybie read-only plików znajdujących się w folderze na serwerze — np. starej struktury
Pictureslub eksportu z NAS. Immich indeksuje je w miejscu ich występowania i wyświetla na osi czasu, ale nigdy nie modyfikuje ani nie usuwa oryginałów.
Aby zaimportować istniejącą strukturę, należy zamontować ją w trybie read-only w kontenerze serwera. Należy edytować docker-compose.yml w sekcji immich-server: i dodać wolumen:
immich-server:
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
- /srv/photos:/mnt/media/photos:roParametr :ro gwarantuje, że Immich nie może modyfikować oryginałów. Należy utworzyć kontener ponownie przy użyciu sudo docker compose up -d, a następnie w interfejsie webowym przejść do: avatar → Administration → External Libraries → Create Library, wybrać użytkownika, kliknąć Add w sekcji Folders i podać ścieżkę wewnątrz kontenera — /mnt/media/photos, a nie ścieżkę hosta /srv/photos. Następnie kliknąć Scan. Użycie ścieżki hosta zamiast ścieżki kontenera jest najczęstszym błędem przy bibliotekach zewnętrznych; skanowanie nie znajduje żadnych plików i raportuje zero zasobów.
Step 8: Dyscyplina aktualizacji wymagana przez Immich
Ten etap decyduje o stabilności działania Immich. Immich jest rozwijane w szybkim tempie; nie stosuje się backportowania poprawek ani nie wspiera downgrade'ów. Śledzenie tagu v3 bez kontroli doprowadzi do uszkodzenia bazy danych. Wymagana dyscyplina:
- Ustal konkretną wersję. Ustawienie
IMMICH_VERSIONna konkretny tag, np.v3.0.2, jest bezpieczniejsze niż używanie taguv3, który zawsze pobiera najnowszą wersję v3.x. - Zawsze czytaj release notes przed aktualizacją. W dokumentacji wymieniane są zmiany powodujące błędy (breaking changes), szczególnie w zakresie bazy danych lub rozszerzeń wektorowych. Przykładem jest wersja v3.0: usunięto z niej pgvecto.rs, co wymagało ukończenia migracji do VectorChord (wprowadzonej w v1.133) przed aktualizacją.
- Najpierw wykonaj kopię zapasową bazy danych (Step 9). Należy to robić zawsze, a szczególnie gdy release notes wspominają o bazie danych.
- Pobierz również nowy plik compose.
IMMICH_VERSIONblokuje jedynie obrazy servera i ML. Obraz Postgres jest blokowany przez digest wewnątrzdocker-compose.yml, więc wersje wymagające nowszych rozszerzeń dostarczają nowy plik compose. Należy ponownie pobrać oba pliki, ponownie zastosować wartości.env, a następnie przeprowadzić aktualizację. - Zaktualizuj aplikacje mobilne w tym samym czasie. Serwer obsługuje tylko swoją wersję główną (major version), a aplikacja wspiera bieżącą oraz poprzednią wersję główną. Jeśli serwer wyprzedzi aplikację, na telefonie pojawi się błąd
Your app major version is not compatible with the server!. Najbezpieczniej jest najpierw zaktualizować aplikację.
Komendy po przygotowaniu nowych plików:
cd /opt/immich
sudo docker compose pull
sudo docker compose up -d
sudo docker image pruneKrok 9: Kopie zapasowe — zrzut bazy danych ORAZ pliki oryginalne, a następnie testowanie
Kopia zapasowa Immich składa się z dwóch elementów; brak jednego z nich powoduje, że kopia jest bezużyteczna. Baza danych zawiera strukturę albumów, dane twarzy, indeksy wyszukiwania oraz mapowanie zasobów na pliki. Katalog originals zawiera właściwe zdjęcia. Przywrócenie tylko jednego elementu skutkuje brakiem organizacji zdjęć lub pustą strukturą wskazującą na brakujące pliki.
Wykonaj zrzut bazy danych za pomocą pg_dump wewnątrz kontenera Postgres — konkretnie bazy immich, a nie całego klastra:
sudo docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres | gzip > /opt/immich/immich-db-$(date +%F).sql.gzNastępnie wykonaj kopię zapasową UPLOAD_LOCATION — całego drzewa /opt/immich/library, w szczególności podfolderów library/, upload/ oraz profile/ — przy użyciu restic, rsync lub borg na inną maszynę lub pamięć obiektową. Najpierw należy wykonać zrzut bazy danych, a następnie kopię plików, aby zrzut nie odwoływał się do zdjęć, których pliki nie zostały jeszcze skopiowane. Biblioteki zewnętrzne należy kopiować oddzielnie z ich rzeczywistych lokalizacji; Immich nie zarządza nimi bezpośrednio.
Następnie etap pomijany przez użytkowników: testowanie przywracania. Proces przywracania należy przeprowadzić na nowym stosie (stack), którego serwer nigdy nie był uruchamiany, na obrazie Postgres z kompatybilną rozszerzeniem vector — dlatego należy zawsze używać dokładnie tej samej wersji obrazu bazy danych. Na czystym systemie z tym samym plikiem compose i .env należy usunąć wszelkie stare dane, uruchomić wyłącznie bazę danych, a następnie załadować zrzut:
cd /opt/immich
sudo docker compose down -v
sudo docker compose pull
sudo docker compose create
sudo docker start immich_postgres
sleep 10
gunzip --stdout immich-db-2026-07-15.sql.gz |
sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" |
sudo docker exec -i immich_postgres psql --dbname=immich --username=postgres --single-transaction --set ON_ERROR_STOP=on
sudo docker compose up -dPonowne zapisanie sed dla search_path jest wymagane w przypadku bazy VectorChord — pominięcie tego kroku spowoduje przerwanie procesu przywracania. Po uruchomieniu stosu z plikami oryginalnymi należy otworzyć interfejs webowy: jeśli zdjęcia i albumy są widoczne, kopia zapasowa jest poprawna. Jeśli nigdy nie przeprowadzono tego testu, posiadana kopia nie jest gwarancją bezpieczeństwa, a jedynie nadzieją.
Tryby awarii oraz wyświetlane komunikaty
Kontener ML zostaje zabity przez OOM-killer. Proces sudo docker compose logs immich-machine-learning zostaje przerwany, docker compose ps wskazuje na Restarting, a kod wyjścia to 137. sudo dmesg | grep -i oom potwierdza to: Out of memory: Killed process ... (python3). Zadania typu search oraz face ulegają zawieszeniu. Przyczyną jest niewystarczająca ilość pamięci RAM dla modeli. Rozwiązania (w kolejności): dodaj swap (Krok 1); zwiększ ilość pamięci RAM w VPS; lub, jeśli jest to niemożliwe, wyłącz ML w Administration → Settings → Machine Learning Settings, odznaczając opcje Smart Search oraz Facial Recognition — zachowane zostaną kopie zapasowe i albumy, ale utracona zostanie funkcja wyszukiwania po zawartości. Usunięcie usługi immich-machine-learning z pliku compose daje ten sam efekt.
Postgres odmawia uruchomienia po aktualizacji. Logi serwera zawierają powtarzającą się linię The database currently has VectorChord 0.5.3 activated, but the Postgres instance only has 0.4.2 available. This most likely means the extension was downgraded. — lub, w starszych stosach technologicznych, The pgvecto.rs extension is not available in this Postgres instance.. Przyczyną jest obraz bazy danych, którego wersja rozszerzenia jest starsza niż wersja danych po aktualizacji. Dzieje się tak najczęściej po ręcznej edycji tagu obrazu lub przywracaniu nowszego zrzutu danych na starszy obraz. Rozwiązaniem jest użycie obrazu Postgres zgodnego z wersją danych — należy pobrać plik compose z wersji odpowiadającej bazie danych, nie dokonywać downgrade'u i przywracać dane wyłącznie na kompatybilny obraz.
Aplikacja mobilna nie może połączyć się z serwerem. Po wpisaniu adresu URL ekran logowania wyświetla błąd połączenia / Server is not reachable. Trzy możliwe przyczyny: wpisano http:// zamiast https:// (gdzie proxy obsługuje tylko https://); połączenie bezpośrednio z backendem bez podania portu, co skutkuje próbą użycia example.com (port 443) zamiast example.com:2283; lub reverse proxy nie przekazuje /api. Rozwiązaniem jest wpisanie pełnego adresu URL https://photos.example.com i sprawdzenie, czy ładuje się on w przeglądarce telefonu. Jeśli przeglądarka działa, a aplikacja nie, przyczyną jest usuwanie ścieżki przez proxy lub certyfikat typu self-signed — aplikacja odrzuca certyfikaty o niezweryfikowanym zaufaniu.
Brak miejsca na dysku podczas importu. Rozpoczyna się błąd przesyłania plików, miniatury stają się puste, a logi wskazują ENOSPC: no space left on device lub (w przypadku Postgres) could not extend file ... No space left on device. df -h wskazuje na zajętość wolumenu UPLOAD_LOCATION na poziomie 100%. Dlatego należy zaplanować wielkość dysku przed importem dużej biblioteki. Odzyskiwanie polega na podłączeniu większego wolumenu, zatrzymaniu stosu, przeniesieniu UPLOAD_LOCATION na nowy wolumen, aktualizacji .env i ponownym uruchomieniu — lub na rozszerzeniu istniejącego dysku, jeśli dostawca na to pozwala. Postgres może ulec awarii przy pełnym dysku, dlatego należy zwolnić miejsce i zrestartować kontener bazy danych przed uznaniem danych za uszkodzone.
FAQ
Ile pamięci RAM i miejsca na dysku wymaga Immich?
Minimalne wymagania Immich to 6 GB RAM, a zalecane to 8 GB. W praktyce dla małej biblioteki absolutnym minimum jest 4 GB wraz ze swapem. Należy skonfigurować swap, ponieważ kontener machine-learning generuje nagłe skoki zużycia zasobów. W przypadku miejsca na dysku należy przewidzieć rozmiar całej biblioteki plus około 10–20% na wygenerowane miniatury i podglądy na pamięci lokalnej. Nigdy nie należy umieszczać katalogu danych Postgres na zasobie sieciowym. Jeśli rozważają Państwo inne usługi, przewodnik po self-hostingu w 2026 porównuje obciążenie Immich z innymi usługami.
Czy mogę uruchomić Immich bez GPU?
Tak. Kontener machine-learning działa poprawnie na procesorze CPU. GPU przyspiesza jedynie indeksowanie smart-search oraz (przy odpowiedniej wersji obrazu) transkodowanie wideo. Przy użyciu CPU wstępne indeksowanie dużej biblioteki może trwać wiele godzin w tle, ale nie blokuje ono tworzenia kopii zapasowych ani przeglądania. Jeśli zasoby maszyny są zbyt małe na ML, można wyłączyć funkcje Smart Search oraz Facial Recognition w ustawieniach administracyjnych, zachowując pozostałe funkcjonalności.
Jak bezpiecznie zaktualizować Immich?
Należy przypisać IMMICH_VERSION do konkretnego tagu, takiego jak v3.0.2, przed każdą aktualizacją przeczytać release notes oraz najpierw wykonać kopię zapasową bazy danych. Ponieważ obraz Postgres jest przypisany wewnątrz docker-compose.yml zamiast przez IMMICH_VERSION, należy ponownie pobrać plik compose oraz example.env z docelowej wersji i ponownie zastosować własne wartości, a następnie uruchomić docker compose pull && docker compose up -d. Nie należy pozostawiać wersji w trybie pływającym (floating) — Immich wprowadza zmiany łamiące wsteczną kompatybilność i nie wspiera downgrade'ów.
Co dokładnie należy wykonać jako kopię zapasową?
Należy wykonać dwie rzeczy: pg_dump bazy danych immich oraz całą zawartość katalogu UPLOAD_LOCATION originals. Baza danych przechowuje albumy, twarze oraz mapowanie zasobów do plików; katalog zawiera właściwe zdjęcia. Proces przywracania wymaga obu tych elementów oraz obrazu bazy danych z kompatybilną rozszerzeniem wektorowym. Najpierw należy wykonać zrzut bazy danych, a następnie kopię plików. Należy co najmniej raz przetestować przywracanie na osobnym urządzeniu — nieprzetestowana kopia zapasowa nie jest kopią zapasową.
Jak zaimportować istniejący folder ze zdjęciami?
Należy zamontować folder w trybie read-only do kontenera immich-server jako dodatkowy wolumen (na przykład - /srv/photos:/mnt/media/photos:ro), ponownie utworzyć kontener, a następnie w sekcji Administration → External Libraries utworzyć bibliotekę i dodać ścieżkę kontenera /mnt/media/photos. Immich indeksuje pliki w miejscu i nigdy ich nie modyfikuje ani nie usuwa. Najczęstszym błędem jest podanie ścieżki hosta zamiast ścieżki kontenera, co skutkuje brakiem wykrycia plików podczas skanowania.