diff --git a/README.md b/README.md index 71d1630..df4c14a 100644 --- a/README.md +++ b/README.md @@ -55,17 +55,18 @@ Neustart an; danach wird derselbe Befehl erneut ausgeführt. | llama.cpp | nur Docker-intern | Inferenz und integrierte Vision | | Profile Controller | nur Docker-intern | eng begrenzter Profil-/FLUX-Hot-Swap | | FLUX Worker | nur Docker-intern, normalerweise gestoppt | Bildgenerierung auf RTX 5080 | -| XTTS-v2 | nur Docker-intern, RTX 3060 | primäre mehrsprachige Sprachausgabe | -| TTS Gateway | nur Docker-intern | Annmarie Nele, Queue und Piper-Fallback | -| Piper | nur Docker-intern, CPU | ausfallsichere deutsche Ersatzstimme | -| MCP-Tool-Stack | nur Docker-intern | Athena-Kontext, Athena Operator, Web, GitHub, Home Assistant, ARR, Unraid und Navidrome | +| XTTS-v2 | `:8092`, RTX 3060 | primäre mehrsprachige Sprachausgabe | +| TTS Gateway | `:8085` | Annmarie Nele, Queue und Piper-Fallback | +| Piper | `:8091`, CPU | ausfallsichere deutsche Ersatzstimme | +| MCP-Tool-Stack | `:8201-8208` | Athena-Kontext, Athena Operator, Web, GitHub, Home Assistant, ARR, Unraid und Navidrome | XTTS-v2, TTS-Gateway, Piper-Fallback und der FLUX.2-Klein-Hot-Swap sind reproduzierbare Kerndienste; STT bleibt optional. Web-, Home-Assistant-, GitHub-, ARR-, Unraid- und Navidrome-Werkzeuge besitzen dagegen bereits getrennte Container unter -`platform/mcp/`. Open WebUI erreicht sie ausschließlich über das interne -`mike-ai-tools`-Netz; llama.cpp erhält keine MCP-Konfiguration und keine +`platform/mcp/`. Open WebUI erreicht sie über das interne `mike-ai-tools`-Netz; +Pi, Hermes und andere Clients verwenden die direkten WireGuard-Ports aus +`docs/VPN_SERVICE_PORTS.md`. llama.cpp erhält keine MCP-Konfiguration und keine Infrastruktur-Secrets. Die Bildanalyse ist Bestandteil des multimodalen Qwen-Modells. diff --git a/compose.yaml b/compose.yaml index af2aeba..f243e59 100644 --- a/compose.yaml +++ b/compose.yaml @@ -48,6 +48,8 @@ services: networks: frontend: ipv4_address: 172.30.10.254 + tools: + ipv4_address: 172.30.40.254 tools-egress: ipv4_address: 172.30.50.254 security_opt: ["no-new-privileges:true"] diff --git a/config/install.env.example b/config/install.env.example index 9f0b65b..9c6408e 100644 --- a/config/install.env.example +++ b/config/install.env.example @@ -33,6 +33,8 @@ SSH_KEY_ONLY=true WIREGUARD_MODE=container WIREGUARD_CONFIG_FILE=/etc/mike-ai/wireguard/fritz-athena.conf WIREGUARD_ENABLE=false +# Stable Fritzbox/WireGuard address used by direct VPN clients such as Pi or Hermes. +VPN_SERVICE_IP=192.168.1.212 # The values below are only used by the legacy host-terminated mode. The # default container mode takes address, peer and routes from the Fritzbox file. AI_BIND_ADDRESS=10.77.0.2 diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index df460f8..7426c54 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -15,6 +15,7 @@ Heimnetz / VPN-Clients | :8080 Open WebUI :8081 Profile Router API + :8201-08 direkte MCP-Endpunkte | Docker-intern +-- Profile Controller -- Docker Socket (feste Allowlist) @@ -39,7 +40,7 @@ Heimnetz / VPN-Clients | Komponente | Außen erreichbar | Aufgabe | |---|---|---| -| WireGuard Gateway | VPN-Adresse, Port 8080/8081 | Tunnel und eng begrenzte TCP-Proxys | +| WireGuard Gateway | VPN-Adresse, feste Portmatrix | Tunnel und direkte TCP-Proxys für UI, API und Werkzeuge | | Open WebUI | nur Docker-intern | Chat-Oberfläche | | Profile Router | nur Docker-intern | OpenAI-API und Profilwahl | | Profile Controller | nein | startet ausschließlich fest erlaubte Profile | @@ -47,7 +48,7 @@ Heimnetz / VPN-Clients | XTTS-v2 | nein | primäre deutsche/englische Text-to-Speech-Ausgabe auf RTX 3060 | | TTS-Gateway | nein | serialisiert XTTS, segmentiert Sprachwechsel und fällt auf Piper zurück | | Piper | nein | CPU-basierte Text-to-Speech-Rückfallebene | -| MCP-Tool-Stack | nein | voneinander getrennte Werkzeugbereiche | +| MCP-Tool-Stack | über feste VPN-Ports | voneinander getrennte Werkzeugbereiche für OpenWebUI, Pi und Hermes | | SearXNG/TinySearch | nein | private Suche, Crawl4AI-Extraktion und lokales Reranking | Nur der Profile Controller erhält den Docker-Socket. Der Router erhält weder @@ -90,7 +91,7 @@ Ultra bleibt für maximalen Kontext bewusst text-only. - Docker-Netze liegen ausschließlich unter `172.30.0.0/16`. - Open WebUI und Router besitzen keine Docker-Host-Portfreigabe. - Der Gateway lauscht in seinem eigenen Namespace auf der Fritz-VPN-IP und - leitet nur 8080/8081 zu den internen Diensten weiter. + leitet die dokumentierte Portmatrix zu UI, API, TTS und MCPs weiter. - Quellrouting schickt `172.30.10.0/24` und `172.30.50.0/24` zum Gateway; Regeln für `172.30.0.0/16` bewahren rein internen Docker-Verkehr. - Die verschlüsselten äußeren Gateway-Pakete sind eng von diesen Quellregeln @@ -132,12 +133,11 @@ werden eindeutig buchstabiert. ## Zentrale MCP-Werkzeugebene -Werkzeuge werden nicht in llama.cpp eingebaut. Sie laufen als eigene, -zentrale MCP-Container. Open WebUI greift intern darauf zu. Für externe Clients -wie Hermes wird später ein authentifizierter MCP-Gateway über WireGuard -vorgeschaltet; die unauthentifizierten internen Ports werden niemals direkt -veröffentlicht. So können alle Oberflächen dieselben geprüften Werkzeuge -verwenden, ohne Secrets zu duplizieren. +Werkzeuge werden nicht in llama.cpp eingebaut. Sie laufen als eigene, zentrale +MCP-Container. Open WebUI greift intern darauf zu; Pi, Hermes und andere +Clients verwenden ihre festen Ports direkt auf Athenas WireGuard-Adresse. Ein +zusätzliches MCP-Gateway ist nicht erforderlich. So können alle Oberflächen +dieselben Werkzeuge verwenden, ohne Secrets zu duplizieren. Die Trenneinheit ist **ein Container pro Fachbereich und Vertrauensstufe** – nicht ein Container pro einzelner Funktion und nicht ein gemeinsamer @@ -153,7 +153,7 @@ Open WebUI ── internes Netz ───────────┬── web-m └── unraid-mcp-read Hermes Agent ─ WireGuard ─┐ -weitere MCP-Clients ──────┴── mcp-gateway (später) ── dasselbe interne Netz +Pi / weitere MCP-Clients ─┴── feste VPN-Ports 8201-8208 ── MCP-Container ``` | Container | Werkzeugbereich | Standardrecht | @@ -169,8 +169,6 @@ weitere MCP-Clients ──────┴── mcp-gateway (später) ── das | `unraid-mcp-read` | System-, Container- und begrenzte Logdiagnose | nur lesen | | `unraid-mcp-admin` | eng definierte Verwaltungsaktionen | bewusst aktivieren | | `sandbox-mcp` | temporäre Code- und Dateiarbeit | isolierter Arbeitsraum | -| `mcp-gateway` | Auth, Routing, Limits und Werkzeugauswahl | keine Fach-Secrets | - Read- und Write-Instanzen dürfen dasselbe Image verwenden, laufen aber mit unterschiedlichen Tokens, Netzwerkzugriffen und Werkzeug-Allowlisten. Der Gateway besitzt keine HA-, ARR- oder Unraid-Secrets. Er authentifiziert Clients, diff --git a/docs/DISASTER_RECOVERY.md b/docs/DISASTER_RECOVERY.md index ad826f0..37409f7 100644 --- a/docs/DISASTER_RECOVERY.md +++ b/docs/DISASTER_RECOVERY.md @@ -116,8 +116,10 @@ laufen, sondern alle fachlichen Funktionen geprüft wurden. ## Phase F – Sicherheitsprüfung -- [ ] Port 8080/8081 an der physischen Hostadresse nicht erreichbar -- [ ] beide Ports über die Fritz-VPN-Adresse erreichbar +- [ ] alle Anwendungsports aus `VPN_SERVICE_PORTS.md` an der physischen + Hostadresse nicht erreichbar +- [ ] OpenWebUI, Router und alle gestarteten MCPs über die Fritz-VPN-Adresse + erreichbar - [ ] gestopptes WireGuard-Gateway blockiert Container-Egress - [ ] Hilfsports nur localhost - [ ] Router nur aus erlaubtem Netz erreichbar diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index b51612b..8f3dd0b 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -180,9 +180,11 @@ Auf einer frischen Open-WebUI-Datenbank werden die internen MCP-Adressen über `TOOL_SERVER_CONNECTIONS` vorbelegt. Bei einer übernommenen Datenbank müssen die Einträge einmal unter **Admin-Einstellungen → Externe Werkzeuge** geprüft oder importiert werden. Die Endpunkte stehen in `platform/mcp/README.md`. -Kein MCP-Port wird auf dem Host veröffentlicht. Externe Clients wie Hermes -benötigen später den authentifizierten WireGuard-Gateway und dürfen nicht -direkt auf das interne Werkzeugnetz zugreifen. +Kein MCP-Port wird auf der physischen Universitätsadresse veröffentlicht. +OpenWebUI nutzt intern weiterhin die Docker-Namen; Pi, Hermes und andere +Clients greifen direkt über die festen WireGuard-Adressen aus +[VPN_SERVICE_PORTS.md](VPN_SERVICE_PORTS.md) zu. Ein zusätzliches MCP-Gateway +oder ein weiterer Auth-Layer innerhalb des Heim-VPNs ist nicht vorgesehen. Die vollständige Wiederherstellung einschließlich OpenWebUI, MCP-Secrets und Navidrome/Last.fm ist unter diff --git a/docs/QWEN_OPERATOR_CONTEXT.md b/docs/QWEN_OPERATOR_CONTEXT.md index 6022abd..70f0ad1 100644 --- a/docs/QWEN_OPERATOR_CONTEXT.md +++ b/docs/QWEN_OPERATOR_CONTEXT.md @@ -129,7 +129,8 @@ Docker-Netze verwenden ausschließlich `172.30.0.0/16`. Wichtige Netze: Open WebUI und Router haben keine normalen Host-Portfreigaben. Der WireGuard-Gateway-Container beendet den Fritzbox-Clienttunnel und veröffentlicht -innerhalb des VPN nur Open WebUI auf Port 8080 und die Router-API auf Port 8081. +innerhalb des VPN OpenWebUI, Router, TTS und die festen MCP-Ports aus +`VPN_SERVICE_PORTS.md`. Die KI- und Werkzeugcontainer erreichen Heimnetz und Internet über diesen Gateway. Quellrouting sorgt dafür, dass sie bei Tunnelausfall nicht über das Universitätsgateway ausweichen. Das gewünschte Verhalten ist fail-closed. @@ -227,8 +228,9 @@ Fallback, internem Endpunkt, reproduzierbarer Version und Hörtest aus. ## 9. MCP-Werkzeuge MCP-Werkzeuge gehören nicht in llama.cpp-Startparameter. Jeder Fachbereich -läuft in einem getrennten Container mit eigener Secret-Datei und minimalem -Netzzugriff. Kein MCP-Port wird am Host veröffentlicht. +läuft in einem getrennten Container mit eigener Secret-Datei. Auf der +Universitätsadresse wird kein MCP-Port veröffentlicht; über die +WireGuard-Adresse sind alle Fach-MCPs direkt erreichbar. | Bereich | Aufgabe | Rechte | |---|---|---| diff --git a/docs/SECURITY.md b/docs/SECURITY.md index eeb8357..a25b16b 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -3,8 +3,9 @@ ## Netzgrenze - Open WebUI und Router veröffentlichen keinerlei Host-Ports. -- Ein dedizierter WireGuard-Container stellt auf seiner VPN-Adresse nur 8080 - und 8081 bereit. +- Ein dedizierter WireGuard-Container stellt OpenWebUI, Router und die + Werkzeugdienste direkt auf seiner VPN-Adresse bereit. Die verbindliche + Portmatrix steht in [VPN_SERVICE_PORTS.md](VPN_SERVICE_PORTS.md). - Die egressfähigen Docker-Netze verwenden eigene Routingtabellen. - Heimnetz- und optionaler Internetverkehr laufen über WireGuard. - Die Tabellen zeigen ausschließlich zum Gateway-Container und besitzen keine @@ -22,13 +23,14 @@ physischen Schnittstelle erreichbar. - Profile Controller: einzige Socket-Ausnahme; feste Profile und nur List/Start/Stop, keine frei wählbaren Images, Befehle oder Mounts. - Open WebUI: einziges persistentes Chat-Volume. -- MCP-Fachcontainer: intern, getrennte Secrets und keine Host-Ports. +- MCP-Fachcontainer: intern verbunden und über feste WireGuard-Ports direkt + für OpenWebUI, Pi, Hermes und andere Heim-VPN-Clients erreichbar. - TinySearch/SearXNG: intern, Suchanfragen ohne Chatverlauf. llama.cpp bekommt weder MCP-Konfiguration noch HA-, ARR- oder Unraid-Secrets. -Open WebUI kennt nur interne MCP-URLs; Authentisierung zu den Zielsystemen -findet im jeweiligen Fachcontainer statt. Externe MCP-Clients werden erst über -einen authentifizierten WireGuard-Gateway zugelassen. +Open WebUI kann weiterhin die internen MCP-Namen verwenden. Andere Clients +nutzen ohne zusätzliches Gateway die festen MCP-Ports der WireGuard-Adresse. +Authentisierung zu den Zielsystemen findet im jeweiligen Fachcontainer statt. Ein Docker-Socket bleibt grundsätzlich privilegiert. Der Controller reduziert die erreichbare Funktion stark, ersetzt aber keine zusätzliche Socket-Proxy- diff --git a/docs/VPN_SERVICE_PORTS.md b/docs/VPN_SERVICE_PORTS.md new file mode 100644 index 0000000..a3d28bc --- /dev/null +++ b/docs/VPN_SERVICE_PORTS.md @@ -0,0 +1,37 @@ +# Dienste direkt über das Heim-VPN + +Athena behandelt die von der Fritzbox zugewiesene WireGuard-Adresse als ihr +normales Anwendungsnetz. OpenWebUI, die Router-API und die nützlichen +Werkzeugdienste sind dort direkt erreichbar. Auf der physischen +Universitätsadresse werden diese Ports nicht veröffentlicht. + +Aktuelle VPN-Adresse: `192.168.1.212` + +| Port | Dienst | Adresse | +|---:|---|---| +| 22 | SSH zum Athena-Host | `ssh root@192.168.1.212` | +| 8080 | OpenWebUI | `http://192.168.1.212:8080` | +| 8081 | OpenAI-kompatible Router-API | `http://192.168.1.212:8081/v1` | +| 8085 | TTS-Gateway | `http://192.168.1.212:8085` | +| 8091 | Piper direkt | `http://192.168.1.212:8091` | +| 8092 | XTTS direkt | `http://192.168.1.212:8092` | +| 8201 | Athena Platform Context MCP | `http://192.168.1.212:8201/mcp` | +| 8202 | Athena Operator MCP | `http://192.168.1.212:8202/mcp` | +| 8203 | Web-MCP | `http://192.168.1.212:8203/mcp` | +| 8204 | GitHub-MCP | `http://192.168.1.212:8204/mcp` | +| 8205 | Home-Assistant-MCP | `http://192.168.1.212:8205/mcp` | +| 8206 | ARR-MCP | `http://192.168.1.212:8206/mcp` | +| 8207 | Navidrome-MCP | `http://192.168.1.212:8207/mcp` | +| 8208 | Unraid-SSH-MCP, falls aktiviert | `http://192.168.1.212:8208/mcp` | +| 8210 | SearXNG-Diagnoseoberfläche | `http://192.168.1.212:8210` | +| 8211 | TinySearch-MCP direkt | `http://192.168.1.212:8211/mcp` | + +Pi, Hermes und andere MCP-Clients tragen diese URLs direkt ein. Ein +zusätzliches MCP-Gateway ist nicht erforderlich. Nicht gestartete optionale +Container führen am jeweiligen Port lediglich zu einer nicht erreichbaren +Verbindung; nach ihrem Start funktioniert derselbe Port automatisch. + +Die Portweiterleitungen laufen ausschließlich im Netzwerk-Namespace des +WireGuard-Containers und binden explizit an dessen VPN-Adresse. Deshalb sind +sie nicht über `172.21.117.202` erreichbar. SSH bleibt davon unabhängig auch +auf der Universitätsadresse zulässig. diff --git a/docs/WIREGUARD_HOME_PEER.md b/docs/WIREGUARD_HOME_PEER.md index bee2a39..fb2e6f8 100644 --- a/docs/WIREGUARD_HOME_PEER.md +++ b/docs/WIREGUARD_HOME_PEER.md @@ -14,8 +14,10 @@ Verschlüsselung. Eine LAN-zu-LAN-Konfiguration ist für diesen Host nicht nöti Der Tunnel endet im Container `mike-ai-wireguard-gateway`. Nur dieser Container erhält `NET_ADMIN` und `/dev/net/tun`. Open WebUI und Router veröffentlichen -keine Host-Ports; der Gateway stellt ausschließlich Port 8080 und 8081 auf der -von der Fritzbox zugeteilten VPN-Adresse bereit. +keine Ports auf der physischen Hostadresse. Der Gateway stellt OpenWebUI, +Router und die Werkzeugdienste auf der von der Fritzbox zugeteilten +VPN-Adresse bereit. Die vollständige Liste steht in +[VPN_SERVICE_PORTS.md](VPN_SERVICE_PORTS.md). ## Split der Verantwortlichkeiten @@ -38,13 +40,13 @@ systemctl status mike-ai-container-vpn-guard Der Healthcheck verlangt einen Handshake, der jünger als drei Minuten ist. Open WebUI liegt unter `http://:8080`, der Router unter -`http://:8081`. An der physischen Standortadresse dürfen beide Ports -nicht antworten. +`http://:8081/v1`; die MCPs liegen auf 8201 bis 8208. An der +physischen Standortadresse dürfen diese Anwendungsports nicht antworten. ## Getestetes Verhalten am 22. August 2026 - Fritzbox-Handshake und Datenverkehr in beide Richtungen: erfolgreich -- Open WebUI und Router über die VPN-Adresse: HTTP 200 +- Open WebUI, Router und direkte MCP-Endpunkte über die VPN-Adresse: erreichbar - dieselben Ports über die physische Hostadresse: geschlossen - VPN-Gateway gestoppt: ausgehender Open-WebUI-Test blockiert (fail-closed) - Gateway erneut gestartet: automatischer aktueller Handshake diff --git a/platform/docker/wireguard-gateway/entrypoint.sh b/platform/docker/wireguard-gateway/entrypoint.sh index e619d0c..0108bfe 100644 --- a/platform/docker/wireguard-gateway/entrypoint.sh +++ b/platform/docker/wireguard-gateway/entrypoint.sh @@ -46,7 +46,7 @@ ip -4 route replace default dev wg0 ip -6 route replace default dev wg0 2>/dev/null || true cleanup() { - kill "${proxy_ui_pid:-}" "${proxy_router_pid:-}" "${proxy_ssh_pid:-}" 2>/dev/null || true + [ -z "${proxy_pids:-}" ] || kill $proxy_pids 2>/dev/null || true wg-quick down "$RUNTIME" 2>/dev/null || true } trap cleanup EXIT INT TERM @@ -58,20 +58,42 @@ iptables -A FORWARD -o wg0 -j ACCEPT iptables -A FORWARD -i wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE -# Nothing is published on the physical host. These listeners exist only in -# the WireGuard container namespace and forward VPN clients to internal names. -socat TCP-LISTEN:8080,bind=0.0.0.0,reuseaddr,fork TCP:open-webui:8080 & -proxy_ui_pid=$! -socat TCP-LISTEN:8081,bind=0.0.0.0,reuseaddr,fork TCP:router:8081 & -proxy_router_pid=$! - -# Emergency SSH path for unattended operation. Bind explicitly to WireGuard's -# IPv4 address, never to a Docker-facing interface or the physical host. The -# target is the host-side gateway of the fixed frontend bridge. Host sshd still -# enforces its normal key-only authentication policy. wg_ipv4=$(ip -4 -o address show dev wg0 | awk 'NR == 1 { split($4, address, "/"); print address[1] }') [ -n "$wg_ipv4" ] || { echo "WireGuard IPv4 address is missing" >&2; exit 1; } -socat TCP-LISTEN:22,bind="$wg_ipv4",reuseaddr,fork TCP:172.30.10.1:22 & -proxy_ssh_pid=$! -wait "$proxy_ui_pid" +# The VPN is Athena's normal application network. Nothing below is published +# on the physical university interface: every listener is bound inside this +# namespace to the Fritzbox-assigned WireGuard address. Clients on the home +# VPN may use OpenWebUI, the router and every useful MCP directly. +proxy_pids="" +start_proxy() { + listen_port=$1 + target=$2 + socat "TCP-LISTEN:${listen_port},bind=${wg_ipv4},reuseaddr,fork" "TCP:${target}" & + proxy_pids="$proxy_pids $!" +} + +start_proxy 22 172.30.10.1:22 +start_proxy 8080 open-webui:8080 +start_proxy 8081 router:8081 +start_proxy 8085 tts-gateway:8085 +start_proxy 8091 piper:8085 +start_proxy 8092 xtts:80 + +# MCP endpoints. Optional services keep their listener even while stopped and +# begin working automatically as soon as their container is started. +start_proxy 8201 mcp-platform-context:8000 +start_proxy 8202 mcp-athena-operator:8000 +start_proxy 8203 mcp-web:8000 +start_proxy 8204 mcp-github:8000 +start_proxy 8205 mcp-homeassistant:8000 +start_proxy 8206 mcp-arr:8000 +start_proxy 8207 mcp-navidrome:3000 +start_proxy 8208 mcp-unraid-ssh:8000 + +# Search backends are also directly available for diagnostics and alternative +# clients. Normal chat clients should prefer the MCP endpoint on 8203. +start_proxy 8210 searxng:8080 +start_proxy 8211 tinysearch:8000 + +wait $(printf '%s\n' "$proxy_pids" | awk '{print $2}') diff --git a/platform/mcp/README.md b/platform/mcp/README.md index f416f70..c05f385 100644 --- a/platform/mcp/README.md +++ b/platform/mcp/README.md @@ -104,7 +104,9 @@ oder ein anderes Werkzeug benötigt wird. ## Sicherheitsmodell -- Kein MCP-Port wird auf eine Host-Adresse veröffentlicht. +- Kein MCP-Port wird auf der physischen Universitätsadresse veröffentlicht. + Über Athenas WireGuard-Adresse sind die Fach-MCPs direkt auf den in + `docs/VPN_SERVICE_PORTS.md` dokumentierten Ports erreichbar. - Nur Clients im privaten Docker-Netz `mike-ai-tools` erreichen die Endpunkte. - Secrets bleiben in Dateien unter `/etc/mike-ai` und werden read-only eingehängt. Sie gehören weder in Git noch in OpenWebUI-Tooldefinitionen. diff --git a/platform/mcp/compose.yaml b/platform/mcp/compose.yaml index 947c2c6..6fc4624 100644 --- a/platform/mcp/compose.yaml +++ b/platform/mcp/compose.yaml @@ -141,9 +141,9 @@ services: MCP_TRANSPORT: http MCP_HTTP_EXPOSE: "true" MCP_HTTP_PORT: "3000" - # The endpoint is not published on the host. Host filtering still makes - # accidental access from any other Docker name fail closed. - MCP_HTTP_ALLOWED_HOSTS: "mike-ai-mcp-navidrome:3000,mike-ai-mcp-navidrome" + # OpenWebUI uses the Docker name; Pi/Hermes may reach the same endpoint + # directly through Athena's WireGuard address and VPN port 8207. + MCP_HTTP_ALLOWED_HOSTS: "mike-ai-mcp-navidrome:3000,mike-ai-mcp-navidrome,${VPN_SERVICE_IP:-192.168.1.212}:8207,${VPN_SERVICE_IP:-192.168.1.212}" WEBUI_ENABLED: "false" tmpfs: - /tmp:rw,noexec,nosuid,nodev,size=64m