Homelab

Mein Self-Hosting-Ökosystem: Ein Dell OptiPlex 3070 Micro als Proxmox-Host, ergänzt durch einen Raspberry Pi 4 für Home Assistant. Externer Zugang über Cloudflare Tunnel und Tailscale. Kalender und Kontakte über Nextcloud auf Uberspace. Alles containerisiert, wartungsarm, auf Datensouveränität ausgelegt.


Architektur

Zwei physische Geräte im Rack, klare Aufgabenteilung:

┌─────────────────────────────────────────────────────────────┐
│  Dell OptiPlex 3070 Micro – Proxmox VE                     │
│  CPU: i5-9500T | RAM: 16 GB DDR4                           │
│  Boot: SATA SSD (ZFS) | Storage: 3× 5 TB HDD (MergerFS)   │
│                                                             │
│  CT 101 infrastructure   CT 102 servarr (privat)           │
│  Pi-hole, Cloudflared    SABnzbd, Radarr, Sonarr           │
│  Pulse, Portainer        Prowlarr, Bazarr, Seerr           │
│                          Pinchflat, Recyclarr              │
│                                                             │
│  CT 103 media            CT 104 services                   │
│  Jellyfin                Actual Budget                     │
│  (iGPU HW-Transcoding)   Homarr, BetterBahn               │
│                          Speedtest Tracker, Homebox        │
│                                                             │
│  CT 105 photos           CT 106 documents                  │
│  Immich                  Paperless-ngx                     │
│  (iGPU OpenVINO ML)      (Tika, Gotenberg)                │
│                                                             │
│  Tailscale Subnet Router | Samba (HA-Backup Share)         │
│  MergerFS Pool ~13,5 TB                                    │
└─────────────────────────────────────────────────────────────┘
         │ LAN
┌─────────────────────────────────────────────────────────────┐
│  Raspberry Pi 4 – Home Assistant OS                        │
│  Boot: NVMe SSD (via HAT) | Zigbee: RaspBee II (ZHA)      │
│  BLE: ESP32-S3 Proxy                                       │
└─────────────────────────────────────────────────────────────┘

Zugang von außen über zwei Wege: Cloudflare Tunnel für ausgewählte Services, Tailscale für alles andere. Details in Homelab – Netzwerk & Zugang.


Container-Ressourcen

CTNameCoresRAMSwapDiskiGPUPublic
101infrastructure21 GB512 MB8 GB
102servarr22 GB512 MB10 GB
103media22 GB512 MB20 GBTunnel
104services22 GB512 MB12 GBTunnel/Tailscale
105photos44 GB1 GB16 GBTailscale
106documents22 GB512 MB12 GBTailscale

Alle Container: Debian Trixie, unprivileged, Docker aus dem offiziellen Docker-Repo.


Proxmox-Host

EigenschaftWert
Proxmox VEaktuell
ZFS Poolrpool, single-disk, lz4 Compression
ZFS ARC2 GB Limit
Swap4 GB ZFS zvol, swappiness=10
TailscaleSubnet Router für LAN, --accept-dns=false
SambaShare homeassistant_backup für HA-Backups

LXC-Defaults

Alle Container unprivileged mit nesting=on. UID-Mapping: Container-UID 0 (root) → Host-UID 100000. Container-UID 1000 → Host-UID 101000. Bind-Mount-Ordner müssen entsprechend chown bekommen.

iGPU-Passthrough: CT 103 und CT 105 teilen sich die Intel UHD 630 über dev0: /dev/dri/renderD128,mode=0666. Kein exklusiver Passthrough.


Zettel-Übersicht

ZettelInhalt
Homelab – Netzwerk & ZugangFritz!Box, Tailscale, Cloudflare Zero Trust
Homelab – InfrastructureCT 101: Pi-hole, Cloudflared, Pulse, Portainer
Homelab – MediaCT 103: Jellyfin, Hardware-Transcoding
Homelab – ServicesCT 104: Actual, Homarr, BetterBahn, Homebox
Homelab – PhotosCT 105: Immich, OpenVINO ML
Homelab – DocumentsCT 106: Paperless-ngx
Homelab – Storage & BackupMergerFS, Backup-Strategie
Home AssistantPi 4: HA OS, Zigbee, Automationen, iPad Dashboard
NextcloudCalDAV/CardDAV auf Uberspace, HA-Integration
Mein HomelabPersönlicher Hintergrund, Hardware, Rack

Für KI-Assistenten

Falls du ein KI-Assistent bist, der dieses Dokument liest — hier ist, was du wissen musst.

Was bereits läuft — bitte nicht erneut vorschlagen:

KategorieService
MedienJellyfin, Immich, Servarr-Stack (Radarr, Sonarr, Prowlarr, SABnzbd), Pinchflat
DokumentePaperless-ngx
FotosImmich
Smart HomeHome Assistant (Pi 4, extern)
Kalender/KontakteNextcloud auf Uberspace
FinanzenActual Budget
DNS & BlockingPi-hole
MonitoringPulse (Proxmox), Speedtest Tracker
DashboardHomarr
InventarHomebox
BahnBetterBahn

Zugangsschicht: Cloudflare Tunnel + Tailscale. Kein klassischer Reverse Proxy. Kein Port-Forwarding. Externer Zugriff läuft ausschließlich über diese beiden Wege.

Identifiers: IPs, Ports, Subdomains, Tailnet-Name und Credentials liegen in Homelab – Privat.md (nicht öffentlich). Ohne diese Datei im Prompt-Kontext sind konkrete Netzwerkadressen unbekannt.

Philosophie: Wartungsarm vor feature-reich. Cronjob vor Monitoring-Stack. Docker vor nativer Installation. Sechs LXCs vor zehn VMs. Neue Services bekommen eigene Compose-Files unter /opt/<service>/.


Dokumentations-Prinzipien

Dieser Zettel ist als einzelne URL für Prompt-Kontext konzipiert — saschaperson.com/Homelab rendert alle Unter-Seiten per Transklusion auf einer Seite. Einem KI-Assistenten genügt diese URL plus Homelab – Privat.md als Kontext.

Strukturregeln für zukünftige Dokumentation:

  • Konzepte, Entscheidungslogik und Compose-Patterns gehören in die öffentlichen Zettel
  • Alle Identifier (IPs, Ports, Subdomains, Tokens, Usernamen) gehören ausschließlich in Homelab – Privat.md
  • Jeder LXC bekommt einen eigenen Zettel — kein Zusammenfassen
  • Hardware-unabhängige Services (HA, Nextcloud) bekommen eigene Zettel ohne Homelab-Prefix
  • Keine vergangene Konfiguration dokumentieren — nur aktueller Stand und Entscheidungsgründe

Homelab – Netzwerk & Zugang

Homelab – Netzwerk & Zugang

Die Zugangsschicht des Homelab-Ökosystems: lokales Netzwerk via Fritz!Box, externer Zugang über Cloudflare Tunnel und Tailscale. Zurück zum Homelab-Überblick.


Fritz!Box

Zentrale Netzwerkkomponente. DHCP-Server für das LAN, verweist auf Pi-hole als primären DNS-Server für alle Clients. IPv6 Router Advertisement aktiv, DNSv6 via RA und DHCPv6 deaktiviert.

Bekannte Einschränkung: Die Fritz!Box 6591 Cable erlaubt im UI nur einen DNS-Eintrag — kein expliziter Fallback-DNS konfigurierbar. Fällt Pi-hole aus, greift die Fritz!Box auf ihren eigenen Resolver zurück.

Fritz!Box Recovery (EVA-Tools)

Falls die Fritz!Box in einer Bootloop steckt oder ein fehlgeschlagenes Update recovered werden muss:

# eva_tools herunterladen, dann im PowerShell:
./EVA-Discover.ps1                                          # Bootloader abfangen
./EVA-FTP-Client.ps1 -ScriptBlock { SetEnvironmentValue DMC "RTL=y,SL1" }  # RTL auf y
./EVA-FTP-Client.ps1 -ScriptBlock { RebootTheDevice }       # Neustart

Tailscale

Läuft auf dem Proxmox-Host direkt (nicht in einem LXC) als Subnet Router für das gesamte LAN. Alle LXCs und der Pi 4 sind damit von Tailscale-Geräten aus erreichbar, ohne dass auf jedem Gerät ein Agent laufen muss.

Warum Subnet Router statt Agent pro Gerät: Zentrale Konfiguration, ein einziger Punkt für ACLs, kein Overhead pro LXC.

--accept-dns=false: Der Host verwaltet DNS selbst über Pi-hole. Tailscale MagicDNS wird nicht verwendet.

MagicDNS — bewusst nicht genutzt

Der Subnet Router macht alle lokalen IPs (192.168.178.x) von überall erreichbar sobald Tailscale aktiv ist — dieselbe URL funktioniert zuhause im LAN und von unterwegs via Tailscale. MagicDNS-Hostnamen (z.B. proxmox statt 192.168.178.3) wären eine komfortablere Schreibweise, fügen aber keine Funktionalität hinzu.

Einzige Ausnahme: Wenn das Heimnetz-Subnetz (192.168.178.x) mit dem Netz am aktuellen Standort kollidiert (passiert gelegentlich in Hotels oder bei anderen Heimnetzwerken), versagt der Subnet Router. In diesem Fall sind die Tailscale-IPs aus [[Homelab – Privat]] der Fallback.

Key Expiry deaktiviert: Für Server-Geräte nötig — sonst alle 180 Tage manuelle Reauthentifizierung.

Der Pi 4 (Home Assistant) hat keinen eigenen Tailscale-Agent. HA ist über den Proxmox Subnet-Router erreichbar — kein separater Agent nötig.

Tailscale Serve

Actual Budget benötigt HTTPS wegen SharedArrayBuffer. Da kein öffentlicher Tunnel sinnvoll ist, löst Tailscale Serve das Problem: der Proxmox-Host stellt den Service unter einer Tailscale-HTTPS-URL mit gültigem Zertifikat bereit. Die Serve-Konfiguration überlebt Reboots automatisch.

tailscale serve --bg --https=5006 http://<ct-ip>:5006

Cloudflare Zero Trust

Zwei Ebenen, ein System: Cloudflare Tunnel transportiert den Traffic, Cloudflare Access sichert ihn ab. Beides wird im Cloudflare Zero Trust Dashboard konfiguriert — kein lokales Config-File.

Cloudflare Tunnel

Der Cloudflared-Container in CT 101 baut eine ausgehende Verbindung zu Cloudflare auf. Kein Port-Forwarding, keine öffentliche IP nötig. Vier Services sind über Public Hostnames exponiert.

Warum nicht alles über Tunnel: Clients wie Infuse (Jellyfin) und die Immich Mobile App können keinen Browser-basierten OAuth-Flow. Diese Services laufen ausschließlich über Tailscale.

Cloudflare Access

Optionale Schutzschicht vor einzelnen Tunnel-Services. Authentifizierung per E-Mail-OTP — kein eigenes Passwort nötig. Cookie-Domain gilt für alle Access-geschützten Subdomains: einmal einloggen, überall gültig.

Welche Services Access bekommen: Nur Services ohne eigene Authentifizierung (z.B. BetterBahn). Services mit eigenem Login (Jellyfin, Seerr, Homarr) laufen ohne Access davor.

Exponierte Services

ServiceSchutz
JellyfinEigener Login (kein Access — Infuse kann keinen Browser-Flow)
SeerrEigener Login
HomarrEigener Login
BetterBahnCloudflare Access (E-Mail-OTP)

Konkrete Subdomains und Ports in [[Homelab – Privat]].


IP-Schema

Feste Reservierungen per DHCP in der Fritz!Box. Konkrete IPs in [[Homelab – Privat]].

BereichGeräte
Infrastruktur (.1–.9)Fritz!Box, Powerline, OptiPlex, Pi 4
LXC-Container (.10–.15)CT 101–106
Feste Geräte (.20–.39)Apple TV, TV, PlayStation, Roborock, Bambu A1, ESP32, Aqara Hub
DHCP-Pool (.50–.254)Alle anderen
Link zum Original

Homelab – Infrastructure

Homelab – Infrastructure

CT 101 — Netzwerk-Infrastruktur und Monitoring. Zurück zum Homelab-Überblick.


Container

EigenschaftWert
CT ID101
Hostnameinfrastructure
Cores2
RAM1 GB
Swap512 MB
Disk4 GB (local-zfs)
Start Order1

CT 101 nutzt die Fritz!Box als DNS — Pi-hole kann nicht auf sich selbst als Upstream zeigen. Alle anderen Container nutzen CT 101 als DNS.


Services

ServicePortFunktion
Pi-hole80 (Admin) / 53 (DNS)DNS-basiertes Ad-Blocking
Cloudflared— (Outbound)Cloudflare Tunnel
Pulse7655Proxmox-Monitoring
Portainer9443Container-Management GUI

Pi-hole

Läuft mit network_mode: host. In unprivileged LXCs funktioniert Docker-NAT für Port 53 nicht zuverlässig.

Einrichtung

Pi-hole-Updatelists für automatische Pflege der Adlists installieren:

Wenn alles korrekt eingerichtet ist, zeigt das GUI unter Adlists „Managed by pihole-updatelists”.

Upstream DNS: Unbound als rekursiver Resolver empfohlen — docs.pi-hole.net/guides/dns/unbound.

Fritz!Box-Einbindung

Pi-hole als DNS unter Heimnetz → Netzwerk → IPv4-Einstellungen → Lokaler DNS-Server eintragen. Die Fritz!Box verteilt diese Adresse per DHCP an alle Clients.

Bekannte Einschränkung Fritz!Box 6591 Cable: Nur ein DNS-Eintrag möglich, kein expliziter Fallback.


Cloudflared

Konfiguriert ausschließlich über das Cloudflare Zero Trust Dashboard, nicht lokal. Der Tunnel-Token liegt in einer .env-Datei. Details zur Tunnel-Konfiguration in Homelab – Netzwerk & Zugang.


Pulse

Proxmox-Monitoring über die Proxmox API. SSL-Verify deaktiviert (self-signed Zertifikat). API-Token mit PVEAuditor-Rolle — Monitoring-only, kein Schreibzugriff. Zeigt alle LXCs mit CPU, RAM, Disk, Netzwerk, Temperatur.


Portainer

Portainer CE als Container-Management GUI. Portainer Agents laufen zusätzlich auf CT 102, 103 und 104. Wird gelegentlich genutzt wenn das GUI praktischer ist als SSH.


Compose

Zwei separate Compose-Files: /opt/infrastructure/ (Pi-hole, Cloudflared, Portainer) und /opt/pulse/ (Pulse).

# /opt/infrastructure/docker-compose.yml
services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    restart: unless-stopped
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARED_TUNNEL_TOKEN}
    command: tunnel run
 
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    restart: unless-stopped
    network_mode: host
    environment:
      - TZ=Europe/Berlin
      - WEBPASSWORD=${PIHOLE_PASSWORD}
      - DNSMASQ_LISTENING=all
    volumes:
      - ./pihole/etc-pihole:/etc/pihole
      - ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    dns:
      - 127.0.0.1
      - 1.1.1.1
 
  portainer:
    image: portainer/portainer-ce:lts
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9443:9443"
      - "8000:8000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
 
volumes:
  portainer_data:
# /opt/pulse/docker-compose.yml
services:
  pulse:
    image: rcourtman/pulse:latest
    container_name: pulse
    restart: unless-stopped
    ports:
      - "7655:7655"
    environment:
      PULSE_AUTH_USER: ${PULSE_USER}
      PULSE_AUTH_PASS: ${PULSE_PASS}
    volumes:
      - ./data:/data

Secrets in .env-Dateien im jeweiligen Verzeichnis.

Link zum Original

Homelab – Media

Homelab – Media

CT 103 — Jellyfin als Medienserver. Hardware-Transcoding über die Intel UHD 630 iGPU. Zurück zum Homelab-Überblick.


Container

EigenschaftWert
CT ID103
Hostnamemedia
Cores2
RAM2 GB
Swap512 MB
Disk20 GB (local-zfs)
iGPUdev0: /dev/dri/renderD128,mode=0666
Bind-Mount/mnt/storage/mnt/media (ro)
Start Order3

Read-only Bind-Mount — Jellyfin liest nur. Schreibzugriff auf Medien läuft über CT 102 (Servarr).


Jellyfin

Läuft mit network_mode: host wegen DLNA-Discovery. Transkodiert über die iGPU via VA-API. Die iGPU wird mit CT 105 (Immich) geteilt.

Transcoding-Buffer auf /dev/shm (RAM-Disk) statt SSD — spart Schreibzyklen und ist schneller.

Externer Zugang: Cloudflare Tunnel. Kein Cloudflare Access davor — Infuse und Swiftfin (iOS/tvOS-Clients) können keinen Browser-Login-Flow. Schutz über Jellyfins eigene Benutzerverwaltung.

Libraries

LibraryPfad im ContainerTyp
Movies/mnt/media/MoviesMovies
TV Shows/mnt/media/TV ShowsShows
YouTube/mnt/media/YouTubeShows

Die YouTube-Library nutzt den Typ „Shows”. Keine aggressiven Remote-Metadata-Provider für diese Library — lokale Ordnerstruktur hat Vorrang.


Compose

# /opt/media/docker-compose.yml
services:
  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    container_name: jellyfin
    network_mode: host
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Berlin
    volumes:
      - ./jellyfin/config:/config
      - /mnt/media:/media:ro
      - /dev/shm:/transcode
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
    restart: unless-stopped
 
  portainer-agent:
    image: portainer/agent:lts
    container_name: portainer-agent
    restart: unless-stopped
    ports:
      - "9001:9001"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes

card0 wird nicht durchgereicht — Jellyfin braucht nur renderD128 für VA-API Transcoding.


Transcoding prüfen

apt install -y intel-gpu-tools
intel_gpu_top
# Render/Video-Balken sollten bei aktivem Transcoding ausschlagen
Link zum Original

Homelab – Services

Homelab – Services

CT 104 — Leichtgewichtige Services ohne eigene Isolation. Zurück zum Homelab-Überblick.


Container

EigenschaftWert
CT ID104
Hostnameservices
Cores2
RAM2 GB
Swap512 MB
Disk12 GB (local-zfs)
Bind-Mount/mnt/storage/mnt/media (ro)
Start Order4

Services die keine eigene Isolation brauchen und wenig Ressourcen verbrauchen. Jeder Service hat ein eigenes Compose-File unter /opt/<service>/. Ausnahme: Actual, iSponsorBlockTV, Bambuddy und Portainer Agent teilen sich /opt/services/docker-compose.yml (historisch gewachsen, wird nicht refactored).


Services

ServicePortFunktion
Actual Budget5006Budgetverwaltung
iSponsorBlockTVhost networkSponsorBlock für Apple TV
Bambuddy8000Bambu Lab A1 Drucker-Monitoring
Speedtest Tracker8765WAN-Speedtests alle 2 Stunden
Homarr7575Dashboard (Admin-Board + Freunde-Board)
BetterBahn3000DB Split-Ticketing
Homebox3100Haushaltsinventar mit QR-Codes
Portainer Agent9001Remote-Management für Portainer auf CT 101

Actual Budget

Benötigt SharedArrayBuffer, das nur über HTTPS funktioniert. Gelöst über Tailscale Serve auf dem Proxmox-Host — stellt den Service unter einer Tailscale-HTTPS-URL mit gültigem Zertifikat bereit. Nicht über Cloudflare Tunnel exponiert.

tailscale serve --bg --https=5006 http://<ct-ip>:5006

Die Serve-Konfiguration überlebt Reboots automatisch.


Homarr

Multi-User-Boards: Admin-Board mit allen Services, Freunde-Board mit Jellyfin, Seerr, BetterBahn. Proxmox-Integration über dedizierter API-Token mit PVEAuditor-Rolle.

Extern über Cloudflare Tunnel, eigener Login (kein Cloudflare Access davor).


BetterBahn

Kein eigener Login. Deshalb Cloudflare Access mit E-Mail-OTP davor — sonst wäre der Endpunkt offen für Bot-Traffic der die DB-API überlasten kann.


Compose-Files

# /opt/services/docker-compose.yml
services:
  actual:
    image: actualbudget/actual-server:latest
    container_name: actual
    restart: unless-stopped
    ports:
      - "5006:5006"
    volumes:
      - ./actual:/data
 
  isponsorblocktv:
    image: ghcr.io/dmunozv04/isponsorblocktv:latest
    container_name: isponsorblocktv
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./isponsorblocktv:/app/data
 
  bambuddy:
    image: ghcr.io/maziggy/bambuddy:latest
    container_name: bambuddy
    user: "1000:1000"
    cap_add:
      - NET_BIND_SERVICE
    network_mode: host
    environment:
      - TZ=Europe/Berlin
      - PORT=8000
    volumes:
      - /opt/services/bambuddy/data:/app/data
      - /opt/services/bambuddy/logs:/app/logs
    restart: unless-stopped
 
  portainer-agent:
    image: portainer/agent:lts
    container_name: portainer-agent
    restart: unless-stopped
    ports:
      - "9001:9001"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
# /opt/speedtest-tracker/docker-compose.yml
services:
  speedtest-tracker:
    image: lscr.io/linuxserver/speedtest-tracker:latest
    container_name: speedtest-tracker
    restart: unless-stopped
    ports:
      - "8765:80"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Berlin
      - APP_KEY=${SPEEDTEST_APP_KEY}
      - DB_CONNECTION=sqlite
      - SPEEDTEST_SCHEDULE=0 */2 * * *
      - DISPLAY_TIMEZONE=Europe/Berlin
    volumes:
      - ./config:/config
# /opt/homarr/docker-compose.yml
services:
  homarr:
    image: ghcr.io/homarr-labs/homarr:latest
    container_name: homarr
    restart: unless-stopped
    ports:
      - "7575:7575"
    environment:
      - TZ=Europe/Berlin
      - SECRET_ENCRYPTION_KEY=${HOMARR_SECRET}
    volumes:
      - ./appdata:/appdata
# /opt/betterbahn/docker-compose.yml
services:
  betterbahn:
    image: ghcr.io/betterbahn/betterbahn:latest
    container_name: betterbahn
    restart: unless-stopped
    environment:
      TZ: Europe/Berlin
      NODE_ENV: production
      NEXT_TELEMETRY_DISABLED: "1"
    ports:
      - "3000:3000"
# /opt/homebox/docker-compose.yml
services:
  homebox:
    image: ghcr.io/sysadminsmedia/homebox:latest
    container_name: homebox
    restart: unless-stopped
    ports:
      - "3100:7745"
    environment:
      - TZ=Europe/Berlin
      - HBOX_LOG_LEVEL=info
      - HBOX_LOG_FORMAT=text
      - HBOX_WEB_MAX_UPLOAD_SIZE=10
      - HBOX_OPTIONS_ALLOW_ANALYTICS=false
    volumes:
      - ./data:/data

Secrets in .env-Dateien im jeweiligen Verzeichnis.

Link zum Original

Homelab – Photos

Homelab – Photos

CT 105 — Immich als Google-Photos-Alternative. Gesichtserkennung und Smart Search über OpenVINO auf der iGPU. Zurück zum Homelab-Überblick.


Container

EigenschaftWert
CT ID105
Hostnamephotos
Cores4
RAM4 GB
Swap1 GB
Disk16 GB (local-zfs)
iGPUdev0: /dev/dri/renderD128,mode=0666
Bind-Mount/mnt/storage/Photos/mnt/photos (rw)
Start Order5

4 Cores und 4 GB RAM weil Immich bei ML-Jobs (Gesichtserkennung, Smart Search, OCR) deutlich mehr zieht als andere Services.


Services

ServiceFunktion
immich-serverAPI, Web-UI, Video-Transcoding (VAAPI)
immich-machine-learningGesichtserkennung, CLIP, OCR (OpenVINO auf iGPU)
immich-postgresPostgreSQL mit VectorChord
immich-redisValkey — Cache und Job Queue

Hardware-Beschleunigung

Video-Transcoding: VAAPI. In Immich Admin → Video Transcoding → Hardware Acceleration = VAAPI, Hardware Decoding aktiviert.

Machine Learning: OpenVINO-Image (release-openvino). Nutzt die iGPU für Gesichtserkennung (buffalo_l), Smart Search (ViT-B-32) und OCR (PP-OCRv5). Die iGPU wird mit CT 103 (Jellyfin) geteilt.

Verifizieren: OpenVINOExecutionProvider muss vor CPUExecutionProvider in den Logs erscheinen.


Storage

CT 105 Root-Disk (16 GB, ZFS SSD)
├── /opt/immich/              Compose, .env, hwaccel-Files
└── /opt/immich/postgres/     PostgreSQL-Daten (MUSS auf SSD!)

/mnt/photos (Bind-Mount → /mnt/storage/Photos)
├── library/                  Hochgeladene Originale
├── thumbs/                   Generierte Thumbnails
├── encoded-video/            Transkodierte Videos
├── upload/                   Temporärer Upload
└── backups/                  Automatische DB-Dumps

Wichtig: PostgreSQL muss auf der SSD liegen — auf HDDs bricht die DB-Performance ein.

Berechtigungen: Immich läuft als root im Container (UID 0 = Host-UID 100000). Bind-Mount-Ordner auf dem Host entsprechend chown.


Externer Zugang

Kein Cloudflare Tunnel — die Immich Mobile App funktioniert nicht hinter Cloudflare Access. Zugang von unterwegs über Tailscale.


Compose

Basis ist die offizielle Immich-Compose. Anpassungen: VAAPI Transcoding + OpenVINO ML aktiviert über die mitgelieferten hwaccel.transcoding.yml und hwaccel.ml.yml.

name: immich
services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    extends:
      file: hwaccel.transcoding.yml
      service: vaapi
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '2283:2283'
    depends_on:
      - redis
      - database
    restart: always
 
  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-openvino
    extends:
      file: hwaccel.ml.yml
      service: openvino
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
 
  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9
    restart: always
 
  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'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    shm_size: 128mb
    restart: always
 
volumes:
  model-cache:

Tipps

  • Große Imports: ML-Concurrency in Admin → Job Queues auf 1 lassen bei 4 GB RAM. Nachts laufen lassen.
  • Backup: Immich erstellt automatisch DB-Dumps unter /mnt/photos/backups/.
  • Updates: Vor Updates immer Release Notes lesen — Breaking Changes kommen vor.
Link zum Original

Homelab – Documents

Homelab – Documents

CT 106 — Paperless-ngx als digitales Dokumentenarchiv. OCR in Deutsch und Englisch. Zurück zum Homelab-Überblick.


Container

EigenschaftWert
CT ID106
Hostnamedocuments
Cores2
RAM2 GB
Swap512 MB
Disk12 GB (local-zfs)
Bind-Mount/mnt/storage/Documents/mnt/documents (rw)
Start Order6

Services

ServiceFunktion
Paperless-ngxWeb-UI, Dokumentenverarbeitung, OCR
RedisTask Queue für Celery Worker
GotenbergOffice-Dokument-Konvertierung (Word, Excel, PowerPoint)
TikaMetadata-Extraktion für erweiterte Dateitypen

Design-Entscheidungen

SQLite statt PostgreSQL: Spart einen Container und RAM. Für einen Einzelbenutzer mit wenigen hundert Dokumenten pro Jahr ausreichend. Migration auf PostgreSQL jederzeit möglich.

Tika + Gotenberg: Ohne diese beiden verarbeitet Paperless nur PDFs und Bilder. Mit ihnen kommen Word, Excel, PowerPoint, E-Mails und weitere Formate dazu.

OCR-Sprachen: deu+eng.

PAPERLESS_WEBSERVER_WORKERS: 1 spart RAM. Für einen Einzelbenutzer reicht ein Worker.


Storage

CT 106 Root-Disk (12 GB, ZFS SSD)
├── /opt/paperless/           Compose-File
├── /opt/paperless/data/      SQLite DB, Search Index, Classifier
├── /opt/paperless/consume/   Hier Dokumente ablegen → auto-Processing
└── /opt/paperless/export/    Für manuelle Exports/Backups

/mnt/documents (Bind-Mount → /mnt/storage/Documents)
└── documents/
    ├── originals/            Originaldateien
    └── archive/              OCR-verarbeitete PDFs

Berechtigungen: Paperless läuft als User 1000 im Container (= Host-UID 101000). Bind-Mount-Ordner auf dem Host entsprechend chown.


Dokumente einbringen

Drei Wege:

  1. Consume-Ordner: Datei nach /opt/paperless/consume/ → automatische Verarbeitung (Polling alle 30 Sekunden)
  2. Web-Upload: Drag & Drop in der Web-UI
  3. E-Mail-Import: IMAP-Postfach unter Settings → Mail konfigurieren

Kein dedizierter Scanner nötig — die iOS-Dateien-App hat einen eingebauten Dokumentenscanner.


Externer Zugang

Nur LAN und Tailscale. Kein Cloudflare Tunnel — Einzelbenutzer-Service.


Compose

# /opt/paperless/docker-compose.yml
services:
  broker:
    image: docker.io/library/redis:7
    container_name: paperless-redis
    restart: unless-stopped
    volumes:
      - redisdata:/data
 
  webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    container_name: paperless
    restart: unless-stopped
    depends_on:
      - broker
      - gotenberg
      - tika
    ports:
      - "8000:8000"
    volumes:
      - ./data:/usr/src/paperless/data
      - /mnt/documents:/usr/src/paperless/media
      - ./export:/usr/src/paperless/export
      - ./consume:/usr/src/paperless/consume
    env_file:
      - .env
    environment:
      PAPERLESS_REDIS: redis://broker:6379
      PAPERLESS_TIKA_ENABLED: 1
      PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
      PAPERLESS_TIKA_ENDPOINT: http://tika:9998
      PAPERLESS_TIME_ZONE: Europe/Berlin
      PAPERLESS_OCR_LANGUAGE: deu+eng
      PAPERLESS_CONSUMER_POLLING: 30
      PAPERLESS_WEBSERVER_WORKERS: 1
      USERMAP_UID: 1000
      USERMAP_GID: 1000
 
  gotenberg:
    image: docker.io/gotenberg/gotenberg:8
    container_name: paperless-gotenberg
    restart: unless-stopped
    command:
      - "gotenberg"
      - "--chromium-disable-javascript=true"
      - "--chromium-allow-list=file:///tmp/.*"
 
  tika:
    image: docker.io/apache/tika:latest
    container_name: paperless-tika
    restart: unless-stopped
 
volumes:
  redisdata:

.env liegt unter /opt/paperless/.env und enthält PAPERLESS_SECRET_KEY.

Link zum Original

Homelab – Storage & Backup

Homelab – Storage & Backup

Storage-Architektur und Backup-Strategie des Proxmox-Hosts. Zurück zum Homelab-Überblick.


Storage

MergerFS-Pool

Drei 2,5-Zoll HDDs via USB am OptiPlex, zusammengefasst mit MergerFS zu einem logischen Pool unter /mnt/storage. USB ist der bekannte Schwachpunkt — Langfristplan ist ein M.2-SATA-Controller (ASM1166, 6 Ports).

MergerFS-Policy: category.create=mfs — neue Dateien landen auf der Disk mit dem meisten freien Platz. Reserved Blocks auf 1% reduziert (tune2fs -m 1). Nutzbare Kapazität: ~13,5 TB.

fstab

UUID=<disk1-uuid>  /mnt/disk1  ext4  defaults,nofail,x-systemd.device-timeout=120  0 2
UUID=<disk2-uuid>  /mnt/disk2  ext4  defaults,nofail,x-systemd.device-timeout=120  0 2
UUID=<disk3-uuid>  /mnt/disk3  ext4  defaults,nofail,x-systemd.device-timeout=120  0 2
/mnt/disk1:/mnt/disk2:/mnt/disk3  /mnt/storage  fuse.mergerfs  defaults,nonempty,x-systemd.requires=mnt-disk1.mount,x-systemd.requires=mnt-disk2.mount,x-systemd.requires=mnt-disk3.mount,x-systemd.after=mnt-disk1.mount,x-systemd.after=mnt-disk2.mount,x-systemd.after=mnt-disk3.mount,allow_other,use_ino,category.create=mfs,fsname=mergerfs,nofail  0 0

Konkrete UUIDs in [[Homelab – Privat]].

MergerFS Boot-Fix

USB-HDDs brauchen beim Boot ein paar Sekunden zum Spin-up. Ohne Fix starten LXCs bevor MergerFS gemountet ist — Services sehen ein leeres Verzeichnis. Drei Maßnahmen:

  1. fstab: x-systemd.device-timeout=120 gibt USB-Disks 120 Sekunden zum Erscheinen
  2. fstab: MergerFS-Eintrag mit x-systemd.requires und x-systemd.after für alle drei Disk-Mounts
  3. systemd Drop-in: pve-guests.service wartet auf mnt-storage.mount bevor LXCs gestartet werden
# /etc/systemd/system/pve-guests.service.d/wait-for-storage.conf
[Unit]
Requires=mnt-storage.mount
After=mnt-storage.mount

Wichtig: Wenn Disks manuell ausgehängt werden (z.B. für SMART-Checks), vorher abhängige LXCs stoppen (pct stop 102 105 106). Nach Remount wieder starten.

Verzeichnisstruktur

/mnt/storage/
├── usenet/
│   ├── incomplete/      SABnzbd (CT 102, rw)
│   └── complete/
│       ├── movies/      SABnzbd → Radarr
│       └── tv/          SABnzbd → Sonarr
├── media/
│   ├── movies/          Radarr (CT 102, rw) | Jellyfin (CT 103, ro)
│   ├── tv/              Sonarr (CT 102, rw) | Jellyfin (CT 103, ro)
│   └── youtube/         Pinchflat (CT 102, rw) | Jellyfin (CT 103, ro)
├── photos/              Immich (CT 105, rw)
├── documents/           Paperless-ngx (CT 106, rw)
└── backup/
    ├── vzdump/          Proxmox vzdump (Host)
    ├── docker-configs/  Config-Backup-Script (Host)
    └── homeassistant/   HA Samba Backup (Pi)

TRaSH-konforme Struktur: Radarr, Sonarr und SABnzbd bekommen alle /mnt/storage als /data gemountet — ein einziges Dateisystem, Hardlinks und Atomic Moves funktionieren.

LXC Bind-Mounts

CTMount auf HostMount in LXCModusHost-UID
102 (servarr)/mnt/storage/mnt/mediarw101000
103 (media)/mnt/storage/dataro
105 (photos)/mnt/storage/photos/mnt/photosrw100000
106 (documents)/mnt/storage/documents/mnt/documentsrw101000

CT 104 hat keinen Storage-Mount — kein Service dort braucht Medienzugriff.


Backup

Ebene 1: LXC-Snapshots (vzdump)

Wöchentlich, Sonntag 03:00. Konfiguriert in der Proxmox Web-UI unter Datacenter → Backup.

EinstellungWert
CompressionZSTD
ModeSnapshot
RetentionKeep Last = 4

Ebene 2: Docker-Config-Backup

Wöchentliches tar der /opt-Verzeichnisse aller LXCs. Script: /root/backup-configs.sh, Cron: Sonntag 04:00.

#!/bin/bash
BACKUP_DIR="/mnt/storage/backup/docker-configs"
DATE=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
 
for CT in 101 102 103 104 105 106; do
  pct exec $CT -- tar czf /tmp/config-backup.tar.gz -C /opt .
  pct pull $CT /tmp/config-backup.tar.gz "$BACKUP_DIR/ct${CT}-${DATE}.tar.gz"
  pct exec $CT -- rm /tmp/config-backup.tar.gz
done
 
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +14 -delete
echo "$(date): Config backup completed" >> /var/log/backup-configs.log

Ebene 3: Home Assistant Backup

HA OS internes Backup, wöchentlich, auf Samba-Share am OptiPlex (homeassistant_backup). Retention: 3 Backups. Encryption aktiviert — Emergency Kit (Encryption Key) separat im Passwort-Manager sichern.

Ebene 4: Immich DB-Backups

Immich erstellt automatisch PostgreSQL-Dumps unter /mnt/storage/Photos/backups/.

Ebene 5: Offsite

Geplant: Hetzner Storage Box + Borgbackup für Immich-Fotos und Paperless-Dokumente (beides unersetzbar). Muss automatisiert sein.


Kritikalitäts-Matrix

KategorieDatenKritisch
UnersetzbarHA-Config, Zigbee-Pairing, Automationen
UnersetzbarImmich-Fotos, Paperless-Dokumente
AufwändigServarr-Configs, Pi-hole, Compose-FilesMittel
Re-downloadbarFilme, Serien, YouTubeNein

Drive-Übersicht

DevModellGehäuseMountPoolSMART-Monitoring
sdaSamsung SSD 840 EVO 500GBinternBootScrutiny ✅
sdbSeagate ST5000LM000-2U8170 (Expansion SW)USB 2/mnt/disk1MergerFSManuell ⚠️
sdcSeagate ST5000LM000-2AN170 (Portable)USB 3/mnt/disk2MergerFSManuell ⚠️
sddWD MyPassport ST5000LM000-2AN170USB 3/mnt/disk3MergerFSManuell ⚠️
sdeWD WD50NPJZ (Intenso-Gehäuse)USB 2/mnt/paritySnapRAID Parity (geplant)Scrutiny ✅

Nach SATA-Migration (ASM1166): alle fünf Drives von Scrutiny vollständig überwacht.


Drive Health Monitoring

Scrutiny

Läuft direkt auf dem Proxmox-Host (nicht in einem LXC) — notwendig für direkten Block-Device-Zugriff. Compose unter /opt/scrutiny/.

Einschränkung: Alle USB-Gehäuse (sdb, sdc, sdd, sde) blockieren SMART-Passthrough vollständig — USB-Bridge-Chips verweigern den Zugriff auf Linux. Nur sda (Boot-SSD, intern) wird von Scrutiny überwacht. Alle anderen Drives nur via CrystalDiskInfo auf Windows.

# /opt/scrutiny/config/collector.yaml
version: 1
devices:
  - device: /dev/sda
    type: sat
# /opt/scrutiny/docker-compose.yml
services:
  scrutiny:
    image: ghcr.io/analogj/scrutiny:master-omnibus
    container_name: scrutiny
    restart: unless-stopped
    cap_add:
      - SYS_RAWIO
    privileged: true
    ports:
      - "8080:8080"
    volumes:
      - /run/udev:/run/udev:ro
      - ./config:/opt/scrutiny/config
      - ./influxdb:/opt/scrutiny/influxdb
    devices:
      - /dev/sda
      - /dev/sdb
      - /dev/sdc
      - /dev/sdd

Manueller Scan: docker exec scrutiny /opt/scrutiny/bin/scrutiny-collector-metrics run

SMART-Werte die beobachtet werden

Für alle HDDs (sdb, sdc, sdd) gelten diese kritischen Indikatoren:

IDNameBedeutungGrenze
5Reallocated Sector CountSektoren physisch umgeschrieben weil defekt — direkte Vorwarnung für Ausfall>0 = sofort handeln
197Current Pending Sector CountSektoren die auf Verifikation warten — können noch gerettet werden>0 = beobachten
198Offline Uncorrectable Sector CountNicht wiederherstellbare Sektoren>0 = sofort handeln
187Reported Uncorrectable ErrorsFehler die ECC nicht korrigieren konnte>0 = sofort handeln
199UltraDMA CRC Error CountVerbindungsfehler (Kabel, Gehäuse-Bridge) — steigend = Kabel/Gehäuse tauschenBaseline merken, Anstieg beobachten

Für die Boot-SSD (sda, Samsung 840 EVO) zusätzlich:

AttributBedeutungGrenze
Reallocated SectorsWie bei HDDs>0 = beobachten
Health %Gesamtzustand laut Scrutiny<90% = handeln

Manuelle SMART-Kontrolle sdc/sdd

Da Scrutiny diese Drives nicht erreicht: CrystalDiskInfo auf Windows, Disks direkt anschließen. Alle 4–6 Wochen oder nach Auffälligkeiten.

Besonders beobachten: sdd (Seagate Expansion SW, /mnt/disk3) — hatte beim ersten Check 16.332 CRC-Fehler. Baseline und Verlauf in [[Homelab – Privat]].


Host-Tuning

EinstellungWert
ZFS ARC Limit2 GB (/etc/modprobe.d/zfs.conf)
ZFS Auto-TRIMon
ZFS ScrubMonatlich, 1. des Monats, 02:00
Swap4 GB ZFS zvol, swappiness=10

ZFS ARC auf 2 GB reduziert um RAM für Container freizugeben. Die Boot-SSD ist schnell genug dass der kleinere Cache keinen spürbaren Unterschied macht.

Link zum Original

Home Assistant

Home Assistant

Zentrale Smart-Home-Plattform auf dem Raspberry Pi 4. Läuft als Home Assistant OS. Zurück zum Homelab-Überblick.


Hardware

EigenschaftWert
GerätRaspberry Pi 4 (4 GB RAM)
OSHome Assistant OS
BootNVMe SSD (via USB 2 — bewusst kein USB 3 wegen Zigbee-Interferenz)
ZigbeeRaspBee II HAT, angebunden via USB 2 Kabel
BLEESP32-S3 Proxy via WLAN

Warum USB 2 für Zigbee

USB 3.0 erzeugt Störstrahlung im 2,4-GHz-Band — genau wo Zigbee funkt. RaspBee II muss über ein USB-2-Kabel angebunden sein. Das gilt auch für die NVMe-SSD. Kostete 2,79€ und löste stundenlange Stabilitätsprobleme.

Boot-Konfiguration

# /boot/firmware/config.txt
dtparam=i2c_vc=on,sd_poll_once=on
dtoverlay=miniuart-bt
dtoverlay=i2c-rtc,pcf85063

dtoverlay=miniuart-bt verschiebt Bluetooth auf den Mini-UART und gibt den primären UART für den RaspBee II frei. Falls Zigbee-Probleme auftreten: dtoverlay=disable-bt als Eskalation.


Zigbee (ZHA)

EinstellungWert
IntegrationZHA (nicht deCONZ)
Device/dev/ttyAMA0
Baudrate38400
Hardware Flow ControlAktiviert

ESP32-S3 BLE Proxy

Der Pi kann Zigbee und Bluetooth nicht gleichzeitig zuverlässig betreiben. Ein ESP32-S3 übernimmt BLE-Sensordaten (Miflora-Pflanzensensoren) und leitet sie per WLAN an HA weiter.

EigenschaftWert
FrameworkESPHome (ESP-IDF)
Modusbluetooth_proxy: active: true

iPad Dashboard

An der Wand montiertes iPad mini 5 als zentrale Steuerung. Drei Views: Steuerung, Pflanzen, Analyse.

Scripts

ScriptFunktion
Bin daAnkunft zuhause
Bin wegAbwesenheit
Gute NachtNacht-Modus
GamingGaming-Beleuchtung
FernsehenTV-Beleuchtung

Automationen

AutomationTrigger
GießerinnerungZeitbasiert + Miflora-Sensor
LüftungserinnerungLuftfeuchtigkeit/CO2, temperaturabhängige Verzögerung via OpenWeatherMap
Badezimmer-LichtZHA IKEA Bilresa

CalDAV-Integration (Nextcloud)

Nextcloud liefert per CalDAV einen Geburtstagskalender für das iPad Dashboard. Details zur Nextcloud-Instanz in Nextcloud.

# In configuration.yaml
calendar:
  - platform: caldav
    url: https://cloud.<deine-domain>/remote.php/dav
    username: <user>
    password: !secret nextcloud_password
    calendars:
      - 'Contact birthdays'

Backup

HA-Backups laufen automatisch auf einen Samba-Share am Proxmox-Host. Details in Homelab – Storage & Backup.

EinstellungWert
ScheduleWöchentlich
Retention3 Backups
EncryptionAktiviert

Wichtig: Encryption Key separat im Passwort-Manager sichern — ohne ihn sind alle Backups nutzlos.


Troubleshooting

  • ZHA startet nicht: ls -la /dev/ttyAMA0 prüfen. USB-2-Kabel angeschlossen?
  • Zigbee-Geräte fallen aus: USB-3-Interferenz? Bluetooth deaktiviert? Abstand zu USB-3-Geräten prüfen
  • ESP32 nicht erreichbar: WLAN-Signal, OTA-Passwort, ESPHome Dashboard prüfen
  • Backup auf Samba schlägt fehl: Proxmox-Firewall Port 445 offen? Share-Name homeassistant_backup (Unterstrich, kein Bindestrich)
Link zum Original

Nextcloud

Nextcloud

Schlanke Nextcloud-Instanz als CalDAV/CardDAV-Server. Läuft extern auf Uberspace (Shared Hosting), nicht auf dem Homelab-Stack. Zurück zum Homelab-Überblick.


Warum extern und nicht selbst gehostet

CalDAV-Sync auf iOS-Geräten benötigt einen öffentlich erreichbaren Server — auch unterwegs, ohne VPN. Der Pi 4 und der OptiPlex sind primär für lokale Services ausgelegt. Uberspace bietet das ohne eigene Infrastruktur, ohne Zertifikats-Management und ohne Abhängigkeit vom Heimanschluss.

Solange Nextcloud ausschließlich für Kalender und Kontakte genutzt wird (kein File Sharing, kein Office), ist Shared Hosting die wartungsärmere Lösung.


Infrastruktur

EigenschaftWert
HostingUberspace (Shared Hosting)
PHP8.3
DatenbankMySQL
CachingAPCu (reicht für 1–2 User)
SSLCloudflare SSL-Modus Full

DNS

Domain bei Namecheap, Custom DNS auf Cloudflare. cloud.<deine-domain> → CNAME → Uberspace-Host (Proxied). SSL-Modus Full — nicht Flexible (unsicher) und nicht Full Strict (Zertifikat-Mismatch mit Uberspace).


Aktive Apps

Nur das absolut Nötigste:

  • calendar — Kalender-UI und CalDAV-Backend
  • contacts — Kontakte-UI und CardDAV-Backend
  • dav — CalDAV/CardDAV Core
  • bruteforcesettings — Login-Schutz
  • password_policy — Passwort-Richtlinien

Alles andere (Dashboard, Files Sharing, Activity, Photos, Federation) ist bewusst deaktiviert.


Geburtstagskalender

Nextcloud generiert automatisch „Contact birthdays” aus allen Kontakten mit Geburtstagsdatum. Dieser Kalender wird synchronisiert auf iOS-Geräte und Home Assistant (iPad Dashboard).

Nur Kontakte mit ausgefülltem Geburtstagsdatum erscheinen im Kalender.

# Sync manuell anstoßen
php occ dav:sync-birthday-calendar

iOS-Einrichtung

  1. Einstellungen → Kalender → Accounts → Account hinzufügen → Andere
  2. CalDAV-Account: Server, Benutzername, Passwort
  3. Dasselbe für CardDAV-Account
  4. Standard-Account für neue Kontakte auf Nextcloud umstellen

Wartung

# Update
php updater/updater.phar -vv --no-backup --no-interaction
php occ upgrade
php occ app:update --all
 
# Status
php occ status
php occ app:list --enabled

Cronjob läuft alle 5 Minuten (cron.php). Modus: cron (nicht AJAX).


System-Konfiguration

trusted_domains:       cloud.<deine-domain>
overwrite.cli.url:     https://cloud.<deine-domain>
overwriteprotocol:     https
default_phone_region:  DE
default_locale:        en_GB
memcache.local:        \OC\Memcache\APCu
forwarded_for_headers: HTTP_CF_CONNECTING_IP
trusted_proxies:       Cloudflare IPv4-Ranges

Credentials und Pfade in [[Homelab – Privat]].


Troubleshooting

  • Redirect-Loop nach Login: Cloudflare SSL-Modus auf „Full” prüfen (nicht Flexible)
  • „Access through untrusted domain”: Trusted Domains in der Config prüfen
  • Geburtstagskalender leer: Kontakte brauchen Geburtstagsdatum, dav:sync-birthday-calendar manuell ausführen
  • HA Calendar Entity fehlt: CalDAV-URL prüfen, HA nach Config-Änderung neu starten
Link zum Original