Die Compose-Datei für Immich kommt nicht aus einem Blog, sondern vom Projekt selbst: Sie liegt bei jedem Release auf GitHub, mit Prüfsummen an den Images und in Zeile eins einer Warnung, bitte nur die Datei der aktuellen Version zu nehmen. Das ist bei Homelab-Diensten selten und der Grund, warum diese Anleitung so wenig erfindet: Vier Container, ein Passwort, ein Ordner für die Fotos, und Immich läuft. Was die Doku dir nicht abnimmt, ist die Frage, was die vier Container eigentlich tun, warum der Server beim ersten Start gern schneller ist als seine Datenbank, und was nach dem ersten Login noch einzustellen ist, bevor die Handy-Kamera hochlädt.
Genau das steht hier. Wer schon ein Immich hat und seine Google-Fotos hinüberziehen will, ist beim Beitrag zu immich-go und Google Takeout richtig; hier geht es um den Server davor.

Was Immich ist, und was die vier Container tun
Immich ist eine Foto- und Video-Verwaltung, die auf deinem Server läuft und sich für das Handy anfühlt wie Google Fotos: eine App, die neue Aufnahmen von selbst hochlädt, eine Zeitleiste, Alben, Gesichter, eine Suche, die „Hund am Strand" versteht. Der Unterschied ist der Ort. Die Originale liegen in einem Ordner auf deiner Platte, die Datenbank daneben, und nichts davon verlässt dein Netz, wenn du es nicht willst.
Dafür braucht Immich vier Container, und ich nenne sie, weil du sie gleich in docker compose ps wiedersiehst:
immich-serverist der Dienst, mit dem Browser und App reden, auf Port 2283. Er nimmt Uploads an, rechnet Vorschaubilder, wandelt Videos um und verteilt Aufträge.immich-machine-learningist die Abteilung für das Verstehen: Sie erkennt Gesichter und berechnet zu jedem Bild, was darauf zu sehen ist, damit die Suche nach Begriffen funktioniert.databaseist eine PostgreSQL-Datenbank mit einer Erweiterung für genau diese Bildmerkmale. Hier stehen Alben, Personen, Zeitstempel und wer welches Foto sehen darf. Die Fotos selbst stehen nicht darin.redisheißt der vierte Dienst, das Image ist Valkey, eine quelloffene Abspaltung von Redis. Er ist die Warteschlange: Der Server legt Aufträge hinein, die Arbeiter holen sie ab.
model-cache. Es ist der Container, der am meisten Arbeitsspeicher will, und der einzige, den du weglassen kannst.Die Mindestanforderungen stehen so in der Doku: 6 GB RAM, empfohlen 8, mindestens zwei Kerne, empfohlen vier, ein 64-Bit-Linux und ein Dateisystem wie ext4. Und ein Satz, den ich fett lesen würde: Die Datenbank gehört nicht auf ein Netzlaufwerk, sondern auf lokalen Speicher, am besten eine SSD. Die Fotos dürfen auf die große Platte, die Datenbank nicht. Mit 4 GB RAM geht es auch, dann aber ohne den Machine-Learning-Container; wie das geht, steht unter „Was am Ende eingestellt ist".
Was du brauchst
- Einen Linux-Rechner mit Docker und Compose, der durchläuft. Prüfen:
docker compose versionmuss eine Versionsnummer ausgeben. Fehlt Docker, steht die Installation in der Compose-Anleitung für Einsteiger, Schritt 1. Die Doku verlangt Docker Engine ab Version 25;docker version --format '{{.Server.Version}}'zeigt deine. - Arbeitsspeicher:
free -hzeigt in der ZeileMem:untertotal, was der Rechner hat. Unter 6 GB: Machine Learning später abschalten. - Prozessorkerne:
nprocgibt die Zahl aus, zwei sind das Minimum. - Platz auf der Platte:
df -h ~zeigt den freien Platz in deinem Home-Verzeichnis. Die vier Images brauchen gut 2 GB, dazu deine Fotos plus laut Doku 10 bis 20 Prozent für Vorschaubilder und umgewandelte Videos. - Port 2283 frei:
sudo ss -tulpn | grep ':2283 'darf nichts ausgeben. - Die IP-Adresse des Servers im Heimnetz, und die sollte sich nicht ändern.
hostname -Izeigt sie; fest machst du sie im Router, bei der FritzBox über „Diesem Netzwerkgerät immer die gleiche IPv4-Adresse zuweisen". - Ein Handy mit der Immich-App aus dem App Store, dem Play Store oder als APK von GitHub. Das kommt in Schritt 4.
Alle Befehle und Klicks rechnen mit denselben Beispielwerten. Wo sie unten auftauchen, setzt du deine ein:
- IP-Adresse des Servers:
192.168.178.20 - Ordner für die Compose-Datei:
~/immich(das~steht für dein Home-Verzeichnis) - Ordner für Fotos und Videos:
~/immich/library, im Container/data - Ordner für die Datenbank:
~/immich/postgres - Datenbank-Passwort:
Wolkenlos2026als Platzhalter; du nimmst ein eigenes, nur aus Buchstaben und Ziffern - Zeitzone:
Europe/Berlin - Weboberfläche:
http://192.168.178.20:2283 - Admin-Konto: E-Mail
sakis@example.com, NameSakis, Passwort frei, lang, anders als das der Datenbank
Schritt 1: Ordner und compose.yaml anlegen
Immich bekommt einen eigenen Ordner, darin die Compose-Datei und zwei Unterordner, die Docker beim ersten Start selbst anlegt: library für alles, was du hochlädst, und postgres für die Datenbank. Beide liegen damit sichtbar neben der Datei, und ein Backup ist später ein Ordner, den man kopieren kann.
Ordner anlegen und hineinwechseln:
mkdir -p ~/immich
cd ~/immichDatei anlegen; nano ist ein Texteditor fürs Terminal:
nano compose.yamlInhalt einfügen, an den zwei Stellen mit Wolkenlos2026 dein Passwort eintragen (beide Male dasselbe), mit Strg+O und Enter speichern, mit Strg+X schließen. Die Einrückung mit zwei Leerzeichen gehört zur Datei:
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:v3
volumes:
- ./library:/data
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=Europe/Berlin
- DB_PASSWORD=Wolkenlos2026
- DB_USERNAME=postgres
- DB_DATABASE_NAME=immich
ports:
- '2283:2283'
depends_on:
redis:
condition: service_healthy
database:
condition: service_healthy
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:v3
volumes:
- model-cache:/cache
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:70739f85ad2ee01a726a965584a0f94895f01b0c60b3cc8b0aeef11eaa6888cf
healthcheck:
test: redis-cli ping | grep -q PONG || exit 1
restart: always
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
environment:
POSTGRES_PASSWORD: Wolkenlos2026
POSTGRES_USER: postgres
POSTGRES_DB: immich
POSTGRES_INITDB_ARGS: '--data-checksums'
volumes:
- ./postgres:/var/lib/postgresql/data
shm_size: 128mb
restart: always
healthcheck:
disable: false
volumes:
model-cache:Prüfen, ob Compose die Datei versteht:
docker compose config --quiet && echo "Datei in Ordnung"Datei in OrdnungDie Datei ist die offizielle docker-compose.yml von Immich 3.2.4, mit Images, Prüfsummen, shm_size und Healthchecks genau wie dort. An drei Stellen weicht sie ab, und die drei erkläre ich, weil sie die Entscheidungen dieser Anleitung sind. Sie ist im Sandkasten dieser Seite gelaufen, bevor sie hier steht.
- Eine Datei statt zwei. Das Projekt verteilt die Einstellungen auf
docker-compose.ymlund eine.env-Datei mit Passwort, Pfaden, Zeitzone und Version. Ich habe die Werte in die Compose-Datei geholt, weil eine Datei leichter zu sichern und zu verstehen ist als zwei, die aufeinander zeigen. Der Preis: Das Datenbank-Passwort steht zweimal drin, einmal beim Server, einmal bei der Datenbank, und beide müssen gleich sein. Wer lieber den Weg der Doku geht, nimmt deren zwei Dateien; die Werte sind dieselben. image: …:v3statt${IMMICH_VERSION:-release}. Die Vorgabe in der offiziellen.envistv3, und ich übernehme sie: Damit bekommst du bei jedempulldie neueste 3.x, aber keine 4.0, die eines Tages wieder etwas Grundlegendes ändert. Die Doku sagt dazu, dass Breaking Changes nur mit Hauptversionen kommen, und dass die Handy-App zuerst aktualisiert wird.depends_onmitcondition: service_healthy. Die offizielle Datei sagt nur, dass der Server nach Datenbank und Warteschlange starten soll, nicht, dass er wartet, bis sie bereit sind. Im Sandkasten dieser Seite ist der Server beim ersten Versuch genau daran gestorben:connect ECONNREFUSED 172.18.0.2:5432, die Datenbank war noch beim Einrichten. Mitrestart: alwayshätte Docker ihn nach ein paar Sekunden neu gestartet, und dann wäre alles gut gewesen; du hättest nur einen roten Eintrag in den Logs, den du nicht einordnen kannst. Die lange Form vondepends_onist in der Compose-Referenz dokumentiert und lässt den Server erst los, wenn der Healthcheck der Datenbank „healthy" meldet. Beim zweiten Lauf antwortete Port 2283 nach 125 Sekunden, davon 60 fürs Ziehen der Images.
Zwei Zeilen noch, die man sonst gern streicht. /etc/localtime:/etc/localtime:ro reicht die Uhrzeit des Servers in den Container, nur lesend; zusammen mit TZ sorgt das dafür, dass Fotos ohne Zeitzone im Bild den richtigen Tag bekommen. Und shm_size: 128mb gibt der Datenbank mehr gemeinsamen Speicher, als Docker Containern normalerweise zugesteht; Postgres arbeitet damit, und die 64 MB Vorgabe sind für die Bildmerkmale zu wenig.
Schritt 2: Starten und prüfen
Der eine Befehl zieht vier Images, legt Netz und Volume an und startet die Container in der Reihenfolge, die depends_on vorgibt. Das Ziehen dauert; der Machine-Learning-Container ist mit Abstand der größte.
docker compose up -d ✔ Container immich_redis Healthy 32.5s
✔ Container immich_postgres Healthy 6.5s
✔ Container immich_machine_learning Started 1.5s
✔ Container immich_server Started 32.3sDas sind die letzten vier Zeilen; davor stehen je eine Zeile Pulled für die vier Images und je eine Zeile Created für das Netz immich_default und das Volume immich_model-cache, jede mit einem Haken und der Zeit, die der Schritt gebraucht hat. Zwei Dinge in dieser Ausgabe: Netz und Volume tragen den Vorsatz immich_, weil die Datei mit name: immich beginnt; setzt dein System die Variable COMPOSE_PROJECT_NAME, steht stattdessen deren Wert davor. Und bei redis und postgres steht Healthy, nicht Started; das ist die Bedingung aus Schritt 1 bei der Arbeit, Compose hat auf beide gewartet, bevor der Server durfte. Nach dem Start braucht der Server etwa eine halbe Minute, bis er auf Port 2283 antwortet. Dann die Frage, ob alle vier auch bleiben:
docker compose psNAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
immich_machine_learning ghcr.io/immich-app/immich-machine-learning:v3 "tini -- python -m i…" immich-machine-learning About a minute ago Up About a minute (healthy)
immich_postgres ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 "/usr/local/bin/immi…" database About a minute ago Up About a minute (healthy) 5432/tcp
immich_redis docker.io/valkey/valkey:9@sha256:70739f85ad2ee01a726a965584a0f94895f01b0c60b3cc8b0aeef11eaa6888cf "docker-entrypoint.s…" redis About a minute ago Up About a minute (healthy) 6379/tcp
immich_server ghcr.io/immich-app/immich-server:v3 "tini -- /bin/bash -…" immich-server About a minute ago Up 32 seconds (healthy) 0.0.0.0:2283->2283/tcp, [::]:2283->2283/tcpDie Spalte STATUS zählt: viermal (healthy). Direkt nach dem Start steht bei Server und Machine Learning noch (health: starting), das darf eine Minute dauern. In der Spalte PORTS ist nur beim Server eine Adresse mit 0.0.0.0, die anderen drei sind von außen nicht erreichbar, auch nicht aus dem Heimnetz; sie reden nur untereinander im Netz immich_default. Was der Server beim Start getan hat, zeigen die Logs:
docker compose logs immich-server --tail 20immich_server | [Nest] 7 - 10/06/2026, 10:40:10 AM LOG [Microservices:SystemConfigService] LogLevel=log (set via system config)
immich_server | [Nest] 7 - 10/06/2026, 10:40:10 AM LOG [Microservices:MachineLearningRepository] Machine learning server became healthy (http://immich-machine-learning:3003).
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:WorkflowExecutionService] Imported plugin immich-plugin-core@2.0.1 (14 methods) from /build/plugins/immich-plugin-core
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:WorkflowExecutionService] Loaded plugin: immich-plugin-core@2.0.1
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:WorkflowExecutionService] Loaded plugin with host functions: immich-plugin-core@2.0.1/worker
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:NestFactory] Starting Nest application...
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] BullModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] ClsModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] ClsCommonModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] OpenTelemetryModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] KyselyModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] OpenTelemetryCoreModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] DiscoveryModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] ClsRootModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] ClsPluginsModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] BullModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] BullModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:InstanceLoader] MicroservicesModule dependencies initialized
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:NestApplication] Nest application successfully started
immich_server | [Nest] 7 - 10/06/2026, 10:40:11 AM LOG [Microservices:Bootstrap] Immich Microservices is running [v3.2.4] [production]Die letzte Zeile nennt die Version. Dann der Klopftest von außen, derselbe, den der Sandkasten macht:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:2283/200Eine 200 heißt: Der Server liefert die Weboberfläche aus. Das war die Installation. Vier Container nach einem Befehl gesund, und das Erste, was ich dann mache, ist nachsehen, wem der Foto-Ordner gehört. stat zeigt je Eintrag die Nummer des Besitzers, die Nummer seiner Gruppe und den Pfad; Nummern statt Namen, weil der Name des Datenbank-Benutzers auf deinem Rechner gar nicht existiert:
stat -c '%u %g %n' ~/immich/*1000 1000 /home/sakis/immich/compose.yaml
0 0 /home/sakis/immich/library
999 0 /home/sakis/immich/postgresDie 1000 bei compose.yaml bist du, der erste Benutzer eines Linux-Systems bekommt diese Nummer; id -u zeigt deine. Und da ist es: library gehört der 0, das ist Root, postgres dem Benutzer 999, so legt Docker Ordner an, die es selbst erzeugt. Für Immich ist das in Ordnung, weil der Server im Container als Root läuft und die Datenbank als ihr eigener Benutzer; die Doku bietet eine Variante ohne Root an, die ich hier weglasse, weil sie Rechte an drei Stellen verlangt und für einen Server im Keller nichts gewinnt. Merken musst du dir nur eins: Wenn du in library mit deinem Benutzer lesen, aber nichts hineinschreiben kannst, ist das kein Fehler. Und laut Backup-Doku sollst du das auch nicht, außer zum Kopieren.
Schritt 3: Admin-Konto anlegen und den Assistenten durchgehen
Der erste Benutzer, der sich registriert, ist der Admin. Das steht so in der Doku, und es heißt: Bis du das getan hast, kann das jeder im Heimnetz. Deshalb jetzt, nicht später. Die Oberfläche folgt der Sprache des Browsers; ich nenne die deutschen Bezeichnungen und dahinter die englischen.
Im Browser http://192.168.178.20:2283 öffnen (Stand Immich 3.2). Auf der Startseite unten Erste Schritte (Getting Started). Den Link Von Datenbank wiederherstellen darunter lässt du liegen. Im Formular Administrator E-Mail (Admin Email) sakis@example.com, Administrator Passwort (Admin Password) dein Passwort, darunter noch einmal bestätigen, bei Name Sakis. Dann Registrieren (Sign up). Es folgt die Anmeldeseite: mit E-Mail und Passwort anmelden.



Nach der ersten Anmeldung startet ein Assistent, der die Einstellungen abfragt, die für den ganzen Server gelten. Die meisten darfst du durchwinken, eine nicht:
Der Assistent beginnt mit Willkommen; der Knopf zum Weitergehen heißt jeweils wie die nächste Seite, nicht Weiter. Er führt durch Theme (hell oder dunkel), Sprache (Language, hier Deutsch wählen, dann sind die nächsten Seiten schon übersetzt) und Privatsphäre auf dem Server (Server Privacy) mit den Schaltern Karte (Map) und Versionsprüfung (Version Check). Danach folgt noch eine Seite Datenschutzeinstellungen Nutzer mit genau einem Schalter, Google Cast, ab Werk aus. Auf der Seite Speichervorlage (Storage Template) den Schalter einschalten und die Vorgabe {{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}} stehen lassen. Die Seite zeigt dann die Marke Ungespeicherte Änderung; der Knopf Sicherungen speichert sie mit der Meldung Erfolgreich und geht weiter. Es folgen die Seiten Sicherungen und Mobile App mit den Knöpfen App Stores und Obtainium Konfigurator; dort steht Fertig (Done).



Die Speichervorlage ist die Stelle, an der ich von der Vorgabe abweiche. Ohne sie legt Immich jede Datei unter einem zufälligen Namen in upload/<deine ID>/ ab; nur die Datenbank weiß, welches Foto das ist. Mit ihr liegen die Originale unter library/<deine ID>/2026/2026-09-29/IMG_4711.jpg, und wenn in fünf Jahren die Datenbank weg ist und nur die Platte übrig, kannst du die Ordner trotzdem lesen. Die Doku warnt, dass eine spätere Änderung einen Migrationsauftrag über alle vorhandenen Dateien braucht; deshalb jetzt, solange die Bibliothek leer ist.
Die beiden Datenschutz-Schalter erklärt die Oberfläche selbst: Die Karte lädt Kacheln von einem Kartendienst des Projekts, wenn du die Kartenansicht öffnest, und die Versionsprüfung fragt beim Projekt nach, ob es eine neue Immich-Version gibt. Beides geht nach draußen, beides ohne deine Fotos. Ich lasse beides an; wer den Server komplett schweigsam will, schaltet sie hier aus und findet sie später unter Verwaltung, Einstellungen wieder.
Die Erfolgskontrolle ist die Zeitleiste: leer, mit dem Hinweis, dass noch nichts hochgeladen ist, und oben rechts ein Knopf Hochladen (Upload). Ein Testbild vom PC per Drag-and-drop hinein, und nach ein paar Sekunden erscheint es mit Datum. Auf dem Server liegt es dann unter ~/immich/library/library/, gefolgt von deiner Benutzer-ID und dem Datum; das doppelte library ist richtig, außen dein Ordner, innen der Unterordner der Speichervorlage.
Schritt 4: Handy-App koppeln und Alben sichern
Das Handy ist bei Immich der Hauptdarsteller, weil es die Bilder hat. Die App braucht die Adresse des Servers und dein Konto; danach lädt sie im Hintergrund, was neu dazukommt. Die Fotos bleiben dabei auf dem Handy, es ist eine Kopie, und laut Doku ausdrücklich eine Einbahnstraße vom Gerät zum Server.
Auf dem Handy die App Immich aus dem App Store oder Play Store installieren (auf Android auch als APK von den GitHub-Releases). Beim ersten Start bei Server-URL (Server Endpoint URL) http://192.168.178.20:2283 eintragen, weiter, dann mit sakis@example.com und dem Passwort anmelden. In der App oben rechts auf das Wolken-Symbol tippen; das ist der Backup-Bildschirm. Dort die Alben auswählen, die gesichert werden sollen, typisch Camera oder Recents, und die Sicherung einschalten (Enable Backup). Der Upload beginnt sofort.
Zwei Vorgaben, die du kennen solltest: Die App lädt laut Doku standardmäßig nur im WLAN hoch, und Video zählt mit. Und die Hintergrund-Sicherung hängt am Betriebssystem. Unter iOS muss Hintergrundaktualisierung für die App erlaubt sein, und wann iOS die App im Hintergrund laufen lässt, entscheidet iOS; die Doku sagt, das hängt davon ab, wie oft du die App öffnest. Android lässt mehr zu, nur bei aggressiver Akku-Optimierung mancher Hersteller wird die App eingeschläfert. Der Weg, der immer geht: App öffnen, dann lädt sie.
Die Erfolgskontrolle steht in der Weboberfläche: Die Zeitleiste füllt sich vom neuesten Bild aus, und unter Verwaltung (Administration), Server Statistiken (Server Stats) zählt die Anzahl der Fotos hoch. Auf dem Server:
ls ~/immich/librarybackups
encoded-video
library
profile
thumbs
uploadDas ist die Ordnung, die die Backup-Doku beschreibt: library mit den Originalen (dank Speichervorlage), upload als Zwischenlager während eines Uploads, profile für Profilbilder, thumbs und encoded-video für das, was Immich neu rechnen kann, und backups für die Datenbank-Sicherungen, zu denen wir gleich kommen. Der erste Upload vom Handy, der in der Zeitleiste auftaucht, ist der Moment, an dem Google Fotos überflüssig wird. Kurz freuen, dann weiter, denn was jetzt läuft, ist noch nicht vernünftig eingestellt.
Was am Ende eingestellt ist
- Du bist Admin, und weitere Konten legst du an, nicht die Leute selbst. Eine Registrierungsseite gibt es nach dem ersten Benutzer nicht mehr. Familie und Freunde bekommen ihr Konto unter Verwaltung, Benutzer (Users), Neuen Nutzer erstellen (Create user). Jeder sieht nur seine eigenen Bilder, geteilt wird über Alben oder geteilte Links.
- Port 2283 ist im ganzen Heimnetz offen, ohne HTTPS und ohne Zugang von außen. Im Router steht keine Freigabe, und die würde ich auch nicht anlegen. Wer von unterwegs sichern will, hat zwei Wege: ein VPN ins Heimnetz, dann bleibt die Adresse in der App dieselbe; oder ein Reverse Proxy mit echtem Zertifikat, dann muss laut FAQ WebSocket-Unterstützung an sein, sonst meldet die App „Server offline", obwohl er läuft.
- Die Datenbank sichert sich selbst, deine Fotos nicht. Ab Werk legt Immich jede Nacht um 2 Uhr einen Datenbank-Export unter
library/backupsab und behält die letzten 14; einstellbar unter Verwaltung, Einstellungen, Einstellungen zum Datenbankexport (Backup Settings). Die Doku sagt es in einem Satz: „Database backups do not contain photos or videos, only metadata." Das Backup deines Immich ist also der ganze Ordner~/immich/libraryan einem zweiten Ort, und zwar erst die Datenbank, dann die Dateien, damit beide zusammenpassen. Ja, dieser Absatz steht in jeder Anleitung hier. Bei Fotos, die es nur einmal gibt, steht er zu Recht. - Updates kommen mit
pull, nicht von selbst, und die App zuerst. Im Ordner~/immicheinmal im Monatdocker compose pullunddocker compose up -d, vorher die Release Notes auf GitHub, die das Projekt ausführlich schreibt. Die Doku nennt dazu die Reihenfolge: Die Handy-App versteht die aktuelle und die vorherige Hauptversion, der Server nur seine eigene, also App vor Server aktualisieren. Und ein Downgrade gibt es nicht; wer 3.3 eingespielt hat, bleibt dort. Der Tagv3hält dich von einer 4.0 fern, bis du sie willst. - Machine Learning läuft mit allem, was es hat. Gesichtserkennung und die Begriffssuche sind an, und der Container zieht sich beim ersten Auftrag die Modelle. Auf einem Rechner mit 4 GB RAM schaltest du beides unter Verwaltung, Einstellungen, Einstellungen für maschinelles Lernen aus und löschst den Dienst
immich-machine-learningsamt seiner Zeilemodel-cache:untervolumes:aus der Compose-Datei, danndocker compose up -d --remove-orphans. Die FAQ sagt ehrlich, was das kostet: „a poor experience for searching and the Explore page". Zeitleiste, Alben und Backup laufen ohne.
Der Papierkorb hält gelöschte Bilder laut Doku 30 Tage, bevor sie wirklich weg sind, einstellbar unter Papierkorbeinstellungen (Trash Settings). Das ist die eine Vorgabe, die ich nicht anfasse.
Wo es klemmt
connect ECONNREFUSED 172.18.0.2:5432 im Server-Log, Container immich_server neu gestartet. Der Server hat die Datenbank angerufen, bevor sie bereit war. Mit der Datei aus Schritt 1 passiert das nicht, weil Compose auf „healthy" wartet; wer die offizielle Datei ohne diese Bedingung nimmt, sieht den Fehler beim ersten Start einmal und dann nie wieder, weil restart: always den Server neu startet. Kein Handlungsbedarf, solange docker compose ps danach (healthy) zeigt.
Ein Container endet mit Exit-Code 137. Laut FAQ heißt 137 „nicht genug Arbeitsspeicher": Der Kernel hat den Prozess abgeschossen. Meist trifft es Machine Learning, wenn viele Bilder auf einmal verarbeitet werden. Erste Hilfe unter Verwaltung, Einstellungen, Aufträge (Job Settings): die Gleichzeitigkeit für Gesichtserkennung und Smart Search auf 1 setzen, und die FAQ rät ausdrücklich, nie über die Zahl der Kerne zu gehen. Reicht das nicht, siehe Punkt 5 oben. Exit-Code 132 daneben heißt laut FAQ etwas anderes: Der Prozessor ist zu alt, Immich braucht x86-64-v2, also grob alles ab 2012.
FATAL: called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied … } im Log der Datenbank. Ein Fall aus den GitHub-Discussions vom August 2025, auf Debian 13: Die Rechte am Ordner stimmten, trotzdem durfte die Datenbank nicht schreiben, weil AppArmor, die Rechteverwaltung von Debian für Programme, den Container ausbremste. Die Antwort im Thread: dem Dienst database in der Compose-Datei die zwei Zeilen security_opt: und darunter - apparmor=unconfined ergänzen, dann docker compose up -d. Das nimmt AppArmor für genau diesen Container heraus. Ich würde das nur tun, wenn genau diese Meldung im Log steht, und nicht vorsorglich.
Die App sagt „Server offline", der Browser zeigt Immich. Fast immer ein Reverse Proxy ohne WebSocket-Unterstützung; die FAQ hat dafür einen eigenen Eintrag. Bei Nginx Proxy Manager ist es der Schalter Websockets Support im Proxy Host. Und wenn die App die Adresse im Heimnetz gar nicht erreicht: Auf dem Server sudo ufw status prüfen, ob eine Firewall aktiv ist; Docker geht an ufw meist vorbei, aber nicht immer so, wie man denkt.
Das Admin-Passwort ist weg. Laut FAQ setzt der Befehl reset-admin-password im Server-Container es zurück:
docker exec -it immich_server reset-admin-passwordDie Datenbank startet auf einem NAS-Share, einer USB-Platte mit NTFS oder in WSL unter /mnt nicht. Das ist kein Fehler von Immich, sondern die Anforderungsseite in Fett: NTFS und FAT32 gehen nicht, Netzlaufwerke gehen nicht, Postgres will ein Linux-Dateisystem auf lokalem Speicher. Der Ordner postgres bleibt auf der Systemplatte; nur library darf umziehen, dann als absoluter Pfad in der Zeile - ./library:/data, etwa - /mnt/fotos:/data.
Was du jetzt hast, ist der Teil von Google Fotos, der wirklich zählt: eine App, die das Handy von selbst leert, eine Suche, die Bilder versteht, und Originale in Ordnern, die du auch ohne Immich lesen kannst. Welche Funktion hat dich zu Immich gebracht, die Suche, die Gesichter oder schlicht der Speicherplatz, und an welchem Schritt hat es bei dir gehakt? Schreib's in die Kommentare.
Der nächste Schritt ist bei den meisten der Umzug: Wie die Jahre aus Google Fotos samt Alben und Datum hier hineinkommen, ohne dass du hunderte ZIP-Dateien von Hand entpackst, steht im Beitrag zu immich-go und Google Takeout; was in Immich 3.2 neu dazukam, dort.
Quellen
- Immich Docs: Docker Compose (Installation, .env-Variablen, Docker Engine 25+)
- Immich v3.2.4: offizielle docker-compose.yml (Images, Prüfsummen, shm_size, Healthchecks)
- Immich v3.2.4: example.env (IMMICH_VERSION=v3, UPLOAD_LOCATION, DB_PASSWORD)
- Immich Docs: Requirements (RAM, CPU x86-64-v2, Dateisysteme, keine Netzlaufwerke für die Datenbank)
- Immich Docs: Environment Variables (TZ, DB_*, IMMICH_PORT, Container neu erzeugen)
- Immich Docs: Post installation steps (erster Benutzer ist Admin, Speichervorlage, Mobile App, Backups)
- Immich Docs: Upgrading (pull, Release Notes, App vor Server, kein Downgrade)
- Immich Docs: Backup and Restore (Ordner unter UPLOAD_LOCATION, tägliches Datenbank-Backup, Reihenfolge)
- Immich Docs: Storage Template (Vorgabe, Migrationsauftrag)
- Immich Docs: System Settings (Machine Learning, Aufträge, Papierkorb 30 Tage, Backup)
- Immich Docs: FAQ (Exit-Code 137 und 132, WebSockets, Machine Learning abschalten, reset-admin-password)
- Immich Docs: Mobile App (Server-URL, Backup-Bildschirm, Einbahnstraße)
- Immich Docs: Automatic Backup (Hintergrund unter iOS und Android, nur WLAN)
- Immich v3.2.4: Release Notes (28-09-2026)
- Immich: deutsche Sprachdatei der Oberfläche (Bezeichnungen der Menüs und Felder)
- Docker Docs: Compose-Referenz, depends_on mit condition: service_healthy
- GitHub Discussions: Cannot start database with all default settings (AppArmor auf Debian 13, 08-2025)