Zum Inhalt

Docker Compose Dauerbetrieb

Du hast Kamerplanter im Schnellstart ausprobiert und möchtest es jetzt dauerhaft betreiben? Diese Anleitung zeigt dir, wie du Kamerplanter auf einem eigenen Server einrichtest — zum Beispiel auf einem Raspberry Pi, einem NAS oder einem Heimserver.


Unterschied zum Schnellstart

Im Schnellstart hast du Kamerplanter aus dem Quellcode gebaut (docker compose up). Für den Dauerbetrieb nutzt du stattdessen fertig gebaute Images — das ist schneller, braucht weniger Speicher und du musst den Quellcode nicht auf dem Server haben.

Schnellstart Dauerbetrieb
Docker Compose Datei docker-compose.yml docker-compose.release.yml
Images Werden lokal gebaut Fertig aus der Registry
Quellcode nötig? Ja Nein
Neustart bei Absturz Manuell Automatisch
Geeignet für Ausprobieren, Entwicklung Dauerbetrieb

Voraussetzungen

  • Ein Server mit Docker und Docker Compose (siehe Installation)
  • Mindestens 2 GB RAM (4 GB empfohlen)
  • Stabile Netzwerkverbindung für den Download der Images

1. Projektdateien herunterladen

Du brauchst nur zwei Dateien vom Repository — nicht den gesamten Quellcode:

# Verzeichnis erstellen
mkdir -p ~/kamerplanter && cd ~/kamerplanter

# Die beiden benötigten Dateien herunterladen
curl -O https://raw.githubusercontent.com/nolte/kamerplanter/main/docker-compose.release.yml
curl -O https://raw.githubusercontent.com/nolte/kamerplanter/main/.env.example

2. Konfiguration erstellen

cp .env.example .env

Öffne die .env-Datei und setze sichere Passwörter:

.env
# Sichere Passwörter generieren: openssl rand -base64 24
ARANGO_ROOT_PASSWORD=hier-sicheres-passwort-einsetzen
ARANGODB_PASSWORD=hier-sicheres-passwort-einsetzen

# Standardwerte — nur bei Bedarf ändern
ARANGODB_DATABASE=kamerplanter
ARANGODB_USERNAME=root
REDIS_URL=redis://valkey:6379/0
DEBUG=false
# Fehlt die Zeile, gilt true; ohne ausgehenden Mailversand ausdrücklich false
REQUIRE_EMAIL_VERIFICATION=false
CORS_ORIGINS=["http://localhost:8080"]

Passwörter

Verwende nicht die Beispielpasswörter aus .env.example. Generiere sichere Passwörter, z.B. mit openssl rand -base64 24. Beide Passwort-Felder (ARANGO_ROOT_PASSWORD und ARANGODB_PASSWORD) müssen identisch sein.

Vier zusätzliche Pflicht-Secrets (sonst startet das Backend nicht)

Ohne diese vier Werte bricht der Backend-Start ab

.env.example setzt DEBUG=false — der für einen Dauerbetrieb richtige Wert. Bei DEBUG=false prüft das Backend beim Start zusätzlich JWT_SECRET_KEY, FERNET_KEY, ERASURE_TOMBSTONE_SALT und LOG_PSEUDONYM_SALT und bricht mit einer Fehlermeldung ab, wenn einer davon fehlt (Fail-Fast-Gate). docker-compose.release.yml reicht diese vier Variablen nicht automatisch an den Backend-Container durch — du musst sie selbst ergänzen. Auch der celery-worker-Container prüft FERNET_KEY und LOG_PSEUDONYM_SALT inzwischen beim Start und bricht ebenso ab, wenn ein Wert fehlt oder ungültig ist — der celery-worker-Eintrag in der docker-compose.override.yml unten ist deshalb Pflicht, nicht optional. celery-beat prüft LOG_PSEUDONYM_SALT nicht.

Erzeuge die vier Werte und trage sie in deine .env ein:

# JWT_SECRET_KEY, ERASURE_TOMBSTONE_SALT und LOG_PSEUDONYM_SALT (je mind. 32 Zeichen)
openssl rand -hex 32

# FERNET_KEY (muss ein gültiger Fernet-Schlüssel sein)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
.env
JWT_SECRET_KEY=<Ausgabe von openssl rand -hex 32>
FERNET_KEY=<Ausgabe des Fernet-Kommandos>
ERASURE_TOMBSTONE_SALT=<zweite Ausgabe von openssl rand -hex 32>
LOG_PSEUDONYM_SALT=<dritte Ausgabe von openssl rand -hex 32>

Lege zusätzlich eine docker-compose.override.yml neben docker-compose.release.yml an — Docker Compose lädt sie automatisch mit:

docker-compose.override.yml
services:
  backend:
    environment:
      JWT_SECRET_KEY: ${JWT_SECRET_KEY}
      FERNET_KEY: ${FERNET_KEY}
      ERASURE_TOMBSTONE_SALT: ${ERASURE_TOMBSTONE_SALT}
      LOG_PSEUDONYM_SALT: ${LOG_PSEUDONYM_SALT}
  celery-worker:
    environment:
      FERNET_KEY: ${FERNET_KEY}
      ERASURE_TOMBSTONE_SALT: ${ERASURE_TOMBSTONE_SALT}
      LOG_PSEUDONYM_SALT: ${LOG_PSEUDONYM_SALT}
  celery-beat:
    environment:
      FERNET_KEY: ${FERNET_KEY}
      ERASURE_TOMBSTONE_SALT: ${ERASURE_TOMBSTONE_SALT}

Vollständige Übersicht aller Pflicht-Secrets je Funktion: Konfigurationsmatrix — Pflicht-Secrets.

Ab jetzt beide Compose-Dateien angeben

Da du eine zusätzliche docker-compose.override.yml angelegt hast, muss ab hier jeder docker compose-Befehl beide Dateien referenzieren: -f docker-compose.release.yml -f docker-compose.override.yml. Alle folgenden Befehle auf dieser Seite gehen davon aus.


3. Version festlegen

In der Datei docker-compose.release.yml steht als Platzhalter __VERSION__. Ersetze ihn durch die gewünschte Version:

# Beispiel: Version 1.0.0 setzen
sed -i 's/__VERSION__/1.0.0/g' docker-compose.release.yml
Welche Version soll ich nehmen?

Verwende die neueste stabile Version. Die verfügbaren Versionen findest du auf der Releases-Seite des Projekts.


4. Starten

docker compose -f docker-compose.release.yml -f docker-compose.override.yml up -d

Prüfe den Status:

docker compose -f docker-compose.release.yml -f docker-compose.override.yml ps

Alle Dienste sollten nach 30–60 Sekunden als running oder healthy angezeigt werden.


5. Zugriff testen

Öffne im Browser:

Auf dem Server selbst setzt du localhost statt dein-server ein. Von jedem anderen Gerät aus antworten diese Adressen erst, wenn du die beiden Ports geöffnet hast — siehe Zugriff von anderen Geräten; bis dahin sind sie an 127.0.0.1 gebunden, und ein anderes Gerät bekommt „Verbindung abgelehnt".


Automatischer Neustart

Die Release-Konfiguration enthält bereits restart: unless-stopped für alle Dienste. Das bedeutet:

  • Nach einem Serverabsturz oder Neustart startet Docker die Dienste automatisch
  • Dienste, die du bewusst mit docker compose stop anhältst, bleiben gestoppt

Damit Docker selbst nach einem Neustart automatisch startet:

sudo systemctl enable docker

Updates durchführen

So aktualisierst du Kamerplanter auf eine neue Version:

cd ~/kamerplanter

# 1. Version in der Compose-Datei aktualisieren
sed -i 's/alte-version/neue-version/g' docker-compose.release.yml

# 2. Neue Images herunterladen und Dienste neu starten
docker compose -f docker-compose.release.yml -f docker-compose.override.yml pull
docker compose -f docker-compose.release.yml -f docker-compose.override.yml up -d

# 3. Alte, nicht mehr benötigte Images aufräumen (optional)
docker image prune -f

Daten bleiben erhalten

Deine Pflanzen, Standorte und alle anderen Daten werden in Docker Volumes gespeichert und überleben Updates problemlos.


Datensicherung

Die Daten von Kamerplanter liegen in zwei Docker Volumes:

  • arangodb_data — Alle Pflanzen, Standorte, Aufgaben und Konfigurationen
  • valkey_data — Cache und Aufgaben-Warteschlange (nicht kritisch, wird automatisch neu aufgebaut)

Sicherung erstellen

# ArangoDB-Daten sichern
docker compose -f docker-compose.release.yml -f docker-compose.override.yml exec arangodb \
  arangodump --server.password "$ARANGO_ROOT_PASSWORD" \
  --output-directory /tmp/backup --overwrite true

# Backup aus dem Container kopieren
docker compose -f docker-compose.release.yml -f docker-compose.override.yml cp \
  arangodb:/tmp/backup ./backup-$(date +%Y%m%d)

Sicherung wiederherstellen

# Backup in den Container kopieren
docker compose -f docker-compose.release.yml -f docker-compose.override.yml cp \
  ./backup-20260317 arangodb:/tmp/backup

# Daten wiederherstellen
docker compose -f docker-compose.release.yml -f docker-compose.override.yml exec arangodb \
  arangorestore --server.password "$ARANGO_ROOT_PASSWORD" \
  --input-directory /tmp/backup --overwrite true

Regelmäßige Backups

Richte einen Cronjob ein, der die Sicherung automatisch durchführt — zum Beispiel täglich um 3:00 Uhr nachts. So verlierst du im schlimmsten Fall maximal einen Tag an Daten.


Zugriff von anderen Geräten

Standardmäßig ist Kamerplanter nur über den Server selbst erreichbar: docker-compose.release.yml bindet jeden Port an 127.0.0.1. Um von Smartphone, Tablet oder anderen Rechnern im Heimnetz zuzugreifen:

  1. Öffne Benutzeroberfläche und API für dein Netzwerk. Ergänze diese Zeile in der .env:

    .env
    KAMERPLANTER_BIND_ADDRESS=0.0.0.0
    

    Damit öffnest du genau zwei Ports: die Benutzeroberfläche (8080) und die API (8000), mit der ein Home-Assistant-Rechner in deinem Netzwerk spricht. Datenbanken, Valkey und Ollama bleiben nur vom Server aus erreichbar, egal was du hier einträgst.

    Hat der Server mehr als ein Netzwerk (ein VPN, eine zweite Netzwerkkarte, eine öffentliche Adresse), trag statt 0.0.0.0 die Heimnetz-Adresse des Servers ein — etwa KAMERPLANTER_BIND_ADDRESS=192.168.1.100 —, dann öffnen sich die Ports nur in diesem Netz.

    Danach kann jeder in deinem Netzwerk Kamerplanter benutzen

    Die Release-Datei läuft im Light-Modus, der keine Anmeldung kennt. Sobald die Ports offen sind, kann jedes Gerät in deinem Netzwerk deine Daten lesen und ändern. Mach das nur in einem Heimnetz, dem du vertraust, hinter der Firewall deines Routers — nie mit einer Portweiterleitung ins Internet. Details: Light-Modus.

  2. Finde die IP-Adresse deines Servers:

    hostname -I
    
  3. Öffne auf dem anderen Gerät den Browser und gehe zu http://<IP-Adresse>:8080

  4. Passe die CORS-Einstellung in .env an, damit die API Anfragen von der neuen Adresse akzeptiert:

    .env
    CORS_ORIGINS=["http://localhost:8080","http://192.168.1.100:8080"]
    
  5. Starte die Dienste nach der Änderung neu:

    docker compose -f docker-compose.release.yml -f docker-compose.override.yml up -d
    

Nächste Schritte


Fehlerbehebung

Die Seite lädt nicht (Verbindung abgelehnt)

Prüfe, ob alle Dienste laufen: docker compose -f docker-compose.release.yml -f docker-compose.override.yml ps. Falls der Frontend-Dienst nicht läuft, prüfe die Logs: docker compose -f docker-compose.release.yml -f docker-compose.override.yml logs frontend.

Backend meldet 'Connection refused' zur Datenbank

ArangoDB braucht beim ersten Start etwas länger. Warte 30 Sekunden und prüfe erneut. Falls der Fehler bleibt: Stimmen die Passwörter in .env überein? ARANGO_ROOT_PASSWORD und ARANGODB_PASSWORD müssen identisch sein.

Zugriff von anderem Gerät funktioniert nicht

Prüfe: (1) Steht KAMERPLANTER_BIND_ADDRESS=0.0.0.0 in der .env, und hast du danach neu gestartet? Ohne diese Zeile ist Port 8080 an 127.0.0.1 gebunden und weist jedes andere Gerät ab. (2) Sind beide Geräte im gleichen Netzwerk? (3) Stimmt die IP-Adresse? (4) Ist die CORS-Einstellung in .env angepasst? (5) Blockiert eine Firewall Port 8080? Beachte auch die Gegenrichtung: Von Docker veröffentlichte Ports umgehen Host-Firewalls wie ufw oder firewalld. Eine Firewall-Regel schützt also keinen Port, den du mit KAMERPLANTER_BIND_ADDRESS geöffnet hast — das tut nur die Bind-Adresse.

Wie viel Speicherplatz braucht Kamerplanter langfristig?

Die Docker-Images belegen ca. 2 GB. Die Datenbank wächst je nach Nutzung — für einen typischen Heimanwender mit bis zu 100 Pflanzen bleiben die Daten unter 100 MB. Sensorik-Daten können bei aktivierter Aufzeichnung schneller wachsen.