| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung |
| it:thinkcentreserver [2026/06/21 21:11] – [6.11 Ghost (CMS für die Porgys)] matthias | it:thinkcentreserver [2026/06/30 15:43] (aktuell) – [6.1 Nginx Proxy Manager (NPM)] matthias |
|---|
| | **Docker-Configs & Indizes (High-End)** | | | | | | **Docker-Configs & Indizes (High-End)** | | | | |
| | ''/opt/docker/[dienstname]/config'' | NVMe SSD | Konfigurationsdaten (Nextcloud, HA, Pi-hole, NPM) | ''${PATH_SSD}'' | | | ''/opt/docker/[dienstname]/config'' | NVMe SSD | Konfigurationsdaten (Nextcloud, HA, Pi-hole, NPM) | ''${PATH_SSD}'' | |
| | | ''/opt/docker/homeassistant/'' | NVMe SSD | HA-Konfiguration (''configuration.yaml'', ''automations.yaml'', ''zigbee.db'') | ''${PATH_SSD}'' | |
| | ''/opt/docker/nextcloud/apps'' | NVMe SSD | Nextcloud Custom-Apps (Ergänzt wegen Compose-Konsistenz) | ''${PATH_SSD}'' | | | ''/opt/docker/nextcloud/apps'' | NVMe SSD | Nextcloud Custom-Apps (Ergänzt wegen Compose-Konsistenz) | ''${PATH_SSD}'' | |
| | ''/opt/docker/nextcloud/db'' | NVMe SSD | MariaDB-Datenbank (Nextcloud & Ghost) | ''${PATH_SSD}'' | | | ''/opt/docker/nextcloud/db'' | NVMe SSD | MariaDB-Datenbank (Nextcloud & Ghost) | ''${PATH_SSD}'' | |
| | ''/mnt/sata-ssd/homeassistant/db'' | SATA-SSD | Home Assistant Recorder-Datenbank (''home-assistant_v2.db'') | ''${PATH_SATA}'' | | | ''/mnt/sata-ssd/homeassistant/db'' | SATA-SSD | Home Assistant Recorder-Datenbank (''home-assistant_v2.db'') | ''${PATH_SATA}'' | |
| | ''/mnt/sata-ssd/paperless/consume'' | SATA-SSD | Paperless-ngx Einzugsordner (Permanenter OCR-Scan) | ''${PATH_SATA}'' | | | ''/mnt/sata-ssd/paperless/consume'' | SATA-SSD | Paperless-ngx Einzugsordner (Permanenter OCR-Scan) | ''${PATH_SATA}'' | |
| | ''/mnt/sata-ssd/paperless/data'' | SATA-SSD | Interner Suchindex von Paperless-ngx | ''${PATH_SATA}'' | | | ''/mnt/sata-ssd/paperless/data'' | SATA-SSD | Interner Suchindex und Dokumentenstruktur von Paperless-ngx | ''${PATH_SATA}'' | |
| | | ''/mnt/sata-ssd/paperless/data/documents/originals/'' | SATA-SSD | Strukturierte Originaldokumente (Unterordner: ''gemeinsam/'', ''matthias/'', ''jana/'') | ''${PATH_SATA}'' | |
| | ''/mnt/sata-ssd/immich/encoded-video'' | SATA-SSD | Temporäre Arbeitsdateien für das Video-Transcoding | ''${PATH_SATA}'' | | | ''/mnt/sata-ssd/immich/encoded-video'' | SATA-SSD | Temporäre Arbeitsdateien für das Video-Transcoding | ''${PATH_SATA}'' | |
| | ''/mnt/sata-ssd/ghost/content'' | SATA-SSD | Ghost-CMS Inhalt (Themes, Bilder, Uploads) | ''${PATH_SATA}'' | | | ''/mnt/sata-ssd/ghost/content'' | SATA-SSD | Ghost-CMS Inhalt (Themes, Bilder, Uploads) | ''${PATH_SATA}'' | |
| PATH_SATA=/mnt/sata-ssd | PATH_SATA=/mnt/sata-ssd |
| PATH_HDD=/media/usbhdd1/ocdata | PATH_HDD=/media/usbhdd1/ocdata |
| | PATH_HA_DB=/mnt/sata-ssd/homeassistant/db |
| | |
| | USER_ID=1000 |
| | GROUP_ID=1000 |
| | |
| | # --- KEEPASS-REFERENZEN --- |
| DB_ROOT_PASSWORD=EinSehrSicheresRootPasswort123! | DB_ROOT_PASSWORD=EinSehrSicheresRootPasswort123! |
| DB_PASSWORD=NextcloudDbPasswort456! | DB_PASSWORD=NextcloudDbPasswort456! |
| |
| <code yaml> | <code yaml> |
| version: '3.8' | |
| |
| networks: | networks: |
| server-network: | server-network: |
| - server-network | - server-network |
| |
| # --- Nextcloud --- | |
| | # --- Nextcloud --- |
| |
| nextcloud: | nextcloud: |
| - server-network | - server-network |
| |
| # --- Paperless-ngx --- | # --- Paperless-ngx --- |
| |
| paperless-redis: | paperless-redis: |
| - paperless-redis | - paperless-redis |
| ports: | ports: |
| - "8090:8000" | - "8090:8000" # Intern läuft Paperless auf 8000, wir legen es auf Port 8090 am TC |
| volumes: | volumes: |
| - ${PATH_SSD}/paperless/config:/usr/src/paperless/data | - ${PATH_SSD}/paperless/config:/usr/src/paperless/data |
| - PAPERLESS_REDIS=redis://paperless-redis:6379 | - PAPERLESS_REDIS=redis://paperless-redis:6379 |
| - PAPERLESS_TIME_ZONE=${TZ} | - PAPERLESS_TIME_ZONE=${TZ} |
| - PAPERLESS_OCR_LANGUAGE=deu+eng | - PAPERLESS_OCR_LANGUAGE=deu+eng # Deutsche und englische Texterkennung laden |
| - USER_ID=1000 | - USER_ID=1000 # Entspricht deinem User matthias (PUID) |
| - GROUP_ID=1000 | - GROUP_ID=1000 # Entspricht deiner Gruppe matthias (PGID) |
| - PAPERLESS_CONSUMER_POLLING=10 | - PAPERLESS_CONSUMER_POLLING=15 |
| | - PAPERLESS_CONSUMER_POLLING_RETRY_COUNT=10 |
| | - PAPERLESS_CONSUMER_POLLING_DELAY=5 |
| - PAPERLESS_CONSUMER_USE_INOTIFY=false | - PAPERLESS_CONSUMER_USE_INOTIFY=false |
| - PAPERLESS_CONSUMER_RECURSIVE=true | - PAPERLESS_CONSUMER_RECURSIVE=true |
| | - PAPERLESS_CONSUMER_ENABLE_BARCODES=true |
| | - PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE=true |
| | - PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX=ASN |
| | - PAPERLESS_CONSUMER_BARCODE_DPI=600 |
| | - PAPERLESS_CONSUMER_BARCODE_UPSCALE=2 |
| | - CELERY_WORKER_CONCURRENCY=4 |
| | - 'PAPERLESS_OCR_USER_ARGS={"continue_on_soft_render_error": true}' |
| | |
| | networks: |
| | - server-network |
| | |
| | |
| | # --- Home Assistant Stack --- |
| | |
| | homeassistant: |
| | image: ghcr.io/home-assistant/home-assistant:latest |
| | container_name: homeassistant |
| | restart: unless-stopped |
| | volumes: |
| | # Performance-Kritisch auf NVMe (alles außer die dicke DB) |
| | - ${PATH_SSD}/homeassistant:/config |
| | # Schreibintensiver DB-Ordner komplett auf die SATA-SSD umgebogen |
| | - /mnt/sata-ssd/homeassistant/db:/config/db |
| | environment: |
| | - TZ=${TZ} |
| | network_mode: "host" # Für Entdeckungsdienste (mDNS/UPnP) im Smart Home zwingend empfohlen |
| | |
| | mosquitto: |
| | image: eclipse-mosquitto:2 |
| | container_name: mosquitto |
| | restart: unless-stopped |
| | ports: |
| | - "1883:1883" |
| | - "9001:9001" |
| | volumes: |
| | - ${PATH_SSD}/mosquitto/config:/mosquitto/config |
| | - ${PATH_SSD}/mosquitto/data:/mosquitto/data |
| | - ${PATH_SSD}/mosquitto/log:/mosquitto/log |
| networks: | networks: |
| - server-network | - server-network |
| |
| ==== 5.2 Docker-Updates ==== | ==== 5.2 Docker-Updates ==== |
| | Da die Docker-Infrastruktur aus Performance- und Strukturgründen in zwei separate Stacks aufgeteilt ist (Haupt-Infrastruktur und Immich), müssen Updates in den jeweiligen Projektverzeichnissen getriggert werden. |
| | |
| | === Manueller Update-Prozess === |
| | Der optimierte Dreischritt holt die neuesten Images, startet geänderte Container neu und räumt verwaiste Image-Leichen direkt auf: |
| <code bash> | <code bash> |
| # Standard-Vierzeiler für Updates über docker-compose: | # 1. Haupt-Infrastruktur updaten |
| cd /opt/docker/ | cd /opt/docker/ |
| docker compose pull | docker compose pull && docker compose up -d --remove-orphans && docker image prune -a |
| docker compose up -d | |
| docker image prune -f | # 2. Immich Foto-Infrastruktur separat updaten |
| | cd /opt/docker/immich/ |
| | docker compose pull && docker compose up -d --remove-orphans && docker image prune -a |
| | </code> |
| | |
| | === Automatisierung via Bash-Alias (Empfohlen) === |
| | Um im Alltag nicht manuell in die Verzeichnisse springen zu müssen, ist in der ''~/.bashrc'' des Users ''matthias'' ein globaler Verkettungs-Alias hinterlegt: |
| | |
| | <code> |
| | alias update-server='cd /opt/docker && sudo docker compose pull && sudo docker compose up -d --remove-orphans && cd /opt/docker/immich && sudo docker compose pull && sudo docker compose up -d --remove-orphans && docker image prune -af && cd ~' |
| | </code> |
| | |
| | **Wartungsbefehl im Alltag:** |
| | <code bash> |
| | update-server |
| </code> | </code> |
| |
| du -h --max-depth=1 | du -h --max-depth=1 |
| </code> | </code> |
| | |
| | ==== 5.4 Shell-Befehle ==== |
| | ^ Kategorie ^ Befehl ^ Beschreibung / Parameter ^ |
| | | **Speicher** | ''du -hd 1 /pfad/ | sort -h'' | Zeigt Ordnergröße der ersten Unterebene, menschlich lesbar (''-h''), numerisch sortiert (''sort -h''): | |
| | | | ''df -h'' | Zeigt freien/belegten Speicherplatz aller gemounteten Partitionen. | |
| | | **Transfer** | ''scp -r user@ip:/quelle/ "C:\ziel"'' | **Lokal in Win-PowerShell:** Rekursiver Download (''-r'') vom Server zu Windows. | |
| | | | ''scp /quelle user@ip:/ziel/'' | Kopiert Datei via SSH von Linux zu Linux. | |
| | | **Immich-CLI** | **In Win-PowerShell (Sitzungsvariablen):** ''$env:IMMICH_INSTANCE="http://192.168.178.128:2283/api"'' ''$env:IMMICH_KEY="wVujBLe3..."'' | Setzt die Verbindungsparameter für das Immich-CLI in der aktuellen Windows-Sitzung, um Parameter-Fehler zu vermeiden. | |
| | | | ''immich upload --recursive "C:\pfad\"'' | Schiebt lokale Windows-Ordnerstrukturen stabil und parallel über das Netzwerk auf das TC (Sitzungsvariablen vorausgesetzt). | |
| | | **Rsync** | ''rsync -avzP --delete /quell/ /ziel/'' | **Backup-Standard:** Synchronisiert Ordner. ''-a'' (Rechte), ''-v'' (Details), ''-z'' (Kompression), ''-P'' (Fortschritt+Resume), ''--delete'' (löscht verwaiste Ziel-Dateien). | |
| | | **Docker** | ''docker compose up -d'' | Startet alle Container des Verzeichnisses im Hintergrund (Detached). | |
| | | | ''docker compose up -d [name]'' | Startet/Aktualisiert nur einen spezifischen Dienst (z. B. ''homeassistant''). | |
| | | | ''docker compose down'' | Stoppt Container und baut Docker-Netzwerk ab (Daten auf SSDs bleiben unberührt). | |
| | | | ''docker compose ps -a'' | Zeigt alle Container des Stacks mit aktuellem Status (Up, Exited) und Ports an. | |
| | | | ''docker compose stop'' | Pausiert Container temporär (ohne Netzwerkabbau). | |
| | | | ''docker compose pull'' | Lädt neuere Container-Images laut Definition in ''docker-compose.yml'' herunter. | |
| | | | ''docker image prune -a'' | Löscht ungenutzte, alte Image-Leichen und gibt massig Speicherplatz auf NVMe frei. | |
| | | **Logs** | ''docker compose logs -f --tail 50'' | Zeigt die letzten 50 Log-Zeilen aller Dienste an und bleibt live geöffnet (''-f''). | |
| | | | ''docker logs -f [name]'' | Zeigt Live-Logs eines spezifischen Containers (z. B. ''homeassistant''). | |
| | | **Rechte** | ''sudo chown -R user:group /pfad/'' | Ändert den Besitzer eines Verzeichnisses rekursiv (''-R''). | |
| | | | ''sudo chmod -R 755 /pfad/'' | Setzt Rechte rekursiv: Besitzer darf alles (7), Gruppe/Andere nur Lesen/Ausführen (5). | |
| |
| ===== 6. Dienst-spezifische Notizen ===== | ===== 6. Dienst-spezifische Notizen ===== |
| |
| ==== 6.1 Nginx Proxy Manager (NPM) ==== | ==== 6.1 Nginx Proxy Manager (NPM) ==== |
| | |
| === Installation & Protokoll === | === Installation & Protokoll === |
| * **Interner Port / Protokoll:** 80 (HTTP), 443 (HTTPS), 81 (Web-UI Admin) | * **Interner Port / Protokoll:** 80 (HTTP), 443 (HTTPS), 81 (Web-UI Admin) |
| * **Externer Zugriff:** Ports 80 & 443 direkt im Router auf das TC weitergeleitet. | * **Externer Zugriff:** Ports 80 & 443 direkt im Router auf das TC weitergeleitet. |
| * **Abhängigkeiten:** Keinerlei Abhängigkeiten. Das Einfallstor für alle HTTP-Dienste. | * **Abhängigkeiten:** Keinerlei Abhängigkeiten. Das Einfallstor für alle HTTP-Dienste. |
| | |
| === Bedienung & Wichtige Befehle === | === Bedienung & Wichtige Befehle === |
| * **Web-UI:** [[http://192.168.178.200:81]] (temporär [[http://192.168.178.128:81]]) | * **Web-UI:** [[http://192.168.178.128:81]] (Zentral auf dem ThinkCentre) |
| * **Tuning:** In den Proxy-Hosts standardmäßig "Block Common Exploits" und "HTTP/2 Support" für Performance und Sicherheit aktivieren. Für Datei-Uploads (Nextcloud/Immich) ''client_max_body_size 512M;'' unter Advanced eintragen. | * **Tuning:** In den Proxy-Hosts standardmäßig "Block Common Exploits" und "HTTP/2 Support" für Performance und Sicherheit aktivieren. Für massive Datei-Uploads (Nextcloud/Immich) zwingend ''client_max_body_size 0;'' (hebt das Limit komplett auf) oder ''client_max_body_size 10G;'' unter Advanced eintragen. |
| | |
| | === Aktive Domain-Struktur (Manitu CNAME) === |
| | Alle Subdomains der Hauptdomain ''tietge.org'' sind im Manitu-Kundencenter als **CNAME-Eintrag** auf das DynDNS ''pfogel.selfhost.bz.'' gemappt, um dynamische IP-Wechsel der FritzBox abzufangen: |
| | |
| | ^ Subdomain ^ Internes Docker-Ziel (TC) ^ Beschreibung / Zweck ^ |
| | | ''wg-wiki.tietge.org'' | ''wg-wiki:80'' | WG-DokuWiki Instanz | |
| | | ''band-wiki.tietge.org'' | ''band-wiki:80'' | Band-DokuWiki Instanz | |
| | | ''ak-wiki.tietge.org'' | ''ak-wiki:80'' | Arbeitskreis-DokuWiki Instanz | |
| | | ''nextcloud.tietge.org'' | ''nextcloud:80'' | Neue Familien-Zentrale auf dem TC | |
| | | ''fotos.tietge.org'' | ''immich_server:2283'' | Immich Foto-Infrastruktur | |
| | | ''porgys.tietge.org'' | ''ghost:2368'' | Ghost CMS Band-Webseite | |
| | |
| | === Migrations- & Routing-Architektur (Fernzugriff) === |
| | Um während der Migrationsphase Ausfallzeiten zu verhindern, fungiert der NPM auf dem ThinkCentre als **zentrale Weiche (Reverse Proxy)** im Heimnetzwerk. Da er sowohl im isolierten ''server-network'' als auch im normalen LAN agiert, routet er den Traffic anhand der aufrufenden Domain bzw. des Subpfads: |
| | |
| | == 1. Fallback für bestehende Alt-Systeme (Raspberry Pi) == |
| | Damit alte Lesezeichen und Smartphone-Syncs über die Selfhost-Domain nicht brechen, leitet ein "Catch-All"-Proxy-Host Anfragen an ''pfogel.selfhost.bz'' per internem HTTPS (Port 443) direkt weiter an den alten Raspberry Pi (''192.168.178.200''). Da dort aktuell unter anderem noch die aktive Nextcloud läuft, bleibt dieser Haupt-Forward unberührt, bis alle Altdienste vollständig migriert sind. SSL-Zertifikate kollidieren hierbei nicht, da der NPM die äußere Verschlüsselung übernimmt und intern verschlüsselt mit dem Pi spricht (SSL-Terminierung). |
| | |
| | == 2. Nahtlose Wiki-Migration via Custom Locations (Zwei-Wege-System) == |
| | Die drei DokuWikis wurden erfolgreich auf das ThinkCentre migriert und laufen nativ und ohne Unterordner auf ihren jeweiligen ''tietge.org''-Subdomains. Damit alte Lesezeichen über die Selfhost-Unterpfade nicht ins Leere laufen (oder auf dem RPi sterben), fängt der NPM diese Pfade gezielt ab und leitet sie per Nginx-Rewrite transparent und unter Beibehaltung aller Unterseiten auf die neuen Domains um. |
| | |
| | Dazu sind im NPM unter dem Proxy-Host ''pfogel.selfhost.bz'' drei **Custom Locations** definiert: |
| | |
| | **Band-Wiki:** |
| | * **Define Location:** ''/band-wiki'' |
| | * **Scheme & Ziel:** ''http://192.168.178.128:8081'' |
| | * **Erweiterte Nginx-Konfiguration (Zahnrad):** |
| | <code nginx> |
| | rewrite ^/band-wiki(.*)$ https://band-wiki.tietge.org$1 permanent; |
| | </code> |
| | |
| | **WG-Wiki:** |
| | * **Define Location:** ''/wg-wiki'' |
| | * **Scheme & Ziel:** ''http://192.168.178.128:8083'' |
| | * **Erweiterte Nginx-Konfiguration (Zahnrad):** |
| | <code nginx> |
| | rewrite ^/wg-wiki(.*)$ https://wg-wiki.tietge.org$1 permanent; |
| | </code> |
| | |
| | **AK-Wiki:** |
| | * **Define Location:** ''/ak-wiki'' |
| | * **Scheme & Ziel:** ''http://192.168.178.128:8082'' |
| | * **Erweiterte Nginx-Konfiguration (Zahnrad):** |
| | <code nginx> |
| | rewrite ^/ak-wiki(.*)$ https://ak-wiki.tietge.org$1 permanent; |
| | </code> |
| |
| | == 3. Zukünftiger Nextcloud-Umzug == |
| | Sobald die Nextcloud auf das TC migriert wird, wird analog zu den Wikis eine Custom Location für ''/nextcloud'' eingerichtet, um den Traffic aus dem Selfhost-Proxy herauszuschneiden. Bis dahin verbleibt der Nextcloud-Traffic im globalen Fallback auf den Raspberry Pi (''192.168.178.200''). |
| ==== 6.2 Pi-hole ==== | ==== 6.2 Pi-hole ==== |
| === Installation & Protokoll === | === Installation & Protokoll === |
| |
| ==== 6.9 Paperless-ngx ==== | ==== 6.9 Paperless-ngx ==== |
| | === Shell Befehle === |
| | * Verzeichnis: ''cd /opt/docker/'' |
| | * Scan Attribute Dokumente ''docker compose exec -it paperless-webserver python3 /usr/src/paperless/src/manage.py document_create_classifier'' |
| | |
| === Installation & Protokoll === | === Installation & Protokoll === |
| * **Interner Port / Protokoll:** 8000 (Auf Host-Port 8090 gemappt) | * **Interner Port / Protokoll:** 8000 (Auf Host-Port 8090 gemappt) |
| === Besonderheiten & Pfadtrennung === | === Besonderheiten & Pfadtrennung === |
| Das System nutzt ein dreistufiges Mapping zur optimalen Performanceverteilung: | Das System nutzt ein dreistufiges Mapping zur optimalen Performanceverteilung: |
| 1. **NVMe SSD:** Server-Konfigurationen und App-Daten (''/usr/src/paperless/data''). | - **NVMe SSD:** Server-Konfigurationen und App-Daten (''/usr/src/paperless/data''). |
| 2. **SATA-SSD (Stoßdämpfer):** Schreibintensiver, permanenter Suchindex sowie der ''consume''-Ordner für das Datei-Scanning (''/usr/src/paperless/consume''). | - **SATA-SSD (Stoßdämpfer):** Schreibintensiver, permanenter Suchindex sowie der ''consume''-Ordner für das Datei-Scanning (''/usr/src/paperless/consume''). |
| 3. **Massenspeicher:** Finale, fertig verarbeitete PDF-Archivdateien werden unter ''/usr/src/paperless/media'' abgelegt. *(Aktuell auf SATA-SSD gemappt, vorbereitet für den direkten HDD-Wechsel über ${PATH_SATA}).* | - **Massenspeicher:** Finale, fertig verarbeitete PDF-Archivdateien werden unter ''/usr/src/paperless/media'' abgelegt. *(Aktuell auf SATA-SSD gemappt, vorbereitet für den direkten HDD-Wechsel über ${PATH_SATA}).* |
| |
| === Linux-Dateisystem & FTP-Brücke (fstab Bind-Mounts) === | === Linux-Dateisystem & FTP-Brücke (fstab Bind-Mounts) === |
| //Hinweis für die Weboberfläche: Beim Erstellen eines neuen Arbeitsablaufs muss das Feld "Sortierreihenfolge" zwingend mit einer Zahl (z.B. 1) befüllt werden, da Paperless den Workflow sonst nicht speichert. Der Inhaltsabgleichsalgorithmus wird auf "Keiner" gesetzt, da das Verzeichnis-Polling über die Variable PAPERLESS_CONSUMER_RECURSIVE=true die Zuteilung vollständig steuert.// | //Hinweis für die Weboberfläche: Beim Erstellen eines neuen Arbeitsablaufs muss das Feld "Sortierreihenfolge" zwingend mit einer Zahl (z.B. 1) befüllt werden, da Paperless den Workflow sonst nicht speichert. Der Inhaltsabgleichsalgorithmus wird auf "Keiner" gesetzt, da das Verzeichnis-Polling über die Variable PAPERLESS_CONSUMER_RECURSIVE=true die Zuteilung vollständig steuert.// |
| ==== 6.10 Immich (Foto-Infrastruktur) ==== | ==== 6.10 Immich (Foto-Infrastruktur) ==== |
| | |
| | Selbstgehostete Foto- und Videoplattform als performanter Ersatz für Google Photos. |
| | |
| === Installation & Protokoll === | === Installation & Protokoll === |
| * **Interner Port / Protokoll:** 2283 (HTTP) | * **Interner Port/Protokoll:** 2283 (HTTP) |
| * **Externer Zugriff:** NPM Proxy Host mit aktiven Websockets. | * **Lokale Web-UI:** http://192.168.178.128:2283/ |
| * **Abhängigkeiten:** Benötigt ''immich-db'' (Postgres mit Vektorerweiterung) und ''nextcloud-redis''. | * **Externer Zugriff:** Über NPM Proxy Host mit aktiven Websockets und ''client_max_body_size 512M;'' |
| === Besonderheiten (Das perfekte Scroll-Tuning) === | * **Abhängigkeiten:** Nutzt eine isolierte PostgreSQL-Datenbank mit Vektorerweiterung (''pgvecto-rs'') und teilt sich den zentralen Redis-Cache. |
| Um das flüssige Durchscrollen der Handy-Timeline ohne NVMe-Verschleiß zu realisieren, ist der Container in drei Zonen zerlegt: | |
| 1. **NVMe SSD:** Speicherort für ''/thumbs'' (Kleine WebP/JPEG-Vorschaubilder für die App-Timeline). | |
| 2. **SATA-SSD:** Speicherort für ''/encoded-video'' (Temporärer Arbeitsordner für rechenintensives Video-Transcoding). | |
| 3. **4TB HDD1:** Speicherort für ''/library'' und ''/upload'' (Die originalen, schweren Bild- und Videodateien). | |
| |
| | === Das 3-Zonen-Speicher-Mapping === |
| | |
| | Um maximales Scroll-Tuning in der App ohne NVMe-Verschleiß zu realisieren, ist der Dienst physisch strikt getrennt: |
| | * **1. High-End Layer (NVMe SSD):** Die kritische PostgreSQL-Datenbank liegt zwecks maximaler IOPS unter ''/opt/docker/immich/db''. |
| | * **2. Stoßdämpfer Layer (SATA-SSD):** Rechenintensive Caches, temporäres Video-Transcoding (''/mnt/sata-ssd/immich/encoded-video'') sowie die generierten Timeline-Vorschaubilder (''/mnt/sata-ssd/immich/thumbs''). |
| | * **3. Vorläufiger Massenspeicher (SATA-SSD):** Das Datengrab für die Originalmedien liegt testweise temporär unter ''/mnt/sata-ssd/immich/original-media''. |
| | |
| | === Lokale Docker-Infrastruktur === |
| | |
| | Im Gegensatz zur globalen ''docker-compose.yml'' (Kapitel 3.2) wird Immich aus Gründen der Übersicht und Wartbarkeit **in einem separaten Verzeichnis mit eigener Konfiguration** betrieben, klinkt sich jedoch nahtlos in das globale ''server-network'' ein. |
| | |
| | == 1. Umgebungsvariablen (/opt/docker/immich/.env) == |
| | <code env> |
| | IMMICH_VERSION=release |
| | TZ=Europe/Berlin |
| | PUID=1000 |
| | PGID=1000 |
| | |
| | # Vorläufiger Pfad auf SATA-SSD (Datengrab) |
| | UPLOAD_LOCATION=/mnt/sata-ssd/immich/original-media |
| | DB_PASSWORD=ImmichPostgresPasswort789! |
| | </code> |
| | |
| | == 2. Docker-Compose (/opt/docker/immich/docker-compose.yml) == |
| | Die Konfiguration nutzt explizit das ''cpuset''-Flag, um den Kern-Containern vollen Zugriff auf alle 4 Kerne und 8 Threads der AMD Ryzen 5 PRO 3400GE CPU zu gewähren. Die originalen Volume-Vorgaben der Entwickler (''/data'') bleiben unangetastet, während das SSD-Mapping über spezifische Unterpfade angedockt wird. |
| | |
| | <code yaml> |
| | name: immich |
| | |
| | services: |
| | immich-server: |
| | container_name: immich_server |
| | image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} |
| | cpuset: "0-7" # Zuweisung aller 8 CPU-Threads |
| | volumes: |
| | - ${UPLOAD_LOCATION}:/data # Originalzeile unangetastet |
| | - /mnt/sata-ssd/immich/thumbs:/data/thumbs # SSD-Tuning Thumbs |
| | - /mnt/sata-ssd/immich/encoded-video:/data/encoded-video # SSD-Tuning Transcoding |
| | - /etc/localtime:/etc/localtime:ro |
| | env_file: |
| | - .env |
| | ports: |
| | - 2283:2283 |
| | depends_on: |
| | - redis |
| | - database |
| | restart: unless-stopped |
| | networks: |
| | - server-network |
| | |
| | immich-machine-learning: |
| | container_name: immich_machine_learning |
| | image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} |
| | cpuset: "0-7" |
| | volumes: |
| | - /mnt/sata-ssd/immich/thumbs:/data/thumbs |
| | env_file: |
| | - .env |
| | restart: unless-stopped |
| | networks: |
| | - server-network |
| | |
| | redis: |
| | container_name: immich_redis |
| | image: docker.io/redis:6.2-alpine |
| | restart: unless-stopped |
| | networks: |
| | - server-network |
| | |
| | database: |
| | container_name: immich_postgres |
| | image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0 |
| | environment: |
| | POSTGRES_DB: immich |
| | POSTGRES_USER: postgres |
| | POSTGRES_PASSWORD: ${DB_PASSWORD} |
| | volumes: |
| | - /opt/docker/immich/db:/var/lib/postgresql/data # DB zwingend auf NVMe |
| | restart: unless-stopped |
| | networks: |
| | - server-network |
| | |
| | networks: |
| | server-network: |
| | external: true |
| | </code> |
| | |
| | === Wartung & Zukünftiger HDD-Umbau === |
| | |
| | == Initialer Bulk-Upload über Windows-PowerShell == |
| | Um große Medienmengen (z.B. >20 GB) stabil ohne Browser-Timeouts zu importieren, wird das offizielle Immich-CLI verwendet: |
| | <code> |
| | # CLI installieren und einloggen |
| | npm install -g @immich/cli |
| | immich login http://192.168.178.128:2283/api DEIN_API_KEY |
| | |
| | # Ordner rekursiv hochladen |
| | immich upload --recursive --yes "C:\Pfad\zu\deinen\Bildern" |
| | </code> |
| | |
| | == Spätere Migration auf das 4TB HDD-Datengrab == |
| | Sobald der Testbetrieb beendet ist, wird der Massenspeicher verlustfrei auf die ''HDD1'' (''/media/usbhdd1/ocdata/immich/'') ausgelagert. Das Vorgehen erfordert nur drei Schritte: |
| | |
| | 1. Immich-Stack stoppen: |
| | <code> |
| | cd /opt/docker/immich && docker compose down |
| | </code> |
| | |
| | 2. Daten per ''rsync'' auf die HDD migrieren: |
| | <code> |
| | sudo rsync -avzP /mnt/sata-ssd/immich/original-media/ /media/usbhdd1/ocdata/immich/ |
| | </code> |
| | |
| | 3. Pfad in der ''/opt/docker/immich/.env'' anpassen und Stack starten: |
| | <code> |
| | # Neue Zuweisung in der .env: |
| | UPLOAD_LOCATION=/media/usbhdd1/ocdata/immich |
| | |
| | # Start: |
| | docker compose up -d |
| | </code> |
| ==== 6.11 Ghost (CMS für die Porgys) ==== | ==== 6.11 Ghost (CMS für die Porgys) ==== |
| === Installation & Protokoll === | === Installation & Protokoll === |
| * **Profil Jana:** Zielordner: ''scan-jana'' | SSL/TLS: ''Nichts'' | * **Profil Jana:** Zielordner: ''scan-jana'' | SSL/TLS: ''Nichts'' |
| * **Profil Gemeinsam:** Zielordner: ''scan-gemeinsam'' | SSL/TLS: ''Nichts'' | * **Profil Gemeinsam:** Zielordner: ''scan-gemeinsam'' | SSL/TLS: ''Nichts'' |
| |
| --- | |
| |
| ==== 7.2 Multi-User-Workflows & Speicherpfade ==== | ==== 7.2 Multi-User-Workflows & Speicherpfade ==== |
| |
| |
| > **Hinweis zu gemeinsamen Dokumenten:** Da Paperless-ngx zwingend einen eindeutigen Besitzer pro Dokument verlangt, wird bei "Gemeinsam" ein Elternteil als Eigentümer gesetzt. Die geteilte Sichtbarkeit wird im Workflow über die Registerkarte **Aktionen -> Berechtigungen** gesteuert, indem dort der Gruppe ''Familie'' Lese- und Schreibrechte (RW) zugewiesen werden. | > **Hinweis zu gemeinsamen Dokumenten:** Da Paperless-ngx zwingend einen eindeutigen Besitzer pro Dokument verlangt, wird bei "Gemeinsam" ein Elternteil als Eigentümer gesetzt. Die geteilte Sichtbarkeit wird im Workflow über die Registerkarte **Aktionen -> Berechtigungen** gesteuert, indem dort der Gruppe ''Familie'' Lese- und Schreibrechte (RW) zugewiesen werden. |
| |
| --- | |
| |
| ==== 7.3 Administration & Fehlerbehebung (Troubleshooting) ==== | ==== 7.3 Administration & Fehlerbehebung (Troubleshooting) ==== |