Bei uns nutzt die ganze Familie Immich. Jeder hat seine eigene Bibliothek, und alles, was vorher in Google Fotos lag, haben wir komplett übernommen. Dazu gibt es gemeinsame Alben, die wir zusammen befüllen. So bleiben die eigenen Fotos privat, und die gemeinsamen landen trotzdem an einer Stelle.
In meinem Beitrag zur Docker-Landschaft habe ich Immich nur kurz vorgestellt. Hier geht es um die Einrichtung, so wie sie bei mir auf dem Ugreen DXP4800 Plus läuft. Wenn du ein anderes NAS oder einen kleinen Linux-Server hast, funktioniert das fast genauso. Die Unterschiede stehen jeweils dabei.
Kurz vorweg: So läuft Immich bei mir, Stand Oktober 2026. Immich entwickelt sich schnell weiter, prüf deshalb vor dem Nachbauen die offizielle Doku. Die Einrichtung erfolgt auf eigene Verantwortung. Lösch deine Fotos bei Google oder auf dem Handy erst, wenn du geprüft hast, dass in Immich alles angekommen ist und eine zweite Sicherung existiert.
Hinweis: Ich zeige hier, wie es bei mir läuft. Nachbau auf eigene Gefahr: Mach vorher ein Backup deiner Daten und Einstellungen. Für Schäden oder Datenverlust übernehme ich keine Haftung.
Was du brauchst
Laut offizieller Doku braucht Immich mindestens 6 GB Arbeitsspeicher und 2 CPU-Kerne, empfohlen sind 8 GB und 4 Kerne. Mit nur 4 GB geht es, dann aber ohne maschinelles Lernen, also ohne Gesichtserkennung und Smart-Suche. Das DXP4800 Plus hat 8 GB, das reicht bei mir.
Außerdem:
- Docker mit dem Compose-Plugin, bei mir verwaltet über Portainer. Auf der Konsole heißt der Befehl
docker composemit Leerzeichen, das altedocker-composeunterstützt Immich nicht mehr. - Eine aktuelle Docker-Version. Kommt beim Start ein Fehler zu
start_intervalund „Docker Engine v25“, ist Docker zu alt. - Ein Speicherort für die Fotos mit genug Platz. Vorschaubilder und umgewandelte Videos brauchen laut Doku zusätzlich 10 bis 20 Prozent.
- Für die Datenbank einen lokalen Speicher, am besten eine SSD. Eine Netzwerkfreigabe (SMB, NFS) ist dafür ausdrücklich nicht unterstützt.
Schritt 1: Netzwerk für den Proxy anlegen
Ich verwalte meine Container mit Portainer. Der Nginx Proxy Manager läuft bei mir selbst als Container und hängt in einem eigenen Docker-Netzwerk namens proxy_net. Alles, was von außen erreichbar sein soll, kommt zusätzlich in dieses Netzwerk. Dann findet der Proxy die Container über ihren Namen, und ich muss keine IP-Adressen pflegen.
Falls es das Netzwerk bei dir noch nicht gibt, legst du es einmal an, entweder in Portainer unter Networks oder auf der Konsole:
docker network create proxy_net
Der Nginx Proxy Manager muss ebenfalls in diesem Netzwerk hängen.
Schritt 2: Den Stack in Portainer anlegen
In Portainer gehst du auf Stacks, dann „Add stack“. Als Namen nehme ich immich-srv-01. Im Web-Editor kommt diese Compose-Datei hinein. Der Name ist frei wählbar. Die Datei basiert auf der offiziellen docker-compose.yml von Immich (Lizenz AGPL-3.0), ich habe sie für Portainer und mein Proxy-Netzwerk angepasst:
services:
immich-server:
container_name: immich_server_01
image: ghcr.io/immich-app/immich-server:release
# Nur bei Intel-CPU mit Grafikeinheit, siehe „Hardware-Beschleunigung“
# devices:
# - /dev/dri:/dev/dri
volumes:
# Fotos, Videos und Immich-Daten
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
env_file:
- stack.env
ports:
- "2283:2283"
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false
networks:
- immich_internal
- proxy_net
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:release
volumes:
- model-cache:/cache
env_file:
- stack.env
restart: always
healthcheck:
disable: false
networks:
- immich_internal
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9
healthcheck:
test: redis-cli ping | grep -q PONG || exit 1
restart: always
networks:
- immich_internal
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: "--data-checksums"
# Liegt die Datenbank auf einer Festplatte statt einer SSD:
# DB_STORAGE_TYPE: "HDD"
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
healthcheck:
disable: false
networks:
- immich_internal
volumes:
model-cache:
networks:
# Das vorhandene Netzwerk des Nginx Proxy Managers
proxy_net:
external: true
# Internes Netzwerk nur für Immich
immich_internal:
driver: bridge
Was gegenüber der offiziellen Datei anders ist:
- Zwei Netzwerke: Datenbank, Valkey und Machine Learning hängen nur im internen Netz
immich_internal. Nur der Immich-Server ist zusätzlich improxy_net, damit der Nginx Proxy Manager ihn erreicht. stack.envstatt.env: Portainer schreibt die Umgebungsvariablen, die du unten im Stack-Formular einträgst, in eine Datei mit diesem Namen. Deshalb steht sie unterenv_file.- Feste Containernamen, damit ich sie im Proxy und im Backup Manager wiederfinde.
releasestatt Versionsvariable: Damit zieht ein Update immer die aktuelle stabile Version. Das heißt aber auch: Kommt eine neue Hauptversion, landet sie beim nächsten Update automatisch bei dir. Die offizielle Vorlage setzt deshalbIMMICH_VERSION=v3in der.envund bleibt so bei Version 3. Wer es ruhiger mag, nimmt diesen Weg./dev/drireicht die Grafikeinheit des Prozessors in den Container. Bei mir steht die Zeile drin, im Codefenster ist sie auskommentiert. Gibt es auf dem Gerät keine Intel-Grafik, würde der Container sonst nicht starten.
In der offiziellen Datei hängt hinter den Images von Valkey und Postgres noch ein langer Code (@sha256:…). Er legt die Version genau fest. Am besten übernimmst du diese beiden Zeilen aus der aktuellen docker-compose.yml von Immich, dann passt die Datenbank immer zur Immich-Version.
Schritt 3: Die Umgebungsvariablen
Unter dem Editor gibt es in Portainer den Bereich „Environment variables“. Dort trage ich diese Werte ein, einzeln oder über „Load variables from .env file“:
# Hier landen die Fotos und Videos
UPLOAD_LOCATION=/pfad/zu/immich/library
# Hier liegt die Datenbank: lokal, keine Netzwerkfreigabe
DB_DATA_LOCATION=/pfad/zu/immich/postgres
TZ=Europe/Berlin
# Nur Buchstaben und Zahlen, keine Sonderzeichen
DB_PASSWORD=HIER-EIN-LANGES-PASSWORT
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
Zwei Dinge, über die man leicht stolpert:
- Beim Datenbank-Passwort nur
A-Z,a-zund0-9verwenden. Sonderzeichen machen laut Doku Probleme. TZsorgt dafür, dass Zeitstempel und geplante Aufgaben in deutscher Zeit laufen.
Die Datenbank gehört am besten auf eine SSD, die Fotos dürfen auf normale Festplatten. Liegt die Datenbank doch auf Festplatten, nimmst du in der Compose die Raute vor DB_STORAGE_TYPE: "HDD" weg.
Bei mir liegt die Datenbank auf den NVMe-SSDs des NAS, die Fotos liegen auf dem RAID 5.
Wer ohne Portainer arbeitet, legt die Compose-Datei als docker-compose.yml ab, schreibt die Variablen in eine Datei .env daneben, ändert stack.env in .env und startet mit dem folgenden Befehl. Das Netzwerk proxy_net aus Schritt 1 muss dann schon existieren, sonst bricht der Start ab:
docker compose up -d
Schritt 4: Starten und ersten Benutzer anlegen
In Portainer auf „Deploy the stack“ klicken. Beim ersten Start lädt Docker vier Images: Immich-Server, Machine Learning, Postgres und Valkey. Danach ist Immich im Heimnetz unter Port 2283 erreichbar:
http://IP-DEINES-NAS:2283
Der erste Benutzer, den du dort anlegst, wird automatisch Administrator. Port 2283 ist nur fürs Heimnetz gedacht. Im Router gibst du ihn nicht frei, von außen geht es nur über den Proxy (Schritt 6).
Optional: Hardware-Beschleunigung
Ich nutze sie derzeit nicht. Wer Videos schneller umwandeln will und eine Intel-CPU ab der 9. Generation hat, kann Quick Sync einschalten. Die offizielle Vorlage holt sich die Einstellungen dafür aus der Datei hwaccel.transcoding.yml. Das Ugreen DXP4800 Plus hat mit dem Pentium Gold eine passende Intel-Grafik. In meiner Compose oben reicht es, die Rauten vor devices und /dev/dri zu entfernen. Danach in Immich unter Administration, Einstellungen, Video-Transkodierung die Hardware-Beschleunigung auf Quick Sync (QSV) stellen.
Schritt 5: Die Handy-App
Für jedes Familienmitglied lege ich unter Administration, Benutzer ein eigenes Konto an. Jeder sieht dann nur seine eigenen Fotos. Die App läuft bei uns auf den Handys und auf dem iPad. Am PC und am Mac nutzen wir Immich im Browser.
Gemeinsame Alben legt einer von uns an und teilt sie mit den anderen. Wer dabei das Recht zum Hinzufügen bekommt, kann eigene Bilder in das Album legen. Die Fotos bleiben dabei in der Bibliothek dessen, der sie hochgeladen hat.
In der App stellst du unter Sicherung ein, welche Alben auf dem Handy hochgeladen werden und ob das nur im WLAN passieren soll.
Optional: Umzug von Google Fotos
Der Weg führt über Google Takeout. Dort lässt sich unter takeout.google.com alles exportieren, was bei Google liegt. Dort wählst du nur „Google Fotos“ aus und lässt dir ZIP-Archive erstellen. Je nach Größe der Sammlung dauert das ein paar Stunden bis Tage, dann kommt eine Mail mit den Download-Links.
Beim Hochladen gibt es einen Haken: Google packt Aufnahmedatum, Ort und Beschreibung nicht in die Bilder selbst, sondern in eigene JSON-Dateien daneben. Wer die Bilder einfach so hochlädt, hat danach falsche Daten in der Zeitachse.
Genau dafür gibt es das kostenlose Werkzeug immich-go. Es stammt nicht vom Immich-Team, sondern von einem anderen Entwickler, und gilt laut eigener Beschreibung noch als frühe Version. Probier es deshalb erst mit einem kleinen Archiv aus. Es liest die Takeout-Archive direkt, ordnet die JSON-Dateien den richtigen Bildern zu, übernimmt die Alben und überspringt Bilder, die schon in Immich liegen. Dafür braucht es einen API-Schlüssel, den jeder Benutzer in Immich in seinen Kontoeinstellungen unter „API-Schlüssel“ anlegt. Welche Berechtigungen der Schlüssel braucht, steht in der Anleitung von immich-go. Nach dem Import kannst du ihn wieder löschen. Weil jeder bei uns eine eigene Bibliothek hat, läuft der Import mit dem Schlüssel der jeweiligen Person:
immich-go upload from-google-photos --server=http://IP-DEINES-NAS:2283 --api-key=DEIN-API-SCHLUESSEL /pfad/zu/takeout-*.zip
Die ZIP-Dateien müssen dafür nicht entpackt werden. So haben wir unsere komplette Google-Fotos-Sammlung übernommen, für jede Person mit ihrem eigenen Schlüssel.
Schritt 6: Von unterwegs über den Nginx Proxy Manager

Wie ich den Nginx Proxy Manager grundsätzlich nutze, steht in einem eigenen Beitrag. Für Immich lege ich einen Proxy Host an:
- Domain: eine eigene Subdomain, z. B.
fotos.example.com. Immich läuft nur direkt auf einer (Sub-)Domain, nicht unter einem Unterpfad wieexample.com/fotos. - Ziel:
http, Hostnameimmich_server_01, Port2283. Das klappt, weil beide improxy_nethängen. Ohne gemeinsames Netzwerk nimmst du die IP des NAS. - Websockets Support: an
- SSL: Let’s-Encrypt-Zertifikat, „Force SSL“ an
Unter „Advanced“ kommen die Werte, die Immich für Nginx empfiehlt. Sonst brechen große Videos beim Hochladen ab:
client_max_body_size 50000M;
proxy_request_buffering off;
client_body_buffer_size 1024k;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
Danach in Immich unter Administration, Einstellungen, Servereinstellungen die externe Domain eintragen. Dann zeigen geteilte Links auf die richtige Adresse.
Weil die Fotos jetzt aus dem Internet erreichbar sind: Jedes Konto bekommt ein eigenes, langes Passwort, und geteilte Links bekommen am besten ein Ablaufdatum oder werden gelöscht, wenn sie nicht mehr gebraucht werden.
Schritt 7: Sicherung
Immich legt jede Nacht um 2 Uhr selbst eine Sicherung der Datenbank an und behält die letzten 14. Die liegen unter UPLOAD_LOCATION/backups. Darin stecken aber nur die Metadaten, also Alben, Gesichter, Benutzer. Die Fotos selbst müssen extra gesichert werden.
Wichtig sind diese Ordner unter UPLOAD_LOCATION:
library/ Originale (wenn die Speichervorlage aktiv ist)
upload/ Originale
profile/ Profilbilder
backups/ Datenbank-Sicherungen
thumbs/ und encoded-video/ kann Immich nach einer Wiederherstellung neu erzeugen. Die kannst du weglassen, das spart Platz.
Bei mir übernimmt das mein Docker Backup Manager: Er sichert die Immich-Container einmal pro Woche per SMB aufs TrueNAS.
Updates
Vor jedem Update lohnt ein Blick in die Release Notes auf GitHub. Immich ändert öfter etwas, das man von Hand nachziehen muss, zum Beispiel das Postgres-Image in der Compose-Datei.
In Portainer öffnest du den Stack, klickst auf „Update the stack“ und schaltest dabei „Re-pull image and redeploy“ ein. Weil in der Compose release steht, holt Docker dann die neueste stabile Version. Auf der Konsole geht dasselbe mit:
docker compose pull
docker compose up -d
Mein Fazit
Für uns hat sich der Umzug gelohnt. Unsere Fotos liegen zu Hause statt bei Google, und die gemeinsamen Alben funktionieren für die ganze Familie. Ich würde alles genauso wieder aufbauen.
Wer auch Dateien und Scans selbst hosten will: So läuft bei mir Nextcloud All-in-One.
Titelbild KI-generiert.


