[Docker / Container] echodevice

Begonnen von Sidey, 12 April 2026, 16:56:20

Vorheriges Thema - Nächstes Thema

Sidey

Hallo,

ich möchte hier mein Projekt kurz vorstellen und auch die grundlegende Architektur erläutern, weil die Frage sonst vermutlich recht schnell aufkommt.

Der FHEM-Docker-Container ist in erster Linie darauf ausgelegt, Perl-Programme auszuführen. Das Modul `echodevice` und auch einige andere Lösungen nutzen zusätzlich weitere Laufzeitumgebungen, zum Beispiel Node.js.

Seit Version 5 des FHEM-Images ist kein Node Package Manager mehr im FHEM-(Perl-)Docker-Image enthalten. In der Vergangenheit bedeutete das meist, dass man sich dafür ein eigenes angepasstes Image bauen musste.
Das dorr enthaltene NodeJS (18) ist schon längst aus der Wartung.
Da hier auch mit Authentifizierungsinformationen handelt, sollte einem die Sicherheit der Software nicht völlig egal sein.

Nach einer kurzen Diskussion hier im Forum habe ich mich daher entschieden, das von `echodevice` verwendete `alexa-cookie2` in einen eigenen Hilfscontainer auszulagern. Das Ganze heißt `alexa-cookie-service`.

Der Service stellt eine REST-API zur Verfügung, über die die notwendigen Schritte für die Anmeldung am Amazon-Dienst umgesetzt werden können.

Projektlink: 
https://github.com/fhem/alexa-cookie-service

Grobes Integrationsmuster: 
FHEM / echodevice -> HTTP/REST -> alexa-cookie-service -> Amazon

Das bedeutet konkret:

- Das Modul `echodevice` bleibt im normalen FHEM-Container.
- Der separate Service-Container stellt per REST-API die Funktionen rund um `alexa-cookie2` bereit.
- FHEM ruft diese API bei Bedarf auf, anstatt Node.js-Code direkt im FHEM-Container auszuführen.

Die Motivation für die Trennung ist vor allem:

- Der FHEM-Container soll möglichst nah an einer klassischen und gut wartbaren FHEM-Laufzeitumgebung bleiben.
- Ein Node.js-Projekt bringt eine eigene Runtime, eigene Abhängigkeiten und meist auch einen anderen Release- und Update-Zyklus mit.
- Wenn man beides in einen einzigen Container packt, vermischt man zwei technisch unterschiedliche Aufgabenbereiche.
- Das macht Images größer, die Wartung aufwendiger und erschwert Updates, Fehlersuche und Debugging.
- Zusätzlich wird es unpraktisch, wenn man nur den Service neu starten oder aktualisieren möchte, ohne gleichzeitig die FHEM-Umgebung anzufassen.

Mit einem separaten Service-Container ist die Trennung sauberer:

- Der Node.js-Dienst kann in einer dafür passenden Umgebung laufen.
- Beide Komponenten können unabhängig voneinander gestartet, gestoppt und aktualisiert werden.
- Fehler lassen sich leichter eingrenzen, weil klarer ist, ob ein Problem aus FHEM oder aus dem Service stammt.

Mir ist wichtig, dass diese Entscheidung nicht als unnötige Verkomplizierung verstanden wird. Auf den ersten Blick könnte es einfacher wirken, alles in einen Container zu legen. Praktisch erkauft man sich diese vermeintliche Einfachheit aber oft mit mehr Aufwand bei Pflege und Betrieb.

Die Aufteilung in FHEM-Container und Service-Container ist daher eine bewusste Designentscheidung zugunsten von Stabilität, Wartbarkeit und klaren Zuständigkeiten.

Damit das aktuelle echodevice Modul mit der Integration weiter funktioniert, habe ich ein paar Hilfs Definitionen (HTTPMOD, notify, at) auf der Projektseite beschrieben.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem,zigbee2mqtt

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker, WebAuth

FlatTV

Hallo Sidey,

ich wollte das mal kurz testen, bekomme nach
curl -H "x-auth-token: change-me" http://127.0.0.1:58080/api/statusein
{"error":"Unauthorized"}zurück
Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

Sidey

Zitat von: FlatTV am 12 Mai 2026, 16:26:02Hallo Sidey,

ich wollte das mal kurz testen, bekomme nach
curl -H "x-auth-token: change-me" http://127.0.0.1:58080/api/status

Hast Du als AUTH_TOKEN auch change-me gesetzt?
Der Wert muss mit dem Header übereinstimmen.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem,zigbee2mqtt

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker, WebAuth

FlatTV

Ja, aber nicht in der yml Datei  :-\
thx
Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

FlatTV

#4
Also wenn ich nur eine yml Datei auf meinem pi habe, startet der Container nicht.

name: alexa-cookie-service
alexa-cookie-service-1 exited with code 1 (restarting)
alexa-cookie-service-1  |
alexa-cookie-service-1  | > alexa-cookie-service@0.3.0 start
alexa-cookie-service-1  | > node src/server.js
alexa-cookie-service-1  |
alexa-cookie-service-1  | node:fs:1370
alexa-cookie-service-1  |   const result = binding.mkdir(
alexa-cookie-service-1  |                          ^
alexa-cookie-service-1  |
alexa-cookie-service-1  | Error: EACCES: permission denied, mkdir '/data/cookie-export'
alexa-cookie-service-1  |     at Object.mkdirSync (node:fs:1370:26)
alexa-cookie-service-1  |     at Object.<anonymous> (/app/src/server.js:13:4)
alexa-cookie-service-1  |     at Module._compile (node:internal/modules/cjs/loader:1705:14)
alexa-cookie-service-1  |     at Object..js (node:internal/modules/cjs/loader:1838:10)
alexa-cookie-service-1  |     at Module.load (node:internal/modules/cjs/loader:1441:32)
alexa-cookie-service-1  |     at Function._load (node:internal/modules/cjs/loader:1263:12)
alexa-cookie-service-1  |     at TracingChannel.traceSync (node:diagnostics_channel:328:14)
alexa-cookie-service-1  |     at wrapModuleLoad (node:internal/modules/cjs/loader:237:24)
alexa-cookie-service-1  |     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:171:5)
alexa-cookie-service-1  |     at node:internal/main/run_main_module:36:49 {
alexa-cookie-service-1  |   errno: -13,
alexa-cookie-service-1  |   code: 'EACCES',
alexa-cookie-service-1  |   syscall: 'mkdir',
alexa-cookie-service-1  |   path: '/data/cookie-export'
alexa-cookie-service-1  | }
alexa-cookie-service-1  |
alexa-cookie-service-1  | Node.js v22.22.2
alexa-cookie-service-1  | npm notice
alexa-cookie-service-1  | npm notice New major version of npm available! 10.9.7 -> 11.14.1
alexa-cookie-service-1  | npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.14.1
alexa-cookie-service-1  | npm notice To update run: npm install -g npm@11.14.1
alexa-cookie-service-1  | npm notice
alexa-cookie-service-1 exited with code 1 (restarting)

cat alexa-cookie-service.yml
name: alexa-cookie-service
networks:
  fhem-net:
    external: true
services:
  alexa-cookie-service:
    image: ghcr.io/fhem/alexa-cookie-service:0.3.0
    volumes:
      - ./alexa-cookie-data:/data
      - ./fhem/cache/alexa-cookie:/opt/fhem/cache/alexa-cookie
    environment:
      HOST: 0.0.0.0
      PORT: 58080
      AUTH_TOKEN: 87b4feb87546bc9bca881d54dde1c3381f39711d5419dbfdb1b35c688db533fc
      DATA_DIR: /data
      STATE_FILE: /data/alexa-registration.json
      METADATA_FILE: /data/service-metadata.json
      COOKIE_EXPORT_DIR: /data/cookie-export
      # COOKIE_EXPORT_DIR: /opt/fhem/cache/alexa-cookie
      DEBUG_HTML_DIR: /data/debug-html
      AMAZON_PAGE: amazon.de
      BASE_AMAZON_PAGE: amazon.com
      ACCEPT_LANGUAGE: de-DE
      PROXY_PUBLIC_HOST: 192.168.178.188
      PROXY_LISTEN_BIND: 0.0.0.0
      PROXY_PORT: 58090
      PROXY_ONLY: true
      SETUP_PROXY: true
      APP_NAME: FHEM EchoDevice Cookie Service
      USE_HERMES: false
      REFRESH_SCHEDULE_HOURS: 24
      REFRESH_MIN_AGE_HOURS: 6
      REQUEST_TIMEOUT_MS: 30000
      LOG_LEVEL: combined
      TZ:   Europe/Berlin
    ports:
      - '58090:58090'
    networks:
      - fhem-net
    restart: unless-stopped
    user: '6061:6061'

So sieht das Verzeichnis aus:
571567 4 drwxrwxr-x  5 pi   pi   4096 May 12 18:12 .
 132722 4 drwx------ 22 pi   pi   4096 May 12 18:12 ..
1116707 4 drwxr-xr-x  2 root root 4096 May 12 18:12 alexa-cookie-data
 535855 4 -rw-rw-r--  1 pi   pi   1256 May 12 18:12 alexa-cookie-service.yml
 566774 4 drwxr-xr-x  4 6062 6062 4096 May 12 10:26 alexa-fhem
 535631 4 -rw-rw-r--  1 pi   pi    380 May 12 09:25 alexa-fhem.yml
 535633 4 -rw-rw-r--  1 pi   pi    847 May 12 09:20 deconz.yml
 535629 4 -rw-rw-r--  1 pi   pi    389 May 12 09:48 docker-compose.yml
 571777 4 drwxr-x--- 15 6061 6061 4096 May 12 15:51 fhem
 535888 4 -rw-rw-r--  1 pi   pi   1837 May 12 16:47 fhem.yml
 535628 4 -rw-rw-r--  1 pi   pi    408 May 12 09:03 openccu.yml
 535619 4 -rw-rw-r--  1 pi   pi    560 May 12 09:58 portainer.yml
 

//edit
Wenn der Ordner von fhem angelegt wurde, geht das auch.
Ich habe das mal mit sudo chown -R 6061:6061 alexa-cookie-data/ simuliert.
Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

Sidey

Zitat von: FlatTV am 12 Mai 2026, 18:25:25Also wenn ich nur eine yml Datei auf meinem pi habe, startet der Container nicht.

...

Ich habe das mal mit sudo chown -R 6061:6061 alexa-cookie-data/ simuliert.

Ja, das /data Verzeichnis muss für den angegeben User beschreibbar sein. Das könnte ich in der readme noch hinterlegen.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem,zigbee2mqtt

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker, WebAuth

FlatTV

Oder man legt das Volumen ./alexa-cookie-data:/data gleich nach .fhem/alexa-cookie-data:/data
Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

Sidey

Zitat von: FlatTV am 13 Mai 2026, 21:32:28Oder man legt das Volumen ./alexa-cookie-data:/data gleich nach .fhem/alexa-cookie-data:/data

Das kann ich jetzt nicht bewerten, was bei dir der Ordner fhem ist.

Was ich aber sagen kann ist, dass das data Volume von alexa-cookie-service nichts im fhem app Volume zu suchen hat.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem,zigbee2mqtt

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker, WebAuth

FlatTV

#8
Ich bekomme kein Cookie.
Der Login auf der Amazon Webseite meldet zwar ,,success" und im Log werden auch ohne Ende Daten ausgetauscht, am Ende aber dann:
alexa-cookie-service  | [2026-05-14T19:28:03,005 Europe/Berlin] [INFO] Alexa-Cookie: Response (401)
alexa-cookie-service  | [2026-05-14T19:28:03,007 Europe/Berlin] [INFO] Get User data Response: ""
alexa-cookie-service  | [2026-05-14T19:28:03,007 Europe/Berlin] [ERROR] Alexa login flow failed: Unexpected end of JSON input

Kann ich da irgendwie debuggen?

Ah, jetzt ist es ohne Fehler durchgelaufen
... csrf=1481045025","csrf":"1481045025","dataVersion":2}


alexa-cookie-service  | [2026-05-14T19:40:38,205 Europe/Berlin] [INFO] 127.0.0.1 - - [14/May/2026:17:40:38 +0000] "GET /healthz HTTP/1.1" 200 4449 "-" "-"

Gespeichert wird aber nichts, irgendwas ist da noch falsch?!

Internals:
   BUSY       0
   DEF        http://alexa-cookie-service:58080/api/status 300
   FUUID      6a05fb1a-f33f-c628-f574-27055de8ff6d3b4b
   Interval   300
   MainURL    http://alexa-cookie-service:58080/api/status
   ModuleVersion 4.2.0 - 11.8.2023
   NAME       AlexaCookieService
   NOTIFYDEV  global
   NR         45
   NTFY_ORDER 50-AlexaCookieService
   STATE      ???
   TYPE       HTTPMOD
   eventCount 12
   value     
   CompiledRegexes:
   HttpUtils:
     NAME       
     addr       http://alexa-cookie-service:58080
     auth       0
     buf       
     code       401
     compress   1
     conn       
     data       
     displayurl http://alexa-cookie-service:58080/api/status
     header     
     host       alexa-cookie-service
     httpheader HTTP/1.1 401 Unauthorized
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Origin-Agent-Cluster: ?1
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
Content-Type: application/json; charset=utf-8
Content-Length: 24
ETag: W/"18-XPDV80vbMk4yY1/PADG4jYM4rSI"
Date: Thu, 14 May 2026 17:48:27 GMT
Connection: close
     httpversion 1.0
     hu_blocking 0
     hu_filecount 1
     hu_port    58080
     hu_portSfx :58080
     ignoreredirects 1
     loglevel   4
     path       /api/status
     protocol   http
     redirects  0
     timeout    8
     url        http://alexa-cookie-service:58080/api/status
     sslargs:
   QUEUE:
   READINGS:
     2026-05-14 19:48:27   LAST_REQUEST    update
     2026-05-14 19:48:27   MATCHED_READINGS error
     2026-05-14 19:48:27   UNMATCHED_READINGS ok updatedAt ageHours hasCookie hasRefreshToken proxyUrl message
     2026-05-14 19:48:27   error           Unauthorized
     2026-05-14 19:39:56   message         Please open http://192.168.178.188:58090/ with your browser and login to Amazon. The cookie will be output here after successfull login.
     2026-05-14 19:39:56   proxyUrl        http://192.168.178.188:58090/
   REQUEST:
     context    reading
     data       
     header     
     ignoreredirects 0
     num        unknown
     retryCount 0
     type       update
     url        http://alexa-cookie-service:58080/api/status
   defptr:
     readingBase:
       error      reading
       message    reading
       proxyUrl   reading
     readingNum:
       error      08
       message    07
       proxyUrl   06
     readingOutdated:
     requestReadings:
       get01:
         error      reading 08
         message    reading 07
         proxyUrl   reading 06
       update:
         error      reading 08
Attributes:
   get01Header1 x-auth-token: %%ACS_TOKEN%%
   get01Name  loginUrl
   get01URL   http://alexa-cookie-service:58080/api/cookie/login/url
   reading01JSON ok
   reading02JSON updatedAt
   reading03JSON ageHours
   reading04JSON hasCookie
   reading05JSON hasRefreshToken
   reading06JSON proxyUrl
   reading07JSON message
   reading08JSON error
   replacement01Mode key
   replacement01Regex %%ACS_TOKEN%%
   replacement01Value alexa_cookie_service_token
   replacement02Mode key
   replacement02Regex %%ACS_EXPORT_NAME%%
   replacement02Value alexa_cookie_service_export_name
   room       Amazon
   set01Data  {}
   set01Header1 x-auth-token: %%ACS_TOKEN%%
   set01Header2 Content-Type: application/json
   set01Method POST
   set01Name  loginStart
   set01NoArg 1
   set01ParseResponse 1
   set01URL   http://alexa-cookie-service:58080/api/cookie/login/start
   set02Data  {}
   set02Header1 x-auth-token: %%ACS_TOKEN%%
   set02Header2 Content-Type: application/json
   set02Method POST
   set02Name  refresh
   set02NoArg 1
   set02ParseResponse 1
   set02URL   http://alexa-cookie-service:58080/api/cookie/refresh?save=%%ACS_EXPORT_NAME%%
   showError  1
   showMatched 1
   timeout    8
yml:
networks:
  fhem-net:
    external: true
services:
  alexa-cookie-service:
    image: ghcr.io/fhem/alexa-cookie-service:0.3.0
    container_name: alexa-cookie-service
    volumes:
      - ./alexa-cookie-data:/data
      - ./fhem/cache/alexa-cookie:/opt/fhem/cache/alexa-cookie
    environment:
      BASE_AMAZON_PAGE: amazon.com
      REFRESH_MIN_AGE_HOURS: 6
      COOKIE_EXPORT_DIR: /opt/fhem/cache/alexa-cookie
      STATE_FILE: /data/alexa-registration.json
      SETUP_PROXY: true
      METADATA_FILE: /data/service-metadata.json
      DEBUG_HTML_DIR: /data/debug-html
      APP_NAME: FHEM EchoDevice Cookie Service
      TZ: Europe/Berlin
      PROXY_ONLY: true
      PROXY_PORT: 58090
      AMAZON_PAGE: amazon.de
      PROXY_LISTEN_BIND: 0.0.0.0
      USE_HERMES: false
      REQUEST_TIMEOUT_MS=: 30000
      LOG_LEVEL: combined
      AUTH_TOKEN: xxx
      HOST: 0.0.0.0
      PORT: 58080
      DATA_DIR: /data
      PROXY_PUBLIC_HOST: 192.168.178.188
      REFRESH_SCHEDULE_HOURS: 24
      ACCEPT_LANGUAGE: de-DE
    ports:
      - '58090:58090'
    networks:
      - fhem-net
    restart: unless-stopped
    user: '6061:6061'
Und
set AlexaCookieService storeKeyValue alexa_cookie_service_export_name 45result.jsonhabe ich gesetzt.

Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)