sphings-dev.de

Marstek Offline Endpoint auf Unraid einrichten

Den Marstek Offline Endpoint auf Unraid mit eigener IP-Adresse betreiben, damit er Port 80 und 443 für sich hat, und per DNS dafür sorgen, dass die Batterie ihn statt der Cloud anspricht.

Der Marstek Offline Endpoint ist ein kleiner Container, der den Telemetrie-Upload eines Marstek Venus (E, D, E v3) im Heimnetz beantwortet. Ohne Antwort aus der Cloud setzt die Batterie auf der Control-Firmware v150 alle 30 Minuten ihren Netzwerkchip zurück; Modbus-Verbindungen brechen dabei ab. Firmware v151 startet stattdessen die Steuerung neu, wenn vier Stunden lang mindestens fünf Uploads unversendet bleiben, und schaltet dabei den Wechselrichterausgang ab. Der Container bestätigt jeden Upload, damit beides gar nicht erst eintritt.

So funktioniert die Umleitung

Die Batterie spricht zwei Server an: api-eu.marstekcloud.com für den Upload (HTTPS, Port 443) und eu.hamedata.com für die Uhrzeit (HTTP, Port 80). Du änderst nichts an der Batterie. Stattdessen sorgst du im Heimnetz dafür, dass beide Namen auf den Rechner zeigen, auf dem der Container läuft. Dazu legst du zwei DNS-Einträge für die ganzen Domains marstekcloud.com und hamedata.com an, damit auch eine andere Region als eu im Namen funktioniert. Die Ports 80 und 443 lassen sich nicht ändern, die Batterie verbindet sich fest dorthin.

Zwei Dinge gehören ausdrücklich nicht dazu: Den MQTT-Broker der Batterie leitest du nicht um (er prüft Zertifikate und lässt sich nicht nachbilden), und der Container gehört nicht ins Internet. Öffne also keine Ports im Router dorthin.

Warum der Container eine eigene IP-Adresse bekommt

Der Container braucht die Ports 80 und 443, und die Batterie verbindet sich fest dorthin. Auf einem Unraid-Server sind genau diese Ports in der Regel schon von der Weboberfläche des NAS belegt. Statt dort etwas umzubauen, bekommt der Container eine eigene Adresse im Heimnetz, so als wäre er ein weiteres Gerät. Die Ports 80 und 443 gehören dann ihm allein, ohne Konflikt mit dem NAS.

Technisch heißt das macvlan: Der Container hängt mit einer eigenen MAC-Adresse direkt im LAN. Diese Adresse ist auch das Ziel der späteren DNS-Einträge. Es gibt eine bekannte Einschränkung: Das NAS selbst kann den Container über diese Adresse nicht erreichen, alle anderen Geräte im Netz schon. Das stört hier nicht, denn die Batterie und dein PC sind andere Geräte. Nur Tests wie ping oder nslookup führst du von einem PC aus durch, nicht auf dem NAS.

Vorbereitung

Die Oberfläche von Unraid ist englisch, deshalb stehen die Menüpunkte hier ebenfalls auf Englisch. Je nach Version können Bezeichnungen leicht abweichen. Unraid unterstützt Docker Compose nicht von Haus aus. Du legst den Container deshalb über das Formular „Add Container“ an.

Docker aktivieren

  1. Öffne die Unraid-Weboberfläche und wechsle zu „Settings › Docker“.
  2. Stelle „Enable Docker“ auf „Yes“, falls es noch auf „No“ steht.
  3. Klicke auf „Apply“.

Danach erscheint in der Hauptnavigation der Reiter „Docker“. Docker läuft nur, wenn das Array gestartet ist. Prüfe das unter „Main“, falls der Reiter fehlt.

Eine freie IP-Adresse wählen

Der Container braucht eine feste Adresse, die der DHCP-Server deines Routers nicht vergibt. Schau im Router nach dem DHCP-Bereich (zum Beispiel 192.168.1.100 bis 192.168.1.200) und wähle eine Adresse außerhalb, zum Beispiel 192.168.1.60. Prüfe mit ping 192.168.1.60 von einem PC, dass niemand antwortet. Schreibe dir die Adresse auf; sie kommt später in die DNS-Einträge.

Container anlegen

  1. Öffne den Reiter „Docker“.
  2. Klicke auf „Add Container“ (unten auf der Seite).
  3. Trage bei „Name“ ein: marstek-offline-endpoint.
  4. Trage bei „Repository“ ein: ghcr.io/sphings79/marstek-offline-endpoint:latest.
  5. Wähle bei „Network Type“ den Eintrag, der mit „Custom“ beginnt, zum Beispiel „Custom : br0“.
  6. Trage bei „Fixed IP address“ die gewählte Adresse ein, zum Beispiel 192.168.1.60.

Das Feld für die feste Adresse erscheint erst, wenn du einen „Custom“-Netzwerktyp gewählt hast. Je nach Netzwerkeinstellungen steht dort „Custom : br0“ oder „Custom : eth0“; beides ist richtig, nimm den Eintrag, der angeboten wird. Ports musst du nicht eintragen: Der Container hat eine eigene Adresse und lauscht dort direkt auf 80 und 443.

Jetzt kommen zwei Ordner für Daten und Zertifikat und eine Variable für die Zeitzone. Jeden Eintrag legst du mit dem Link „Add another Path, Port, Variable, Label or Device“ an, der im Formular unter den vorhandenen Feldern steht. Es öffnet sich ein kleiner Dialog.

  1. Klicke auf „Add another Path, Port, Variable, Label or Device“.
  2. Wähle bei „Config Type“ den Eintrag „Path“.
  3. Trage bei „Container Path“ ein: /data.
  4. Trage bei „Host Path“ ein: /mnt/user/appdata/marstek-offline-endpoint/data.
  5. Klicke im Dialog auf „Add“.
  6. Lege mit demselben Link einen zweiten „Path“ an: bei „Container Path“ /certs, bei „Host Path“ /mnt/user/appdata/marstek-offline-endpoint/certs.
  7. Lege mit demselben Link eine „Variable“ an: bei „Key“ TZ, bei „Value“ Europe/Berlin (oder deine Zeitzone).
  8. Klicke unten im Formular auf „Apply“.

Die Zeitzone ist wichtig: Der Container stellt die Uhr der Batterie, und ohne TZ bekommt sie UTC. Unraid lädt das Image und startet den Container. Wenn das Fenster „Done“ anzeigt, klicke darauf, um zur Docker-Seite zurückzukehren. Dort steht marstek-offline-endpoint in der Liste und läuft.

Automatisch starten

Fällt der Container länger aus, füllt sich der Puffer der Batterie, und die Resets beginnen von vorn. Er muss deshalb nach jedem Neustart des Servers wieder laufen.

  1. Schalte auf der Docker-Seite bei marstek-offline-endpoint den Schalter „Autostart“ auf „ON“.

Der Container startet jetzt mit dem Array. Dieser Schalter ersetzt restart: unless-stopped aus anderen Anleitungen.

Start prüfen

  1. Klicke auf das Symbol des Containers in der Docker-Liste.
  2. Wähle im Menü „Logs“.

Du willst drei „listening“-Zeilen sehen und keine Fehler:

https listening on :443
http  listening on :80
mqtt probe listening on :8883

DNS-Einträge anlegen

Jetzt kommt der Schritt, der die Batterie tatsächlich zu deinem Container umleitet. Du brauchst Zugriff auf den DNS-Server, den dein Heimnetz benutzt. Das ist meist ein Pi-hole oder AdGuard Home, manchmal der Router selbst, wenn er lokale DNS-Einträge für ganze Domains erlaubt. Als Ziel trägst du die feste Adresse des Containers ein; in dieser Anleitung ist das als Beispiel 192.168.1.60. Setze deine eigene Adresse ein.

So findest du heraus, wo du die Einträge anlegen musst: Schau in die DHCP-Einstellungen deines Routers. Der dort verteilte DNS-Server ist der, den auch die Batterie bekommt, und genau dort musst du die Einträge anlegen.

AdGuard Home

  1. Öffne die Weboberfläche von AdGuard Home.
  2. Wechsle zu „Filter › DNS-Umschreibungen“.
  3. Klicke auf „DNS-Umschreibung hinzufügen“.
  4. Trage als Domain marstekcloud.com und als IP-Adresse 192.168.1.60 ein und speichere.
  5. Lege ebenso *.marstekcloud.com mit 192.168.1.60 an.
  6. Lege hamedata.com mit 192.168.1.60 an.
  7. Lege *.hamedata.com mit 192.168.1.60 an.

AdGuard Home übernimmt Umschreibungen sofort. Es sind vier Einträge, jeweils die Domain ohne und mit Platzhalter.

Pi-hole

Die Maske für lokale DNS-Einträge in Pi-hole nimmt nur ganze Hostnamen. Einfacher ist eine kleine Konfigurationsdatei für den eingebauten dnsmasq-Dienst. Du legst sie auf dem Gerät an, auf dem Pi-hole läuft.

  1. Öffne ein Terminal auf dem Pi-hole-Rechner und gib den folgenden Befehl ein. Ersetze zuvor die Adresse durch deine eigene.
sudo tee /etc/dnsmasq.d/99-marstek.conf >/dev/null <<'EOF'
address=/marstekcloud.com/192.168.1.60
address=/hamedata.com/192.168.1.60
EOF
  1. Starte den DNS-Dienst von Pi-hole neu.
pihole restartdns

Wenn du statt der Domains nur die beiden genauen Namen eintragen willst, geht das in der Pi-hole-Oberfläche als lokaler DNS-Eintrag für api-eu.marstekcloud.com und für eu.hamedata.com. Das gilt dann nur für die Region eu, die bei der Batterie im Test beobachtet wurde. Die Domain-Variante ist die sicherere.

Router oder anderer DNS-Server

Wenn dein Router oder Firewall-System einen lokalen DNS-Eintrag oder „Host Override“ für eine ganze Domain anbietet, gelten dieselben zwei Domains mit derselben Zieladresse. Bei OPNsense liegt das unter „Services › Unbound DNS › Overrides › Domain Overrides“. Ob dein Router das kann, steht in dessen Handbuch; nicht jeder Router erlaubt Einträge für ganze Domains. Wenn nicht, brauchst du einen eigenen DNS-Server wie Pi-hole oder AdGuard Home.

Prüfen, ob die Einträge greifen

  1. Öffne auf einem PC oder Mac ein Terminal (unter Windows die Eingabeaufforderung oder PowerShell) und frage den ersten Namen ab.
nslookup api-eu.marstekcloud.com
  1. Frage auch den zweiten Namen ab.
nslookup eu.hamedata.com

In beiden Antworten muss unter „Name“ der jeweilige Hostname stehen und unter „Address“ die Adresse 192.168.1.60, also deine Container-Adresse, keine öffentliche. Steht dort eine fremde Adresse, benutzt dein PC einen anderen DNS-Server. Frage dann den richtigen direkt ab, indem du dessen Adresse anhängst: nslookup api-eu.marstekcloud.com DNS-SERVER-IP.

Die Batterie muss denselben DNS-Server benutzen wie dieser Test. Manche Geräte ignorieren den per DHCP verteilten DNS-Server und benutzen einen fest eingebauten. Dann hilft statt DNS eine Firewall-Regel (DNAT) im Router: Verkehr von der IP der Batterie auf die Ports 443 und 80 wird auf den Container umgebogen. Wenn die Batterie in einem eigenen VLAN hängt, muss sie den Container außerdem erreichen dürfen.

Kontrolle

  1. Öffne auf der Docker-Seite das Menü des Containers marstek-offline-endpoint (Klick auf das Symbol).
  2. Wähle „Logs“.

Innerhalb von etwa fünf Minuten erscheinen Zeilen wie diese (Uhrzeit und Anhänge sind bei dir anders):

2026-08-26 08:17:38 TIME   http GET eu.hamedata.com/app/neng/getDateInfoeu.php?uid=… (0 B)
2026-08-26 08:19:07 ACCEPT https POST api-eu.marstekcloud.com/data-upload/v1/venus/… (1204 B)

TIME ist die Batterie, die nach der Uhrzeit fragt. ACCEPT ist der Telemetrie-Upload, den der Container bestätigt. Beides zusammen heißt: Die Umleitung funktioniert. Die Zeitabfrage kommt etwa alle zehn Minuten, der Upload etwa alle fünf Minuten.

Kommen vier TIME-Zeilen im Abstand von 20 Sekunden hintereinander, lehnt die Batterie die Antwort ab; dann läuft ein veraltetes Image, lade es neu. Kommen Uploads exakt alle 86 Sekunden, ist noch ein Rückstau in der Batterie abzubauen. Das ist für ein bis zwei Stunden normal.

Die Messdaten schreibt der Container in den Ordner appdata/marstek-offline-endpoint/data auf dem Server: eine Datei requests-JJJJ-MM-TT.jsonl pro Tag. Du siehst sie in der Freigabe appdata.

Um zu sehen, dass die Abbrüche weg sind, kannst du von einem Mac oder Linux-Rechner, der durchläuft, die Batterie anpingen. Das folgende Skript meldet sich nur, wenn ein Ping ausfällt; so sieht ein Netzwerk-Reset der Batterie von außen aus. Ersetze 192.168.1.50 durch die IP deiner Batterie (in der Geräteliste deines Routers, meist als „Marstek“, „VenusE“ oder ähnlich geführt).

IP=192.168.1.50; F=0
while true; do
  if ping -c1 -W1 "$IP" >/dev/null 2>&1; then
    [ $F -gt 0 ] && echo "$(date '+%F %T')  WIEDER DA nach ${F}s"; F=0
  else
    [ $F -eq 0 ] && echo "$(date '+%F %T')  WEG"; F=$((F+1))
  fi
  sleep 1
done

Bleibt die Ausgabe über zwei halbe Stunden leer, ist es geschafft. Vorher stand dort alle 30 Minuten eine Meldung. Beim gemessenen Gerät dauerte es nach dem ersten bestätigten Upload etwa 45 Minuten, bis der Rückstau abgebaut war und die Abbrüche aufhörten.

Ein Rest bleibt, den der Container nicht beheben kann: Bei jedem Upload rechnet die Batterie etwa vier bis fünf Sekunden am TLS-Schlüsselaustausch und beantwortet in der Zeit kein Modbus. Stelle deshalb in deinem Modbus-Client ein Antwort-Timeout von mindestens 6 Sekunden ein.

Wenn etwas nicht klappt

Nach 15 Minuten steht nichts im Log.

Die Batterie landet nicht beim Container. Wiederhole die nslookup-Prüfung. Sieht sie richtig aus, hat die Batterie womöglich eine alte Antwort zwischengespeichert: Trenne sie kurz vom Strom, schalte sie wieder ein und warte fünf Minuten. Kommt immer noch nichts, benutzt sie einen fest eingebauten DNS-Server, dann hilft die DNAT-Regel im Router.

TIME-Zeilen kommen, aber kein ACCEPT.

Nur hamedata.com ist umgeleitet, marstekcloud.com nicht. Prüfe den zweiten DNS-Eintrag samt Platzhalter-Variante.

Der Server oder die Unraid-Oberfläche kann den Container nicht erreichen.

Das ist die bekannte macvlan-Einschränkung: Der Unraid-Server erreicht seine Container mit eigener Adresse nicht direkt. Teste vom PC aus. Die Batterie ist davon nicht betroffen.

Bei „Network Type“ gibt es keinen „Custom“-Eintrag.

Prüfe unter „Settings › Network Settings“, ob die Netzwerkschnittstelle läuft, und halte danach Docker unter „Settings › Docker“ kurz an und starte es wieder. Ohne einen „Custom“-Eintrag lässt sich keine feste Adresse für Container vergeben.

Die Adresse wird nicht angenommen oder ist doppelt vergeben.

Die gewählte Adresse liegt im DHCP-Bereich des Routers oder gehört schon einem anderen Gerät. Wähle eine freie Adresse außerhalb des Bereichs, ändere sie bei „Fixed IP address“ und klicke auf „Apply“. Danach musst du die DNS-Einträge anpassen.

Der Container ist nach dem Neustart des Servers nicht da.

Prüfe, dass „Autostart“ auf „ON“ steht und das Array startet. Docker kann nur starten, wenn das Array gestartet ist.

Voraussetzungen

  • Unraid 7 mit gestartetem Array und aktiviertem Docker
  • Eine freie IP-Adresse im Heimnetz außerhalb des DHCP-Bereichs für den Container
  • Zugriff auf den DNS-Server im Heimnetz (z. B. Pi-hole oder AdGuard Home)
  • Ein Marstek Venus (E, D oder E v3) im selben Netz
  • Ein PC im Heimnetz für die Tests (nslookup, ping)

Andere Systeme

Unterstützen

Diese Tools entstehen in meiner Freizeit und bleiben kostenlos, offen und cloud-frei. Wenn dir eins davon einen Nachmittag gespart hat, freue ich mich über einen Kaffee oder ein Stück Pizza.

Kaffee oder Pizza