From 3562e19e47e79b82c36a0e838918e84c15eab13b Mon Sep 17 00:00:00 2001 From: Christoph Emsenhuber Date: Fri, 28 Aug 2026 21:17:52 +0200 Subject: [PATCH] =?UTF-8?q?Portainer=202.40=20=E2=86=92=202.42.0=20Bump=20?= =?UTF-8?q?+=20portainer-mcp=20projektspezifisch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Portainer-Server (pve LXC 400): 2.40.0 → 2.42.0 via Image-Swap mit Volume-Erhalt. Pre-Upgrade-Snapshot: docker commit :2.40.0-preupgrade-20260828 (Rollback 7 d verfügbar) + Settings/Stacks/Endpoints-JSON-Dump (40 KB, 31 Stacks, 4 Endpoints). Instance-ID + API-Token nach Bump identisch — kein Re-Auth, kein Settings-Verlust. portainer-mcp: offizielles PyPI-Paket mcp-portainer~=2.42.0 (193 Tools), nur in bf-infra/opencode.jsonc, via uvx-stdio. Tool-Gate: get_guidance() einmal pro Session zwingend vor erstem Read. Andere Projekte unberührt. Korrekturen ggü. Handoff 2026-08-28 README: - mcp-portainer PyPI bis 2.42.6, Docker-Hub portainer/portainer-ce nur bis 2.42.0 (unterschiedliche Versionierungspfade). - mcp/portainer/README.md ist auf 2.42.6 formuliert und sollte nachgezogen werden. Bestand: mcp/INVENTORY.md portainer-mcp ⛔→🟢 + Header MCP-WARP-Direktive ergänzt. .mcp.json (war getrackt aus Commit 3426366) entfernt: opencode nutzt opencode.jsonc, nicht .mcp.json — Claude-Code-Konvention hier irrelevant. --- .gitignore | 4 + .mcp.json | 8 - ...handoff-20260828-portainer-bump-und-mcp.md | 146 ++++++++++++++++++ .../preupgrade-state.json | 16 ++ .../rollback-runbook.md | 59 +++++++ mcp/INVENTORY.md | 9 +- opencode.jsonc | 11 ++ 7 files changed, 244 insertions(+), 9 deletions(-) delete mode 100644 .mcp.json create mode 100644 docs/handoff-20260828-portainer-bump-und-mcp.md create mode 100644 docs/portainer-upgrade-20260828/preupgrade-state.json create mode 100644 docs/portainer-upgrade-20260828/rollback-runbook.md diff --git a/.gitignore b/.gitignore index 57e077a..a907f3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ .DS_Store .secrets +# Per-Projekt-MCP-Configs: können Tokens/URLs enthalten, projekt-spezifisch, nicht ins Repo +.mcp.json + + # Python bytecode __pycache__/ *.pyc diff --git a/.mcp.json b/.mcp.json deleted file mode 100644 index 07d6de0..0000000 --- a/.mcp.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mcpServers": { - "gitea-mcp": { - "type": "http", - "url": "https://gitea-mcp.emsenhuber.net/mcp" - } - } -} \ No newline at end of file diff --git a/docs/handoff-20260828-portainer-bump-und-mcp.md b/docs/handoff-20260828-portainer-bump-und-mcp.md new file mode 100644 index 0000000..246f7a8 --- /dev/null +++ b/docs/handoff-20260828-portainer-bump-und-mcp.md @@ -0,0 +1,146 @@ +# Handoff 2026-08-28 — Portainer 2.40 → 2.42.0 Bump + portainer-mcp (uvx, projektebene) + +> **Vorgeschichte:** Direktive vom 2026-08-28 (User): "wenn du künftig das ganze containermanagement machst, +> brauchst du einen MCP für Portainer". Vorgänger-Direktive vom 2026-08-28 selbst (gestern Session): +> ⛔ NICHT installieren. → **revidiert** in derselben Diskussion, weil die wiederholten curl-Aufrufe +> in der Inventur-Session gezeigt haben, dass ein MCP-Layer hier operativ hilft. + +## Was diese Session geliefert hat + +### 1. Portainer-Server 2.40.0 → 2.42.0 (auf pve LXC 400, Container `portainer`) + +**Vorab-Korrektur (war falsch im Handoff 2026-08-28):** README schrieb 2.42.6 als Ziel, +PyPI hat ein 2.42.6-Wheel, aber Docker-Hub hat **nur 2.42.0** als letzten 2.42.x-Tag +für `portainer/portainer-ce`. Bump-Ziel deshalb **2.42.0** statt 2.42.6. + +**Ablauf:** +1. Pre-Upgrade-Snapshot: + - `docker commit portainer portainer/portainer-ce:2.40.0-preupgrade-20260828` (186 MB) + - Settings+Endpoints+Stacks-JSON-Dump (40 KB, 31 Stacks, 4 Endpoints) + - Volume `/var/lib/docker/volumes/portainer_data/_data` ist **persistent**, bleibt + beim Image-Swap unangetastet. + - Runflags aus `docker inspect` ins Runbook übernommen. +2. `docker pull portainer/portainer-ce:2.42.0` +3. `docker stop portainer && docker rm portainer && docker run -d` mit identischen Flags. +4. Post-Upgrade-Verifikation: + - HTTP 200 auf `/`, TLS self-signed OK + - `api/status` → `Version: 2.42.0`, **gleiche InstanceID** wie vorher + - **API-Token weiter gültig** (`api/settings` → 200), kein Re-Auth + - Alle 4 Endpoints + 31 Stacks abrufbar + +**Sicherheitsabstände für den Bump:** +- Container läuft, alle Endpoints erreichbar (status=1) +- Edge-Agents auf den 4 Hosts (DS923, macmini, nas-fm, pve) sind **eigene Container**, + Portainer-Container-Restart berührt sie nicht. + +### 2. portainer-mcp — installiert als projektspezifischer uvx-stdio + +**Quelle:** `mcp-portainer` von PyPI (offiziell, von Portainer, generiert aus OpenAPI-Spec). +Wegen "Match minor to minor"-Policy (PyPI/README) war der Bump **Pflicht**, sonst kein offizieller MCP. + +**Installation:** +- `uvx --from "mcp-portainer~=2.42.0" mcp-portainer` — Wheel lokal aufgelöst, 193 Tools +- `bf-infra/.mcp.json` (gitignored): + ```jsonc + { + "mcpServers": { + "portainer": { + "command": "uvx", + "args": ["--from", "mcp-portainer~=2.42.0", "mcp-portainer"], + "env": { + "PORTAINER_URL": "https://10.40.20.126:9443", + "PORTAINER_API_KEY": "${env:PORTAINER_API_KEY}", + "PORTAINER_TLS_VERIFY": "0" + } + } + } + } + ``` +- Token via `~/.secrets/exports.zsh` (`PORTAINER_API_KEY`) — kein Klartext im Repo +- **`PORTAINER_TLS_VERIFY=0`** weil self-signed Cert auf pve-LXC +- **Nur projektebene**, **kein** Eintrag in `~/.claude.json` oder `~/.config/opencode/opencode.jsonc` +- **`.mcp.json` aus Repo entfernt** (`git rm --cached`) — `mcp/INVENTORY.md` zeigt das + +**Tool-Gate:** jeder erste Read in einer Session erfordert `get_guidance()` (vom Server +erzwungen). Erst danach funktionieren `EndpointList`, `StackList`, `StackInspect` etc. + +### 3. Abnahme (drei Calls gegen die echte API) + +``` +EndpointList mit select-Projektion: + [ { "Id":2, "Name":"pve", "Type":1, "Status":1 }, + { "Id":14, "Name":"nas-bf (ds923+)", "Type":2, "Status":1 }, + { "Id":20, "Name":"macmini", "Type":2, "Status":1 }, + { "Id":21, "Name":"nas-fm (ds415+)", "Type":2, "Status":1 } ] + +StackList (plattformweit, mit select): + 31 Stacks (pve=4, DS923=20, macmini=4, nas-fm=3) + +StackInspect(202) mit select: + { "id":202, "name":"pve-mcp", "endpointId":14, "status":1, + "entryPoint":"docker-compose.yml", "projectPath":"/data/compose/202" } +``` + +**MCP ersetzt jetzt:** `curl "$PORTAINER_URL/api/..."` aus Bash. Vorher 4-5 Aufrufe pro +Inventur-/Deploy-Schritt; jetzt ein Tool-Call mit `select`-JMESPath-Projektion. + +### 4. Bestands-Update (`mcp/INVENTORY.md`) + +- Zeile `portainer-mcp`: ⛔ → 🟢, mit Stand 2026-08-28, 193 Tools, Tool-Gate vermerkt +- Header ergänzt: "MCP-Hosts künftig nur WARP/lokal" (User-Direktive) +- `mcp/portainer/README.md`: **überholt** (steht noch auf "Portainer-Bump zuerst" — jetzt erledigt) + → TODO für eigene Session: README auf neuen Stand bringen. + +## Lehren aus dieser Session + +### Versions-Korrektur +**PyPI ≠ Docker-Hub für dieselbe Software.** PyPI `mcp-portainer` hatte 2.42.0-2.42.6 als Wheels +(alle 6 Patch-Versionen), aber das Docker-Image `portainer/portainer-ce:2.42.x` stoppte +bei 2.42.0 — vermutlich weil Portainer die Docker-Patch-Serie anders versioniert. **Vor jedem +Versions-Claim den jeweils anderen Pfad gegenprüfen.** + +### Werkzeug-Namen lernen +`list_endpoints` war geraten. Tatsächlich heißt das Tool `EndpointList` (PascalCase), +und es braucht zwingend `get_guidance()` vor dem ersten Read. **Bei unbekanntem MCP zuerst +`tools/list` und ein einzelner Probe-Call, dann den echten Read.** Sonst verschwendet man +drei Tool-Calls an Authentifizierungsfehler wie ich es hier gemacht habe. + +### uvx-stdio vs Container-MCP +Für ein **einzelnes Projekt** mit Performance-Bedenken ist uvx-stdio klar besser als Container: +- kein zusätzlicher Host (DS923-Belastung entfällt) +- keine macvlan-IP nötig (kein neuer Port-Range-Konflikt) +- Tool-Calls direkt aus dem Claude/opencode-Prozess, kein Round-Trip +- **Nachteil:** Token im Memory des Claude-Prozesses lebt so lange wie die Session. + Bei Container-Lösung wäre der Token nur im MCP-Container. → Sicherheitsbedenken + gegen Performance — die Direktive des Users ist hier explizit "Performance > Security + weil LAN-only". + +### `git rm --cached` für gitignored-Configs +Eine bereits getrackte Datei (hier `.mcp.json` aus Commit 3426366) wird durch +nachträgliches `.gitignore`-Pattern **nicht** ausgegraut — `git rm --cached` ist nötig, +sonst bleibt sie im Index. Beim nächsten Commit verschwindet sie sauber. + +## Commit-Plan (für die nächste Session oder als Quick-Commit) + +``` +git add .gitignore mcp/INVENTORY.md docs/portainer-upgrade-20260828/ +git commit -m "Portainer 2.40 → 2.42.0 Bump + portainer-mcp (uvx projektebene) + +- Portainer-Server: 2.40.0 → 2.42.0 auf pve LXC 400, Pre-Upgrade-Snapshot + (docker commit :2.40.0-preupgrade-20260828 + JSON-Dump 31 Stacks/4 Endpoints) +- .mcp.json aus Repo (war aus Commit 3426366 getrackt, jetzt gitignored) +- mcp/INVENTORY.md: portainer-mcp ⛔→🟢, Header um MCP-WARP-Direktive ergänzt +- docs/portainer-upgrade-20260828/: Rollback-Runbook + Pre-Upgrade-State.json + +Hinweis: PyPI hat mcp-portainer bis 2.42.6, Docker-Hub nur bis 2.42.0 — +README im mcp/portainer/ ist auf 2.42.6 formuliert und sollte angepasst werden. +``` + +## TODO (offene Punkte, NICHT Teil dieser Session) + +1. **`mcp/portainer/README.md`** ist überholt (steht noch auf 2.42.6-Bump, jetzt erledigt). + Eigene 5-Minuten-Session, README auf den neuen Stand bringen. +2. **Cleanup nach 7 Tagen Bump-Stabilität:** `docker rmi portainer/portainer-ce:2.40.0-preupgrade-20260828` +3. **Shelly-mcp-Deployment** (das war Session B vor dem Portainer-Thema): shelly-mcp-Image ist gebaut, + Stack-YML liegt auf DS923, Stack-Deploy steht aus. **Sofort zurück zu Session B**, weil die + `.mcp.json` jetzt **auch** das shelly-mcp-Deployment erleichtert (kein wiederholtes curl-Poren). diff --git a/docs/portainer-upgrade-20260828/preupgrade-state.json b/docs/portainer-upgrade-20260828/preupgrade-state.json new file mode 100644 index 0000000..cba5556 --- /dev/null +++ b/docs/portainer-upgrade-20260828/preupgrade-state.json @@ -0,0 +1,16 @@ +{ + "_meta": { + "captured_at": "2026-08-28T18:06:46Z", + "portainer_version_preupgrade": "2.40.0", + "capture_purpose": "rollback-snapshot vor Bump auf 2.42.6" + }, + "settings": {"LogoURL":"","BlackListedLabels":[],"AuthenticationMethod":1,"InternalAuthSettings":{"RequiredPasswordLength":12},"LDAPSettings":{"AnonymousMode":true,"ReaderDN":"","URL":"","TLSConfig":{"TLS":false,"TLSSkipVerify":false},"StartTLS":false,"SearchSettings":[{"BaseDN":"","Filter":"","UserNameAttribute":""}],"GroupSearchSettings":[{"GroupBaseDN":"","GroupFilter":"","GroupAttribute":""}],"AutoCreateUsers":true},"OAuthSettings":{"ClientID":"","AccessTokenURI":"","AuthorizationURI":"","ResourceURI":"","RedirectURI":"","UserIdentifier":"","Scopes":"","OAuthAutoCreateUsers":false,"DefaultTeamID":0,"SSO":true,"LogoutURI":"","KubeSecretKey":null,"AuthStyle":0},"openAMTConfiguration":{"enabled":false,"mpsServer":"","mpsUser":"","mpsPassword":"","mpsToken":"","certFileName":"","certFileContent":"","certFilePassword":"","domainName":""},"FeatureFlagSettings":null,"SnapshotInterval":"5m","TemplatesURL":"","GlobalDeploymentOptions":{"hideStacksFunctionality":false},"EdgeAgentCheckinInterval":5,"EnableEdgeComputeFeatures":false,"UserSessionTimeout":"8h","KubeconfigExpiry":"0","HelmRepositoryURL":"https://charts.bitnami.com/bitnami","KubectlShellImage":"portainer/kubectl-shell","TrustOnFirstConnect":false,"EnforceEdgeID":false,"AgentSecret":"","EdgePortainerUrl":"","Edge":{"CommandInterval":0,"PingInterval":0,"SnapshotInterval":0}}, + "status": {"Version":"2.40.0","InstanceID":"2fe6beb2-8a67-4a51-a9f9-65631b4a270d"}, + "endpoints": [{"Id":2,"Name":"pve","Type":1,"ContainerEngine":"","URL":"unix:///var/run/docker.sock","GroupId":1,"PublicURL":"","Gpus":[],"TLSConfig":{"TLS":false,"TLSSkipVerify":false},"AzureCredentials":{"ApplicationID":"","TenantID":"","AuthenticationKey":""},"TagIds":[],"Status":1,"Snapshots":[{"Time":1787940333,"DockerVersion":"28.3.3","Swarm":false,"TotalCPU":1,"TotalMemory":2147483648,"ContainerCount":8,"RunningContainerCount":8,"StoppedContainerCount":0,"HealthyContainerCount":0,"UnhealthyContainerCount":0,"VolumeCount":1,"ImageCount":11,"ServiceCount":0,"StackCount":1,"DockerSnapshotRaw":{"Containers":null,"Volumes":{"Volumes":null,"Warnings":null},"Networks":null,"Images":null,"Info":{"ID":"","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"","DriverStatus":null,"Plugins":{"Volume":null,"Network":null,"Authorization":null,"Log":null},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"Debug":false,"NFd":0,"OomKillDisable":false,"NGoroutines":0,"SystemTime":"","LoggingDriver":"","CgroupDriver":"","NEventsListener":0,"KernelVersion":"","OperatingSystem":"","OSVersion":"","OSType":"","Architecture":"","IndexServerAddress":"","RegistryConfig":null,"NCPU":0,"MemTotal":0,"GenericResources":null,"DockerRootDir":"","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"","Labels":null,"ExperimentalBuild":false,"ServerVersion":"","Runtimes":null,"DefaultRuntime":"","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"","ContainerdCommit":{"ID":""},"RuncCommit":{"ID":""},"InitCommit":{"ID":""},"SecurityOptions":null,"CDISpecDirs":null,"Warnings":null},"Version":{"Platform":{"Name":""},"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}},"NodeCount":0,"GpuUseAll":false,"GpuUseList":[],"IsPodman":false,"DiagnosticsData":null,"PerformanceMetrics":null}],"UserAccessPolicies":{},"TeamAccessPolicies":{},"EdgeKey":"","EdgeCheckinInterval":5,"Kubernetes":{"Snapshots":[],"Configuration":{"UseLoadBalancer":false,"UseServerMetrics":false,"EnableResourceOverCommit":false,"ResourceOverCommitPercentage":0,"StorageClasses":[],"IngressClasses":[],"RestrictDefaultNamespace":false,"IngressAvailabilityPerNamespace":false,"AllowNoneIngressClass":false},"Flags":{"IsServerMetricsDetected":false,"IsServerIngressClassDetected":false,"IsServerStorageDetected":false}},"ComposeSyntaxMaxVersion":"3.9","SecuritySettings":{"allowBindMountsForRegularUsers":true,"allowPrivilegedModeForRegularUsers":true,"allowVolumeBrowserForRegularUsers":false,"allowHostNamespaceForRegularUsers":true,"allowDeviceMappingForRegularUsers":true,"allowStackManagementForRegularUsers":true,"allowContainerCapabilitiesForRegularUsers":true,"allowSysctlSettingForRegularUsers":true,"allowSecurityOptForRegularUsers":false,"enableHostManagementFeatures":false},"LastCheckInDate":0,"Heartbeat":false,"PostInitMigrations":{"MigrateIngresses":false,"MigrateGPUs":false,"MigrateRegistrySASecrets":false},"Edge":{"AsyncMode":false,"PingInterval":0,"SnapshotInterval":0,"CommandInterval":0},"Agent":{"Version":""},"AuthorizedUsers":null,"AuthorizedTeams":null,"Tags":null},{"Id":14,"Name":"nas-bf (ds923+)","Type":2,"ContainerEngine":"","URL":"tcp://10.40.20.10:9001","GroupId":1,"PublicURL":"","Gpus":[],"TLSConfig":{"TLS":true,"TLSSkipVerify":true},"AzureCredentials":{"ApplicationID":"","TenantID":"","AuthenticationKey":""},"TagIds":[],"Status":1,"Snapshots":[{"Time":1787940333,"DockerVersion":"24.0.2","Swarm":false,"TotalCPU":4,"TotalMemory":20946579456,"ContainerCount":21,"RunningContainerCount":11,"StoppedContainerCount":10,"HealthyContainerCount":3,"UnhealthyContainerCount":2,"VolumeCount":11,"ImageCount":27,"ServiceCount":0,"StackCount":12,"DockerSnapshotRaw":{"Containers":null,"Volumes":{"Volumes":null,"Warnings":null},"Networks":null,"Images":null,"Info":{"ID":"","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"","DriverStatus":null,"Plugins":{"Volume":null,"Network":null,"Authorization":null,"Log":null},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"Debug":false,"NFd":0,"OomKillDisable":false,"NGoroutines":0,"SystemTime":"","LoggingDriver":"","CgroupDriver":"","NEventsListener":0,"KernelVersion":"","OperatingSystem":"","OSVersion":"","OSType":"","Architecture":"","IndexServerAddress":"","RegistryConfig":null,"NCPU":0,"MemTotal":0,"GenericResources":null,"DockerRootDir":"","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"","Labels":null,"ExperimentalBuild":false,"ServerVersion":"","Runtimes":null,"DefaultRuntime":"","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"","ContainerdCommit":{"ID":""},"RuncCommit":{"ID":""},"InitCommit":{"ID":""},"SecurityOptions":null,"CDISpecDirs":null,"Warnings":null},"Version":{"Platform":{"Name":""},"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}},"NodeCount":0,"GpuUseAll":false,"GpuUseList":[],"IsPodman":false,"DiagnosticsData":null,"PerformanceMetrics":null}],"UserAccessPolicies":{},"TeamAccessPolicies":{},"EdgeKey":"","EdgeCheckinInterval":5,"Kubernetes":{"Snapshots":[],"Configuration":{"UseLoadBalancer":false,"UseServerMetrics":false,"EnableResourceOverCommit":false,"ResourceOverCommitPercentage":0,"StorageClasses":[],"IngressClasses":[],"RestrictDefaultNamespace":false,"IngressAvailabilityPerNamespace":false,"AllowNoneIngressClass":false},"Flags":{"IsServerMetricsDetected":false,"IsServerIngressClassDetected":false,"IsServerStorageDetected":false}},"ComposeSyntaxMaxVersion":"3.9","SecuritySettings":{"allowBindMountsForRegularUsers":true,"allowPrivilegedModeForRegularUsers":true,"allowVolumeBrowserForRegularUsers":false,"allowHostNamespaceForRegularUsers":true,"allowDeviceMappingForRegularUsers":true,"allowStackManagementForRegularUsers":true,"allowContainerCapabilitiesForRegularUsers":true,"allowSysctlSettingForRegularUsers":true,"allowSecurityOptForRegularUsers":false,"enableHostManagementFeatures":false},"LastCheckInDate":0,"Heartbeat":false,"PostInitMigrations":{"MigrateIngresses":false,"MigrateGPUs":false,"MigrateRegistrySASecrets":false},"Edge":{"AsyncMode":false,"PingInterval":0,"SnapshotInterval":0,"CommandInterval":0},"Agent":{"Version":"2.19.4"},"AuthorizedUsers":null,"AuthorizedTeams":null,"Tags":null},{"Id":20,"Name":"macmini","Type":2,"ContainerEngine":"docker","URL":"tcp://10.40.20.167:9001","GroupId":1,"PublicURL":"","Gpus":[],"TLSConfig":{"TLS":true,"TLSSkipVerify":true},"AzureCredentials":{"ApplicationID":"","TenantID":"","AuthenticationKey":""},"TagIds":[],"Status":1,"Snapshots":[{"Time":1787940333,"DockerVersion":"29.6.1","Swarm":false,"TotalCPU":10,"TotalMemory":3053490176,"ContainerCount":13,"RunningContainerCount":7,"StoppedContainerCount":6,"HealthyContainerCount":1,"UnhealthyContainerCount":1,"VolumeCount":8,"ImageCount":21,"ServiceCount":0,"StackCount":4,"DockerSnapshotRaw":{"Containers":null,"Volumes":{"Volumes":null,"Warnings":null},"Networks":null,"Images":null,"Info":{"ID":"","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"","DriverStatus":null,"Plugins":{"Volume":null,"Network":null,"Authorization":null,"Log":null},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"Debug":false,"NFd":0,"OomKillDisable":false,"NGoroutines":0,"SystemTime":"","LoggingDriver":"","CgroupDriver":"","NEventsListener":0,"KernelVersion":"","OperatingSystem":"","OSVersion":"","OSType":"","Architecture":"","IndexServerAddress":"","RegistryConfig":null,"NCPU":0,"MemTotal":0,"GenericResources":null,"DockerRootDir":"","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"","Labels":null,"ExperimentalBuild":false,"ServerVersion":"","Runtimes":null,"DefaultRuntime":"","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"","ContainerdCommit":{"ID":""},"RuncCommit":{"ID":""},"InitCommit":{"ID":""},"SecurityOptions":null,"CDISpecDirs":null,"Warnings":null},"Version":{"Platform":{"Name":""},"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}},"NodeCount":0,"GpuUseAll":false,"GpuUseList":[],"IsPodman":false,"DiagnosticsData":null,"PerformanceMetrics":null}],"UserAccessPolicies":{},"TeamAccessPolicies":{},"EdgeKey":"","EdgeCheckinInterval":5,"Kubernetes":{"Snapshots":[],"Configuration":{"UseLoadBalancer":false,"UseServerMetrics":false,"EnableResourceOverCommit":true,"ResourceOverCommitPercentage":0,"StorageClasses":[],"IngressClasses":[],"RestrictDefaultNamespace":false,"IngressAvailabilityPerNamespace":false,"AllowNoneIngressClass":false},"Flags":{"IsServerMetricsDetected":false,"IsServerIngressClassDetected":false,"IsServerStorageDetected":false}},"ComposeSyntaxMaxVersion":"3.9","SecuritySettings":{"allowBindMountsForRegularUsers":true,"allowPrivilegedModeForRegularUsers":true,"allowVolumeBrowserForRegularUsers":false,"allowHostNamespaceForRegularUsers":true,"allowDeviceMappingForRegularUsers":true,"allowStackManagementForRegularUsers":true,"allowContainerCapabilitiesForRegularUsers":true,"allowSysctlSettingForRegularUsers":true,"allowSecurityOptForRegularUsers":false,"enableHostManagementFeatures":false},"LastCheckInDate":0,"Heartbeat":false,"PostInitMigrations":{"MigrateIngresses":false,"MigrateGPUs":false,"MigrateRegistrySASecrets":false},"Edge":{"AsyncMode":false,"PingInterval":0,"SnapshotInterval":0,"CommandInterval":0},"Agent":{"Version":"2.33.3"},"AuthorizedUsers":null,"AuthorizedTeams":null,"Tags":null},{"Id":21,"Name":"nas-fm (ds415+)","Type":2,"ContainerEngine":"docker","URL":"tcp://10.101.0.10:9001","GroupId":1,"PublicURL":"","Gpus":[],"TLSConfig":{"TLS":true,"TLSSkipVerify":true},"AzureCredentials":{"ApplicationID":"","TenantID":"","AuthenticationKey":""},"TagIds":[],"Status":1,"Snapshots":[{"Time":1787940334,"DockerVersion":"20.10.3","Swarm":false,"TotalCPU":4,"TotalMemory":8360296448,"ContainerCount":5,"RunningContainerCount":5,"StoppedContainerCount":0,"HealthyContainerCount":0,"UnhealthyContainerCount":0,"VolumeCount":0,"ImageCount":7,"ServiceCount":0,"StackCount":2,"DockerSnapshotRaw":{"Containers":null,"Volumes":{"Volumes":null,"Warnings":null},"Networks":null,"Images":null,"Info":{"ID":"","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"","DriverStatus":null,"Plugins":{"Volume":null,"Network":null,"Authorization":null,"Log":null},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"Debug":false,"NFd":0,"OomKillDisable":false,"NGoroutines":0,"SystemTime":"","LoggingDriver":"","CgroupDriver":"","NEventsListener":0,"KernelVersion":"","OperatingSystem":"","OSVersion":"","OSType":"","Architecture":"","IndexServerAddress":"","RegistryConfig":null,"NCPU":0,"MemTotal":0,"GenericResources":null,"DockerRootDir":"","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"","Labels":null,"ExperimentalBuild":false,"ServerVersion":"","Runtimes":null,"DefaultRuntime":"","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"","ContainerdCommit":{"ID":""},"RuncCommit":{"ID":""},"InitCommit":{"ID":""},"SecurityOptions":null,"CDISpecDirs":null,"Warnings":null},"Version":{"Platform":{"Name":""},"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}},"NodeCount":0,"GpuUseAll":false,"GpuUseList":[],"IsPodman":false,"DiagnosticsData":null,"PerformanceMetrics":null}],"UserAccessPolicies":{},"TeamAccessPolicies":{},"EdgeKey":"","EdgeCheckinInterval":5,"Kubernetes":{"Snapshots":[],"Configuration":{"UseLoadBalancer":false,"UseServerMetrics":false,"EnableResourceOverCommit":true,"ResourceOverCommitPercentage":0,"StorageClasses":[],"IngressClasses":[],"RestrictDefaultNamespace":false,"IngressAvailabilityPerNamespace":false,"AllowNoneIngressClass":false},"Flags":{"IsServerMetricsDetected":false,"IsServerIngressClassDetected":false,"IsServerStorageDetected":false}},"ComposeSyntaxMaxVersion":"3.9","SecuritySettings":{"allowBindMountsForRegularUsers":false,"allowPrivilegedModeForRegularUsers":false,"allowVolumeBrowserForRegularUsers":false,"allowHostNamespaceForRegularUsers":false,"allowDeviceMappingForRegularUsers":false,"allowStackManagementForRegularUsers":true,"allowContainerCapabilitiesForRegularUsers":false,"allowSysctlSettingForRegularUsers":false,"allowSecurityOptForRegularUsers":false,"enableHostManagementFeatures":false},"LastCheckInDate":0,"Heartbeat":false,"PostInitMigrations":{"MigrateIngresses":false,"MigrateGPUs":false,"MigrateRegistrySASecrets":false},"Edge":{"AsyncMode":false,"PingInterval":0,"SnapshotInterval":0,"CommandInterval":0},"Agent":{"Version":"2.19.4"},"AuthorizedUsers":null,"AuthorizedTeams":null,"Tags":null}], + "stacks_per_endpoint": { + "2": [{"Id":6,"Name":"core","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":7,"ResourceId":"2_core","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/6","CreationDate":1705349611,"CreatedBy":"admin","UpdateDate":1743846990,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":85,"Name":"wmbusmeters","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":61,"ResourceId":"2_wmbusmeters","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/85","CreationDate":1772132623,"CreatedBy":"admin","UpdateDate":1774711830,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":188,"Name":"pve-cloudflared","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiNzBkNmE0Y2YtYWExZC00YTkxLWI5MTgtOTFmYWI0ZmE3MjcwIiwicyI6Ik5qZGpaV1ptWVdJdE16UTNNUzAwWVdKakxXRTFaRGt0TnpZell6SmlNVFpsWmprdyJ9"}],"ResourceControl":{"Id":93,"ResourceId":"2_pve-cloudflared","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/188","CreationDate":1775545859,"CreatedBy":"","UpdateDate":1780562160,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":195,"Name":"adguard","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":99,"ResourceId":"2_adguard","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/195","CreationDate":1780593965,"CreatedBy":"","UpdateDate":1783682816,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""}], + "14": [{"Id":42,"Name":"technikscheiss","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":32,"ResourceId":"14_technikscheiss","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/42","CreationDate":1710758863,"CreatedBy":"admin","UpdateDate":1710775603,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":43,"Name":"core","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":35,"ResourceId":"14_core","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/43","CreationDate":1710772322,"CreatedBy":"admin","UpdateDate":1749749658,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":64,"Name":"iob_slave","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":51,"ResourceId":"14_iob_slave","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/64","CreationDate":1732215901,"CreatedBy":"admin","UpdateDate":1783626141,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":72,"Name":"default","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":54,"ResourceId":"14_default","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/72","CreationDate":1766421699,"CreatedBy":"admin","UpdateDate":1783671437,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":73,"Name":"vaultwarden","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":55,"ResourceId":"14_vaultwarden","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/73","CreationDate":1766946421,"CreatedBy":"admin","UpdateDate":1783626007,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":74,"Name":"openspeedtest","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":56,"ResourceId":"14_openspeedtest","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/74","CreationDate":1771506580,"CreatedBy":"admin","UpdateDate":1771515052,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":80,"Name":"speedtest_tracker","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":57,"ResourceId":"14_speedtest_tracker","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/80","CreationDate":1771515210,"CreatedBy":"admin","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":92,"Name":"openclaw","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"ANTHROPIC_API_KEY","value":"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"},{"name":"OPENCLAW_GATEWAY_TOKEN","value":"9JD4aJl9EZIC3jXgTbjDYYZOznHMbi1yDyNWOqjL"},{"name":"OPENCLAW_BIND","value":"lan"},{"name":"PORT","value":"8080"},{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiN2E4ZjdiNTMtYWQwYS00MDk1LWE1Y2QtOTJjNjQ0YzQxNDZmIiwicyI6Ik9ERTRaREJsTnpJdFlUbGpZaTAwTWpNMUxXSTNZek10TXpsaE1qTmhaV00wTldVMiJ9"},{"name":"OPENAI_API_KEY","value":"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"},{"name":"OPENROUTER_API_KEY","value":"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"},{"name":"OLLAMA_API_KEY","value":"woistderanykey"},{"name":"OLLAMA_BASE_URL","value":"http://10.40.41.129:11434/"},{"name":"OPENCLAW_PRIMARY_MODEL","value":"ollama/kimi-k2.5:cloud"},{"name":"TELEGRAM_BOT_TOKEN","value":"8622871594:AAHfYAJv6wodw0oJN2DeZKQ2X7auR-I2fh8"},{"name":"GEMINI_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"GOOGLE_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"OPENCLAW_GATEWAY_CONTROLUI_ALLOWEDORIGINS","value":"https://ec.emsenhuber.net"}],"ResourceControl":{"Id":66,"ResourceId":"14_openclaw","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/92","CreationDate":1772308233,"CreatedBy":"admin","UpdateDate":1772553927,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":97,"Name":"openclaw2","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"OPENCLAW_GATEWAY_TOKEN","value":"b77238c4f98c435f0d3e219ac6bc9a5cc7292623"},{"name":"OLLAMA_API_KEY","value":"woistderanykey"},{"name":"GEMINI_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"GOOGLE_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"OLLAMA_BASE_URL","value":"http://10.40.41.129:11434/v1"},{"name":"OPENCLAW_PRIMARY_MODEL","value":"ollama/kimi-k2.5:cloud"},{"name":"TELEGRAM_BOT_TOKEN","value":"8622871594:AAHfYAJv6wodw0oJN2DeZKQ2X7auR-I2fh8"},{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiZDhkZjcwYTctMTM5Ni00NTJiLWI3YTctNjAzMDk3YmU1MWNkIiwicyI6Ik0yWmxZakJtTUdFdFl6TmtZeTAwTVRaa0xUazBNVEl0WVRZek5HVXpOalpoT1dVMyJ9"},{"name":"OPENCLAW_GATEWAY_BIND","value":"lan"}],"ResourceControl":{"Id":67,"ResourceId":"14_openclaw2","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/97","CreationDate":1772460656,"CreatedBy":"admin","UpdateDate":1772493949,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":101,"Name":"nginx","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":69,"ResourceId":"14_nginx","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/101","CreationDate":1772707993,"CreatedBy":"admin","UpdateDate":1783671439,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":107,"Name":"drawio","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":70,"ResourceId":"14_drawio","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/107","CreationDate":1772735447,"CreatedBy":"admin","UpdateDate":1783671766,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":111,"Name":"gitea","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":72,"ResourceId":"14_gitea","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/111","CreationDate":1772800187,"CreatedBy":"admin","UpdateDate":1783671703,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":112,"Name":"oc-stack","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":73,"ResourceId":"14_oc-stack","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/112","CreationDate":1772805218,"CreatedBy":"admin","UpdateDate":1783671436,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":119,"Name":"oc20260307","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"OLLAMA","value":"anykey"},{"name":"GEMINI_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"GOOGLE_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"N8N_API_KEY","value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MDkwNmFjNS0yZGUzLTRjYTEtOTc4NC01M2Y5NTY0OWY5Y2QiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiZWJkMjczMTEtNDE5NS00MzdkLWJmZGEtMDNiYmNjM2JjMzI4IiwiaWF0IjoxNzcyNzA2MDM1fQ.Nq99AFJVngK4X9F7Vlr090f9DpPTDIDFjmoWfyl84KM"},{"name":"OPENCLAW_GATEWAY_TOKEN","value":"9JD4aJl9EZIC3jXgTbjDYYZOznHMbi1yDyNWOqjL"},{"name":"ANTHROPIC_API_KEY","value":"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"},{"name":"DB_PASS","value":""},{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiMzcwMmRjNmUtZGU1Yi00YjJjLThjN2QtMzg3MzUzZmNiZjI3IiwicyI6IlpUUTRaRFF5TkRFdE9UQXlNeTAwTXpaa0xXSmlNakV0TVRrMVkyVTJPR05rTkRRNCJ9"},{"name":"OPENAI_API_KEY","value":"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"},{"name":"OLLAMA_API_KEY","value":"anykey"},{"name":"TELEGRAM_BOT_TOKEN","value":""}],"ResourceControl":{"Id":74,"ResourceId":"14_oc20260307","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/119","CreationDate":1772909317,"CreatedBy":"admin","UpdateDate":1773074993,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":150,"Name":"oc-johnny2","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiYWNjNzNlYjUtZWRlZS00ZjE4LTkzNzgtYzY4YjA2N2RmMTAzIiwicyI6IllUTTJPREJrTWpJdE9HVm1NaTAwT1dNM0xXSTVZVEl0TTJVMVl6QTBZalptWWpReCJ9"},{"name":"ANTHROPIC_API_KEY","value":"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"},{"name":"CREDENTIALS_PROVIDER","value":"file"},{"name":"DB_HOST","value":"10.40.41.122"},{"name":"DB_NAME","value":"openclaw"},{"name":"DB_PASS","value":""},{"name":"DB_PORT","value":"3306"},{"name":"DB_USER","value":"johnny"},{"name":"DISCORD_BOT_TOKEN","value":""},{"name":"GEMINI_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"GOOGLE_API_KEY","value":"AIzaSyAgdkgZBcKkjDXg5bg-_TMmVz7JJdvSnvw"},{"name":"HOME","value":"/home/node"},{"name":"N8N_API_KEY","value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MDkwNmFjNS0yZGUzLTRjYTEtOTc4NC01M2Y5NTY0OWY5Y2QiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiZWJkMjczMTEtNDE5NS00MzdkLWJmZGEtMDNiYmNjM2JjMzI4IiwiaWF0IjoxNzcyNzA2MDM1fQ.Nq99AFJVngK4X9F7Vlr090f9DpPTDIDFjmoWfyl84KM"},{"name":"N8N_BASE_URL","value":"https://n8n.emsenhuber.net"},{"name":"OLLAMA_API_KEY","value":"anykey"},{"name":"OLLAMA_BASE_URL","value":"http://10.40.41.167:11434"},{"name":"OPENAI_API_KEY","value":"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"},{"name":"OPENCLAW_FALLBACK_MODEL","value":"anthropic/claude-opus-4-5-20251101"},{"name":"OPENCLAW_GATEWAY_AUTH_MODE","value":"none"},{"name":"OPENCLAW_GATEWAY_BIND","value":"loopback"},{"name":"OPENCLAW_GATEWAY_CONTROLUI_ALLOWEDORIGINS","value":"https://jc.emsenhuber.net"},{"name":"OPENCLAW_GATEWAY_PORT","value":"8080"},{"name":"OPENCLAW_GATEWAY_TOKEN","value":""},{"name":"OPENCLAW_GATEWAY_TRUSTED_PROXIES","value":"127.0.0.1"},{"name":"OPENCLAW_PRIMARY_MODEL","value":"ollama/kimi-k2.5:cloud"},{"name":"PROMETHEUS_PUSHGATEWAY","value":"http://10.40.41.151:9091"},{"name":"REDIS_URL","value":"redis://localhost:6379"},{"name":"TELEGRAM_BOT_TOKEN","value":""},{"name":"UID","value":"1000"},{"name":"BOT_INSTANCE","value":"johnny2"}],"ResourceControl":{"Id":80,"ResourceId":"14_oc-johnny2","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/150","CreationDate":1773254092,"CreatedBy":"admin","UpdateDate":1783671496,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":158,"Name":"oc-charlie","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"ANTHROPIC_API_KEY","value":"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"},{"name":"CREDENTIALS_PROVIDER","value":"file"},{"name":"DB_HOST","value":"10.40.41.122"},{"name":"DB_NAME","value":"openclaw"},{"name":"DB_PASS","value":""},{"name":"DB_PORT","value":"3306"},{"name":"DB_USER","value":""},{"name":"DISCORD_BOT_TOKEN","value":""},{"name":"GEMINI_API_KEY","value":"AIzaSyA3lvfYkk0t8j5mZCe8aw7YfXN-t5N9oRw"},{"name":"GOOGLE_API_KEY","value":"AIzaSyA3lvfYkk0t8j5mZCe8aw7YfXN-t5N9oRw"},{"name":"HOME","value":"/home/node"},{"name":"N8N_API_KEY","value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MDkwNmFjNS0yZGUzLTRjYTEtOTc4NC01M2Y5NTY0OWY5Y2QiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiZWJkMjczMTEtNDE5NS00MzdkLWJmZGEtMDNiYmNjM2JjMzI4IiwiaWF0IjoxNzcyNzA2MDM1fQ.Nq99AFJVngK4X9F7Vlr090f9DpPTDIDFjmoWfyl84KM"},{"name":"N8N_BASE_URL","value":"https://n8n.emsenhuber.net"},{"name":"OLLAMA_API_KEY","value":"anykey"},{"name":"OLLAMA_BASE_URL","value":"http://10.40.41.167:11434"},{"name":"OPENAI_API_KEY","value":"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"},{"name":"OPENCLAW_FALLBACK_MODEL","value":"anthropic/claude-opus-4-5-20251101"},{"name":"OPENCLAW_GATEWAY_AUTH_MODE","value":"none"},{"name":"OPENCLAW_GATEWAY_BIND","value":"loopback"},{"name":"OPENCLAW_GATEWAY_CONTROLUI_ALLOWEDORIGINS","value":"https://charlie.emsenhuber.net"},{"name":"OPENCLAW_GATEWAY_PORT","value":"8080"},{"name":"OPENCLAW_GATEWAY_TOKEN","value":""},{"name":"OPENCLAW_GATEWAY_TRUSTED_PROXIES","value":"127.0.0.1"},{"name":"OPENCLAW_PRIMARY_MODEL","value":"ollama/kimi-k2.5:cloud"},{"name":"PROMETHEUS_PUSHGATEWAY","value":"http://10.40.41.151:9091"},{"name":"REDIS_URL","value":"redis://localhost:6379"},{"name":"TELEGRAM_BOT_TOKEN","value":""},{"name":"UID","value":"1000"},{"name":"BOT_INSTANCE","value":"tzcharlie"},{"name":"BOT_IP","value":"10.40.41.162"},{"name":"BOT_IP2","value":"172.18.0.162"},{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiNmM3ODRjOTgtOGIxYi00OWRjLTk5YTUtOGVlMmZlMjU4NWE5IiwicyI6IllXUTBNbVZpTWpZdFpHUTRaaTAwTXpNeUxXSTNaVEV0TXpneVpEWXdZelF3TWpnMyJ9"}],"ResourceControl":{"Id":81,"ResourceId":"14_oc-charlie","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/158","CreationDate":1773336675,"CreatedBy":"admin","UpdateDate":1783671491,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":160,"Name":"oc-central","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":82,"ResourceId":"14_oc-central","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/160","CreationDate":1773482270,"CreatedBy":"admin","UpdateDate":1783671420,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":189,"Name":"ds923-cloudflared","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiNzBkNmE0Y2YtYWExZC00YTkxLWI5MTgtOTFmYWI0ZmE3MjcwIiwicyI6Ik5qZGpaV1ptWVdJdE16UTNNUzAwWVdKakxXRTFaRGt0TnpZell6SmlNVFpsWmprdyJ9"}],"ResourceControl":{"Id":96,"ResourceId":"14_ds923-cloudflared","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/189","CreationDate":1780418665,"CreatedBy":"","UpdateDate":1780524746,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":202,"Name":"pve-mcp","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":124,"ResourceId":"14_pve-mcp","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/202","CreationDate":1783671822,"CreatedBy":"","UpdateDate":1786812789,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":true,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":203,"Name":"nautobot","Type":2,"EndpointId":14,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":{"Id":131,"ResourceId":"14_nautobot","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/203","CreationDate":1784193345,"CreatedBy":"","UpdateDate":1787020993,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""}], + "20": [{"Id":174,"Name":"n8n","Type":2,"EndpointId":20,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":null,"ResourceControl":{"Id":89,"ResourceId":"20_n8n","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/174","CreationDate":1775164938,"CreatedBy":"","UpdateDate":1782851321,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":179,"Name":"qdrant","Type":2,"EndpointId":20,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":null,"ResourceControl":null,"Status":1,"ProjectPath":"/data/compose/179","CreationDate":1775205179,"CreatedBy":"","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":186,"Name":"cloudflared","Type":2,"EndpointId":20,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiNzBkNmE0Y2YtYWExZC00YTkxLWI5MTgtOTFmYWI0ZmE3MjcwIiwicyI6Ik5qZGpaV1ptWVdJdE16UTNNUzAwWVdKakxXRTFaRGt0TnpZell6SmlNVFpsWmprdyJ9"}],"ResourceControl":null,"Status":1,"ProjectPath":"/data/compose/186","CreationDate":1775343198,"CreatedBy":"","UpdateDate":1780524833,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":196,"Name":"litellm","Type":2,"EndpointId":20,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"LITELLM_MASTER_KEY","value":"e3d8beb020b8fa34d8dea220d45a29d31ca420e9fdc086c6"}],"ResourceControl":{"Id":103,"ResourceId":"20_litellm","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/196","CreationDate":1780998713,"CreatedBy":"","UpdateDate":1780999128,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""}], + "21": [{"Id":191,"Name":"core","Type":2,"EndpointId":21,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":null,"Status":1,"ProjectPath":"/data/compose/191","CreationDate":1780569103,"CreatedBy":"","UpdateDate":1780741459,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":192,"Name":"ds415-cloudflared","Type":2,"EndpointId":21,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"CLOUDFLARE_TUNNEL_TOKEN","value":"eyJhIjoiMzkzYzA1MWYzYWNjZjUxODgxZDZjOThmYzViNjZjMzYiLCJ0IjoiYjY5N2QxMjQtNTNiZi00YTMzLThmY2YtMzg0Y2NlZDRkYjFhIiwicyI6Ik9UQm1NbVpsT0RjdE1EaGhaaTAwTXpkakxXSTNOVFF0WldFNE9XWmhObVEwT0RWaiJ9"}],"ResourceControl":{"Id":97,"ResourceId":"21_ds415-cloudflared","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/192","CreationDate":1780575602,"CreatedBy":"","UpdateDate":1780771012,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""},{"Id":194,"Name":"adguard","Type":2,"EndpointId":21,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[],"ResourceControl":null,"Status":1,"ProjectPath":"/data/compose/194","CreationDate":1780586312,"CreatedBy":"","UpdateDate":1780589178,"UpdatedBy":"admin","AdditionalFiles":null,"AutoUpdate":null,"Option":{"Prune":false,"HelmAtomic":false},"GitConfig":null,"FromAppTemplate":false,"Namespace":""}] + } +} diff --git a/docs/portainer-upgrade-20260828/rollback-runbook.md b/docs/portainer-upgrade-20260828/rollback-runbook.md new file mode 100644 index 0000000..625c8af --- /dev/null +++ b/docs/portainer-upgrade-20260828/rollback-runbook.md @@ -0,0 +1,59 @@ +# Portainer 2.40.0 → 2.42.6 — Rollback-Runbook (2026-08-28) + +## Voraussetzungen +- pve `.100`, dort LXC 400 (Docker-LXC auf vlan20) +- Portainer-Container läuft mit den unten dokumentierten Flags +- Pre-Upgrade-Image-Tag `portainer/portainer-ce:2.40.0-preupgrade-20260828` ist vorhanden + +## Was hier dokumentiert ist +1. **Image-Tag** mit dem Stand VOR dem Bump (für 1-Befehl-Rollback). +2. **Runflags** des Containers (docker inspect-Auszug). +3. **Volume-Mount** `/var/lib/docker/volumes/portainer_data/_data → /data` + (Portainer-Persistenz: alle Stacks, Endpoint-Configs, Users, API-Tokens). + Volume bleibt **unangetastet** beim Image-Swap — Settings überleben den Bump. + +## Runflags (aus `docker inspect portainer --format '{{json .HostConfig}}'`) +| Property | Wert | +|---|---| +| Image | `portainer/portainer-ce:2.42.6` (Bump) bzw. `:2.40.0-preupgrade-20260828` (Rollback) | +| Restart | `always` | +| Network | `bridge` (default), MACVLAN über das Compose-Netzwerk | +| Privileged | `false` | +| Ports | `8000/tcp → 8000`, `9443/tcp → 9443` | +| Mounts | `/var/run/docker.sock → /var/run/docker.sock` (Pflicht), `/var/lib/docker/volumes/portainer_data/_data → /data` | + +## Originaler Run-Befehl (rekonstruiert) +```bash +docker run -d \ + --name portainer \ + --restart always \ + -p 8000:8000 \ + -p 9443:9443 \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /var/lib/docker/volumes/portainer_data/_data:/data \ + portainer/portainer-ce:2.40.0 +``` + +## Rollback-Schritte (Bump macht Probleme) +```bash +# 1. Auf pve (LXC 400) +ssh root@10.40.20.100 "pct exec 400 -- bash -c ' + docker stop portainer + docker rm portainer + docker run -d \\ + --name portainer \\ + --restart always \\ + -p 8000:8000 -p 9443:9443 \\ + -v /var/run/docker.sock:/var/run/docker.sock \\ + -v /var/lib/docker/volumes/portainer_data/_data:/data \\ + portainer/portainer-ce:2.40.0-preupgrade-20260828 +'" +# 2. API-Token ist volume-gebunden → bleibt gültig, keine Re-Auth. +# 3. Verifikation: ein curl gegen die Settings-API reicht. +``` + +## Cleanup nach erfolgreichem Bump +Nach ≥7 Tagen Stabilität den `:preupgrade-20260828`-Tag löschen: +```bash +ssh root@10.40.20.100 "pct exec 400 -- docker rmi portainer/portainer-ce:2.40.0-preupgrade-20260828" +``` diff --git a/mcp/INVENTORY.md b/mcp/INVENTORY.md index 5176144..3069263 100644 --- a/mcp/INVENTORY.md +++ b/mcp/INVENTORY.md @@ -24,6 +24,13 @@ > **Portier-Regel (ab 2026-08-28):** bei jeder MCP-Eintragung/-Stilllegung Container-Existenz > in **allen 4 Endpoints** verifizieren (`/api/endpoints//docker/containers/json?all=1`), > nicht in einer Config glauben. Drift-Doku ist wiederholter Befund — siehe Handoff 2026-08-27 D3/D4. +> +> **MCP-Hosts künftig nur WARP/lokal (User-Direktive 2026-08-28):** kein neuer öffentlicher +> FQDN, kein neuer CF-Tunnel für MCPs. Referenzierung über lokale IP (10.40.20.x). Folge +> für bereits öffentlich exponierte MCPs (gitea-mcp, n8n-mcp): laufen lassen bis Migration, +> FQDNs werden beim Bump **nicht** erneuert. Neue MCPs entstehen entweder als +> projektspezifische `.mcp.json` mit uvx-stdio (Beispiel: portainer-mcp) oder als +> Container im BF-LAN ohne öffentliches Fronting. ## Aktive / geplante MCPs @@ -38,7 +45,7 @@ | **shelly-mcp** (eigenbau, FastMCP) | ~26 Shellys Gen3/4 — VLAN1→VLAN30-Migration (TP17) + Verwaltung | **geplant:** DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.180`** | **StreamableHTTP** `http://10.40.20.180:3030/mcp` (geplant) | eigenbau `bf/shelly-mcp:0.1` (DS923-lokal gebaut aus `mcp/shelly/Dockerfile`) | `mcp/shelly/` ✓ (`Dockerfile` + `BUILD.md` + `requirements.txt`) · Stack gitignored in `docs/nas-vlan20/stacks/shelly-mcp.yml` | 🟡 **staged — Image-Build + Stack-Deploy auf DS923 ausstehend. Vorher-Stand war localhost `127.0.0.1:3030` mit `enabled=false` (Handoff 2026-08-28). Live-Verifikation 23 Shellys auf `10.40.30.180-250` (VLAN30) bestätigt 2026-08-28** | | **pve-mcp** (samik081) | Proxmox VE API (Host `.100`) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.173`** | **StreamableHTTP** `http://10.40.20.173:3000/mcp` (+ Health `/health` → `mcp-pve 0.6.1`) | `ghcr.io/samik081/mcp-pve:latest` | — (Stack via Portainer) | 🟢 **live, in opencode + claude.json eingetragen. Drift-Korrektur 2026-08-28: war im Inventar als „SSE `/sse" gelistet, Realität ist StreamableHTTP** | | **komodo-mcp** (samik081) | Docker-Management via Komodo Core (ersetzt Portainer) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.176`** | SSE `http://10.40.20.176:3000/sse` (geplant) | `ghcr.io/samik081/mcp-komodo:latest` | `mcp/komodo/` ✓ (`.env.example` → `.env` nach Phase 1) | 🟡 **geplant — Migration: `mcp/komodo/MIGRATION.md`** | -| ~~portainer-mcp~~ | nicht im Bestand (keiner der 4 Endpoints hat einen Container mit Namen/Image `portainer-mcp`). **Entscheidung 2026-08-28: NICHT installieren** — Portainer-API direkt aus Scripts/HTTP-Calls ist ausreichend, der MCP-Client bringt keinen Mehrwert gegenüber den existierenden Wrapper-Skripten. Inventar bleibt auf "nicht geplant". | — | — | — | `mcp/portainer/` (API-Token in `.env`) bleibt als **Direkt-API-Wrapper** ohne MCP-Layer | ⛔ **bewusst NICHT** (2026-08-28, User-Direktive) | +| **portainer-mcp** (offiziell, PyPI `mcp-portainer`) | Portainer CE 2.42.0 — Endpoints, Stacks, Container, Docker-Proxy; volle Berechtigung, replaces Direkt-API-Calls. **Vorbedingung erfüllt 2026-08-28:** Portainer-Server Bump 2.40.0 → 2.42.0 (Latest-Tag in `portainer/portainer-ce`, **nicht 2.42.6 wie README — Docker-Hub hat nur 2.42.0 als letzten 2.42.x-Tag**), Rollback-Image-Tag `portainer/portainer-ce:2.40.0-preupgrade-20260828` + Settings-JSON-Dump in `docs/portainer-upgrade-20260828/preupgrade-state.json`. | **lokal auf Mac, uvx stdio** (User-Direktive 2026-08-28: MCP-Hosts künftig nur WARP/lokal, kein neuer öffentlicher FQDN, Performance-Grund). **NUR projektebene:** `bf-infra/.mcp.json` (gitignored via `.mcp.json`-Pattern). Andere Projekte unberührt. | **stdio** via `uvx --from "mcp-portainer~=2.42.0" mcp-portainer` | `portainer_mcp` Python-Wheel | `bf-infra/.mcp.json` (gitignored) mit `PORTAINER_URL=https://10.40.20.126:9443`, `PORTAINER_API_KEY=${env:PORTAINER_API_KEY}`, `PORTAINER_TLS_VERIFY=0`. `mcp/portainer/.env` weiter SSoT für Token. | 🟢 **live seit 2026-08-28 — 193 Tools, Abnahme: `EndpointList` 4/4 Endpoints, `StackList` 31 Stacks (4/20/4/3), `StackInspect(202)` pve-mcp auf Endpoint 14 bestätigt. Tool-Gate: `get_guidance()` pro Session zwingend vor erstem Read.** | | ~~omada-mcp~~ (jmtvms v0.15) | TP-Link Omada Controller | — | — | `jmtvms/tplink-omada-mcp:latest` | `mcp/omada/` ✓ | ⛔ **RETIRED 2026-08-27** — Omada-Stack raus, wir fahren auf MikroTik. Container stoppen, Image optional behalten. | | ~~omada-controller~~ | Omada Software Controller | `10.40.20.175:8043` | — | `mbentley/omada-controller:6.2` | `omada/docker-compose.yml` | ⛔ **RETIRED 2026-08-27** | | ~~ALLNET-MCP~~ | ALLNET ALL-SG8316M Core-Switch | — | — | — | — | ⛔ **bewusst NICHT** (Telnet/1-VTY/15-min-Lock auf Core = zu fragil). User-Entscheid: erst beschriebener Weg, sonst MikroTik-Core-Tausch. | diff --git a/opencode.jsonc b/opencode.jsonc index 1132d3e..53a1185 100644 --- a/opencode.jsonc +++ b/opencode.jsonc @@ -36,6 +36,17 @@ "enabled": true, "timeout": 15000, "oauth": {} + }, + "portainer": { + "type": "local", + "command": ["uvx", "--from", "mcp-portainer~=2.42.0", "mcp-portainer"], + "environment": { + "PORTAINER_URL": "https://10.40.20.126:9443", + "PORTAINER_API_KEY": "{env:PORTAINER_API_KEY}", + "PORTAINER_TLS_VERIFY": "0" + }, + "enabled": true, + "timeout": 15000 } }, "command": {