> ## Content Index
> Fetch the complete content index at: https://sakis.tech/llms.txt
> Use this file to discover other available public pages before exploring further.

# Immich installieren: eigene Foto-Cloud per Docker Compose
- URL: https://sakis.tech/immich-installieren-docker-compose/
- Published: 2026-10-06T08:53:23.000Z
- Updated: 2026-10-06T08:53:23.000Z
- Description: Vier Container, ein Passwort, ein Ordner für die Fotos: Immich läuft mit der offiziellen Compose-Datei, im Sandkasten geprüft. Dazu Admin-Konto, Speichervorlage, Handy-App und was ab Werk offen ist.
- Author: Sakis
- Tags: homelab, docker

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](https://sakis.tech/raus-aus-google-fotos-so-ziehst-du-deine-bilder-zu-immich-um/) richtig; hier geht es um den Server davor.

**Kurz gesagt:** Am Ende läuft Immich mit vier Containern auf deinem Server, du bist als Admin angemeldet, die Handy-App sichert deine Alben ins Heimnetz, die Speichervorlage legt Fotos nach Jahr und Tag ab, und die Datenbank sichert sich ab Werk jede Nacht selbst. Dauer: rund 30 Minuten plus die Zeit, die dein Anschluss für gut zwei Gigabyte Images braucht. Stufe: Standard, Docker und Kommandozeile im Groben bekannt, alles Weitere wird erklärt. Stand: Immich 3.2.4, geprüft am 06-10-2026.

![Schaubild: Immich in drei Schritten: compose.yaml mit vier Containern anlegen, Passwort und Foto-Ordner eintragen; docker compose up -d und ps, vier Zeilen healthy; Port 2283 im Browser, erster Benutzer ist Admin, Handy-App koppeln, Datenbank-Backup läuft ab Werk](https://sakis.tech/content/images/2026/09/grafik-43.png)

Der ganze Weg auf einen Blick: Bauplan, Start, erster Benutzer.

## 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-server`** ist 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-learning`** ist 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.
- **`database`** ist 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.
- **`redis`** heiß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.

Handy-App / Browser→ Port 2283 →immich-server→ Metadaten →PostgreSQL→ Bildanalyse →Machine Learning

**Machine Learning?** Ein Programm, das aus vielen Beispielbildern gelernt hat, wie ein Hund, ein Strand oder ein bestimmtes Gesicht aussieht, und das neue Bilder danach einsortiert. Bei Immich läuft das komplett auf deinem Server, ohne Cloud-Dienst dahinter; die Modelle dafür lädt der Container beim ersten Auftrag herunter und behält sie im Volume `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 version` muss eine Versionsnummer ausgeben. Fehlt Docker, steht die Installation in der [Compose-Anleitung für Einsteiger](https://sakis.tech/docker-compose-grundlagen-fuer-einsteiger/), Schritt 1\. Die Doku verlangt Docker Engine ab Version 25; `docker version --format '{{.Server.Version}}'` zeigt deine.
- Arbeitsspeicher: `free -h` zeigt in der Zeile `Mem:` unter `total`, was der Rechner hat. Unter 6 GB: Machine Learning später abschalten.
- Prozessorkerne: `nproc` gibt 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 -I` zeigt 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.

**So liest du diese Anleitung:** Alles, was du selbst tun sollst, steht in einem farbigen Kasten. **\[ per klick \]** heißt: Das erledigst du mit der Maus in einer Web-Oberfläche, hier der Immich-Oberfläche im Browser und der Immich-App auf dem Handy. **\[ über die shell \]** heißt: Den Befehl kopieren, ins Terminal einfügen, Enter. Stehen beide Kästen direkt untereinander, führen sie zum selben Ergebnis. Du gehst EINEN davon, nicht beide.

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: `Wolkenlos2026` als 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`, Name `Sakis`, 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:

```bash
mkdir -p ~/immich
cd ~/immich
```

Datei anlegen; `nano` ist ein Texteditor fürs Terminal:

```bash
nano compose.yaml
```

Inhalt 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:

```yaml
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:

```bash
docker compose config --quiet && echo "Datei in Ordnung"
```

```text
Datei in Ordnung
```

Die 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.yml` und 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: …:v3` statt `${IMMICH_VERSION:-release}`.** Die Vorgabe in der offiziellen `.env` ist `v3`, und ich übernehme sie: Damit bekommst du bei jedem `pull` die 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_on` mit `condition: 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. Mit `restart: always` hä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 von `depends_on` ist 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.

**@sha256:…?** Die lange Zeichenkette hinter dem Image-Namen ist die Prüfsumme genau dieses Images, wie der Fingerabdruck einer Datei. Mit ihr zieht Docker nicht „irgendein Valkey 9", sondern exakt das Valkey 9, das die Immich-Entwickler mit dieser Version getestet haben. Ändert sich das Image auf dem Server, passt die Prüfsumme nicht mehr, und Docker lehnt es ab. Für die Datenbank ist das mehr als Kosmetik: Ein falsches Postgres-Image kann die Datenbank unbrauchbar machen.

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.

```bash
docker compose up -d
```

```text
 ✔ Container immich_redis                                                                                  Healthy 32.5s
 ✔ Container immich_postgres                                                                               Healthy  6.5s
 ✔ Container immich_machine_learning                                                                       Started  1.5s
 ✔ Container immich_server                                                                                 Started 32.3s
```

Das 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:

```bash
docker compose ps
```

```text
NAME                      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/tcp
```

Die 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:

```bash
docker compose logs immich-server --tail 20
```

```text
immich_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:

```bash
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:2283/
```

```text
200
```

Eine 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:

```bash
stat -c '%u %g %n' ~/immich/*
```

```text
1000 1000 /home/sakis/immich/compose.yaml
0 0 /home/sakis/immich/library
999 0 /home/sakis/immich/postgres
```

Die 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.

![Die Startseite von Immich mit dem Link Erste Schritte und darunter dem Knopf Von Datenbank wiederherstellen.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-01-2026-10-06.png)

Hier klicken

![Das Formular Admin-Registrierung mit E-Mail sakis@example.com, zweimal Passwort, Name Sakis und dem Knopf Registrieren.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-02-2026-10-06.png)

(1) sakis@example.com; (2) Sakis; (3) Hier klicken

![Die Anmeldeseite von Immich mit der E-Mail sakis@example.com, dem Passwortfeld und dem Knopf Anmelden.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-03-2026-10-06.png)

(1) sakis@example.com; (2) Hier klicken

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 Seite Sprache des Assistenten mit der Auswahl Deutsch und dem Knopf Privatsphäre auf dem Server zum Weitergehen.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-05-2026-10-06.png)

(1) Deutsch; (2) Hier klicken

![Die Seite Speichervorlage des Assistenten mit eingeschaltetem Schalter Speichervorlagen-Engine aktivieren und der Marke Ungespeicherte Änderung.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-06-2026-10-06.png)

Schalter einschalten

![Das Feld Vorlage mit der Vorgabe {{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}} und der Knopf Sicherungen, der die Änderung speichert.](https://sakis.tech/content/images/2026/10/labor-immich-installieren-docker-compose-07-2026-10-06.png)

(1) Vorgabe stehen lassen; (2) Hier klicken

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:

```bash
ls ~/immich/library
```

```text
backups
encoded-video
library
profile
thumbs
upload
```

Das 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

1. **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.
2. **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](https://sakis.tech/wg-easy-docker-compose/), dann bleibt die Adresse in der App dieselbe; oder ein [Reverse Proxy](https://sakis.tech/nginx-proxy-manager-installieren/) mit echtem Zertifikat, dann muss laut FAQ WebSocket-Unterstützung an sein, sonst meldet die App „Server offline", obwohl er läuft.
3. **Die Datenbank sichert sich selbst, deine Fotos nicht.** Ab Werk legt Immich jede Nacht um 2 Uhr einen Datenbank-Export unter `library/backups` ab 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/library` an 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.
4. **Updates kommen mit `pull`, nicht von selbst, und die App zuerst.** Im Ordner `~/immich` einmal im Monat `docker compose pull` und `docker 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 Tag `v3` hält dich von einer 4.0 fern, bis du sie willst.
5. **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-learning` samt seiner Zeile `model-cache:` unter `volumes:` aus der Compose-Datei, dann `docker 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](https://sakis.tech/docker-ufw-ports-trotz-firewall-offen/), 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:

```bash
docker exec -it immich_server reset-admin-password
```

**Die 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](https://sakis.tech/raus-aus-google-fotos-so-ziehst-du-deine-bilder-zu-immich-um/); was in [Immich 3.2](https://sakis.tech/immich-3-2-0-release/) neu dazukam, dort.

sakis@homelab:\~$ echo "bleib neugierig — und mach backups" 

## Quellen

- [Immich Docs: Docker Compose (Installation, .env-Variablen, Docker Engine 25+)](https://docs.immich.app/install/docker-compose?ref=sakis.tech)
- [Immich v3.2.4: offizielle docker-compose.yml (Images, Prüfsummen, shm\_size, Healthchecks)](https://github.com/immich-app/immich/blob/v3.2.4/docker/docker-compose.yml?ref=sakis.tech)
- [Immich v3.2.4: example.env (IMMICH\_VERSION=v3, UPLOAD\_LOCATION, DB\_PASSWORD)](https://github.com/immich-app/immich/blob/v3.2.4/docker/example.env?ref=sakis.tech)
- [Immich Docs: Requirements (RAM, CPU x86-64-v2, Dateisysteme, keine Netzlaufwerke für die Datenbank)](https://docs.immich.app/install/requirements?ref=sakis.tech)
- [Immich Docs: Environment Variables (TZ, DB\_\*, IMMICH\_PORT, Container neu erzeugen)](https://docs.immich.app/install/environment-variables?ref=sakis.tech)
- [Immich Docs: Post installation steps (erster Benutzer ist Admin, Speichervorlage, Mobile App, Backups)](https://docs.immich.app/install/post-install?ref=sakis.tech)
- [Immich Docs: Upgrading (pull, Release Notes, App vor Server, kein Downgrade)](https://docs.immich.app/install/upgrading?ref=sakis.tech)
- [Immich Docs: Backup and Restore (Ordner unter UPLOAD\_LOCATION, tägliches Datenbank-Backup, Reihenfolge)](https://docs.immich.app/administration/backup-and-restore?ref=sakis.tech)
- [Immich Docs: Storage Template (Vorgabe, Migrationsauftrag)](https://docs.immich.app/administration/storage-template?ref=sakis.tech)
- [Immich Docs: System Settings (Machine Learning, Aufträge, Papierkorb 30 Tage, Backup)](https://docs.immich.app/administration/system-settings?ref=sakis.tech)
- [Immich Docs: FAQ (Exit-Code 137 und 132, WebSockets, Machine Learning abschalten, reset-admin-password)](https://docs.immich.app/FAQ?ref=sakis.tech)
- [Immich Docs: Mobile App (Server-URL, Backup-Bildschirm, Einbahnstraße)](https://docs.immich.app/features/mobile-app?ref=sakis.tech)
- [Immich Docs: Automatic Backup (Hintergrund unter iOS und Android, nur WLAN)](https://docs.immich.app/features/automatic-backup?ref=sakis.tech)
- [Immich v3.2.4: Release Notes (28-09-2026)](https://github.com/immich-app/immich/releases/tag/v3.2.4?ref=sakis.tech)
- [Immich: deutsche Sprachdatei der Oberfläche (Bezeichnungen der Menüs und Felder)](https://github.com/immich-app/immich/blob/v3.2.4/i18n/de.json?ref=sakis.tech)
- [Docker Docs: Compose-Referenz, depends\_on mit condition: service\_healthy](https://docs.docker.com/reference/compose-file/services/?ref=sakis.tech#depends%5Fon)
- [GitHub Discussions: Cannot start database with all default settings (AppArmor auf Debian 13, 08-2025)](https://github.com/immich-app/immich/discussions/20901?ref=sakis.tech)