sphings-dev.de

Marstek Offline Endpoint auf Synology einrichten

Den Marstek Offline Endpoint auf einem Synology-NAS mit Container Manager betreiben. Per macvlan bekommt er eine eigene IP und kollidiert nicht mit der NAS-Oberfläche; per DNS spricht die Batterie dann ihn statt der Cloud an.

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 Synology-NAS 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 Anleitung gilt für DSM 7 mit dem Paket „Container Manager“. Je nach Version können Bezeichnungen leicht abweichen. Wenn „Container Manager“ im Paketzentrum nicht erscheint, unterstützt dein NAS-Modell das Paket nicht.

Container Manager installieren

  1. Öffne das „Paketzentrum“.
  2. Wechsle zu „Alle Pakete“.
  3. Suche oben links nach „Container Manager“.
  4. Klicke bei „Container Manager“ auf „Installieren“.

Nach der Installation erscheint „Container Manager“ im Hauptmenü. Bei einer Neuinstallation legt das Paket außerdem den freigegebenen Ordner docker an.

Netzwerkwerte sammeln

Für das Netzwerk in der Compose-Datei brauchst du vier Werte. Alle vier findest du in der Weboberfläche deines Routers, die ersten drei auch in den Netzwerkeinstellungen des NAS.

  • Die Schnittstelle des NAS („parent“): der LAN-Anschluss, über den das NAS im Netz hängt, meist eth0. Bei einem Zusammenschluss mehrerer Anschlüsse oder aktiviertem Open vSwitch heißt sie anders, etwa bond0 oder ovs_eth0. Sie muss ein Kabelanschluss sein; über WLAN funktioniert macvlan in der Regel nicht.
  • Das Subnetz: Wenn die Adresse deines NAS mit 192.168.1. beginnt und die Subnetzmaske 255.255.255.0 lautet, ist das Subnetz 192.168.1.0/24. Das /24 steht für diese Maske.
  • Das Gateway: die Adresse deines Routers, meist 192.168.1.1.
  • Eine freie IP-Adresse für den Container, 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.

Im Folgenden gelten diese Beispielwerte: Schnittstelle eth0, Subnetz 192.168.1.0/24, Gateway 192.168.1.1, Container-Adresse 192.168.1.60. Ersetze sie in der Compose-Datei durch deine eigenen.

Ordner anlegen

  1. Öffne die „File Station“.
  2. Wechsle in den freigegebenen Ordner docker.
  3. Lege darin einen Ordner namens marstek-offline-endpoint an.

Fehlt der freigegebene Ordner docker, legst du ihn unter „Systemsteuerung › Freigegebener Ordner › Erstellen“ an. Die Unterordner data und certs legt der Container selbst an.

Projekt erstellen

Du legst den Container als Projekt an. Das ist eine Compose-Datei, die du direkt in die Oberfläche einfügst.

  1. Öffne den „Container Manager“.
  2. Wähle links „Projekt“.
  3. Klicke oben auf „Erstellen“.
  4. Trage bei „Projektname“ ein: marstek-offline-endpoint.
  5. Wähle bei „Pfad“ den Ordner docker/marstek-offline-endpoint aus (Schaltfläche zum Durchsuchen).
  6. Wähle bei „Quelle“ die Möglichkeit, die Datei „docker-compose.yml“ selbst zu erstellen.
  7. Füge im Editor den folgenden Inhalt ein und passe die mit ANPASSEN markierten Werte an dein Netz an.
# Marstek Offline Endpoint: beantwortet die Cloud-Anfragen deiner Marstek Venus im Heimnetz
services:
  marstek-offline-endpoint:
    image: ghcr.io/sphings79/marstek-offline-endpoint:latest   # fertiges Image für PC, NAS und Raspberry Pi
    container_name: marstek-offline-endpoint
    restart: unless-stopped        # startet nach einem Neustart automatisch wieder, das ist wichtig
    networks:
      meo_lan:
        ipv4_address: 192.168.1.60 # ANPASSEN: freie Adresse für den Container, außerhalb des DHCP-Bereichs
    # Keine "ports": Der Container hat eine eigene IP und lauscht dort direkt auf 80 und 443.
    volumes:
      - /volume1/docker/marstek-offline-endpoint/data:/data     # ANPASSEN: Volume-Nummer, falls nicht 1
      - /volume1/docker/marstek-offline-endpoint/certs:/certs
    environment:
      - TZ=Europe/Berlin           # deine Zeitzone, sonst stellt der Container die Uhr der Batterie auf UTC

networks:
  meo_lan:
    driver: macvlan
    driver_opts:
      parent: eth0                 # ANPASSEN: LAN-Anschluss des NAS (Kabel)
    ipam:
      config:
        - subnet: 192.168.1.0/24   # ANPASSEN: dein Subnetz
          gateway: 192.168.1.1     # ANPASSEN: dein Router
  1. Klicke auf „Weiter“.
  2. Lass die Option für das Webportal („Web Station“) ausgeschaltet und klicke auf „Weiter“.
  3. Lass die Option zum Starten des Projekts eingeschaltet.
  4. Klicke auf „Fertig“.

Container Manager lädt das Image aus der GitHub Container Registry, legt das Netzwerk an und startet den Container. Das dauert eine Weile. Danach steht das Projekt in der Liste mit dem Status „Läuft“. Der Eintrag „Erstellen“ taucht an zwei Stellen auf: als Schaltfläche, die ein neues Projekt anlegt, und im Menü „Aktion“ als Aktion für ein bestehendes Projekt. Wir brauchen hier nur die Schaltfläche.

Wichtig: Klicke später nicht auf „Bereinigen“ oder „Löschen“, wenn du die Daten behalten willst. Mit „Beenden“ und „Starten“ stoppst und startest du das Projekt gefahrlos.

Start prüfen

  1. Wähle im Container Manager links „Container“.
  2. Klicke auf marstek-offline-endpoint, dann auf „Details“.
  3. Öffne den Reiter „Protokoll“.

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

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

Der Container startet nach einem Neustart des NAS automatisch wieder, dafür sorgt restart: unless-stopped in der Compose-Datei, solange der Container Manager mit dem NAS startet.

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 im Container Manager „Container“.
  2. Klicke auf marstek-offline-endpoint, dann auf „Details“.
  3. Öffne den Reiter „Protokoll“.

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 liegen in der File Station unter docker/marstek-offline-endpoint/data: eine Datei requests-JJJJ-MM-TT.jsonl pro Tag.

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.

Das Projekt startet nicht, es gibt eine Meldung zum Netzwerk.

Meistens stimmt einer der Werte im Netzwerkteil nicht: Subnetz, Gateway oder Schnittstelle. Prüfe sie noch einmal gegen deinen Router und die Netzwerkeinstellungen des NAS. Ist die gewählte Container-Adresse bereits vergeben oder liegt sie nicht im Subnetz, scheitert das Starten ebenfalls.

Der Container antwortet nicht auf ping.

Teste von einem anderen Gerät, nicht vom NAS aus: Der Zugriff vom NAS auf den eigenen Container ist bei macvlan nicht möglich. Antwortet auch der PC nicht, läuft der Container nicht oder die Schnittstelle (parent) stimmt nicht. Bei einem WLAN-Anschluss funktioniert macvlan meistens nicht. In seltenen Fällen lässt ein Switch oder Router mit Port-Sicherheit nur eine MAC-Adresse pro Anschluss zu.

Eine andere Adresse im Netz ist plötzlich nicht mehr erreichbar.

Die Container-Adresse wird noch von einem anderen Gerät benutzt (Adresskonflikt). Wähle eine andere freie Adresse, ändere sie in der Compose-Datei und stelle das Projekt neu bereit.

Das Image lässt sich nicht herunterladen.

Das Image liegt bei ghcr.io (GitHub Container Registry), nicht bei Docker Hub. Prüfe, dass das NAS ins Internet kommt. Das Projekt zieht das Image selbst; du musst es nicht in der Registrierung suchen.

Voraussetzungen

  • Ein Synology-NAS mit DSM 7, das den Container Manager unterstützt
  • Zugriff auf Paketzentrum, Systemsteuerung und File Station (Administrator-Konto)
  • Eine freie IP-Adresse im Heimnetz außerhalb des DHCP-Bereichs für den Container
  • Subnetz und Gateway deines Netzes (Router-Adresse), aus der Router-Oberfläche
  • Das NAS hängt per Kabel im Netz
  • 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