Fix UI networking across gateway recreation
This commit is contained in:
@@ -31,10 +31,14 @@ werden keine zweiten Instanzen dieser Dienste angelegt.
|
||||
| `/etc/mike-ai` | lokale Konfiguration und Secrets, niemals Git |
|
||||
|
||||
Portainer läuft als separater, optionaler Verwaltungscontainer
|
||||
`mike-ai-portainer`, teilt den Netzwerk-Namespace des WireGuard-Gateways und
|
||||
ist unter `https://192.168.1.212:9443` erreichbar. Seine Einstellungen liegen
|
||||
im Docker-Volume `portainer_data`, das vom Athena-Backup mitgesichert wird.
|
||||
Portainer beobachtet beziehungsweise
|
||||
`mike-ai-portainer` im internen Frontend-Netz und ist ausschließlich über den
|
||||
namensbasierten Proxy des WireGuard-Gateways unter
|
||||
`https://192.168.1.212:9443` erreichbar. Das Dashboard verwendet denselben
|
||||
stabilen Aufbau auf Port 8099. Beide teilen ausdrücklich nicht den
|
||||
Netzwerk-Namespace des Gateway-Containers: Ein Recreate des Gateways kann sie
|
||||
dadurch nicht mehr in einem veralteten Namespace zurücklassen. Portainers
|
||||
Einstellungen liegen im Docker-Volume `portainer_data`, das vom Athena-Backup
|
||||
mitgesichert wird. Portainer beobachtet beziehungsweise
|
||||
verwaltet Docker, ist aber keine Abhängigkeit des Inferenz-Stacks.
|
||||
|
||||
## Standardbefehle
|
||||
|
||||
+2
-7
@@ -50,11 +50,6 @@ services:
|
||||
- /tmp:size=16m,mode=1777
|
||||
volumes:
|
||||
- "${WIREGUARD_CONFIG_FILE:-/etc/mike-ai/wireguard/fritz-athena.conf}:/run/secrets/fritz-athena.conf:ro"
|
||||
# Namespace-sharing services cannot publish ports themselves. The owner
|
||||
# must keep these bindings so a gateway recreation cannot hide their UIs.
|
||||
ports:
|
||||
- "8099:8099"
|
||||
- "9443:9443"
|
||||
networks:
|
||||
frontend:
|
||||
ipv4_address: 172.30.10.254
|
||||
@@ -843,7 +838,7 @@ services:
|
||||
image: mike-ai/llama-dashboard:local
|
||||
container_name: mike-ai-llama-dashboard
|
||||
restart: unless-stopped
|
||||
network_mode: "service:wireguard-gateway"
|
||||
networks: [frontend]
|
||||
gpus: all
|
||||
read_only: true
|
||||
tmpfs:
|
||||
@@ -884,7 +879,7 @@ services:
|
||||
image: ${PORTAINER_IMAGE:-portainer/portainer-ce@sha256:511f3f06c96fe3b993ebeaafde311c1959cae73a7ef825dba6397d51b450dffa}
|
||||
container_name: mike-ai-portainer
|
||||
restart: unless-stopped
|
||||
network_mode: "service:wireguard-gateway"
|
||||
networks: [frontend]
|
||||
command: [--no-setup-token]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
+14
-8
@@ -82,17 +82,23 @@ class RecoveryScriptTests(unittest.TestCase):
|
||||
for profile in ("fast", "medium", "large", "ultra", "uncensored"):
|
||||
self.assertIn(f"llama-{profile}", installer)
|
||||
|
||||
def test_gateway_consumers_are_stopped_before_gateway_recreation(self) -> None:
|
||||
def test_gateway_consumers_do_not_require_rebinding(self) -> None:
|
||||
manager = (ROOT / "manage.sh").read_text(encoding="utf-8")
|
||||
stop = 'stop llama-dashboard portainer'
|
||||
deploy = 'up -d --build'
|
||||
self.assertIn(stop, manager)
|
||||
self.assertLess(manager.index(stop), manager.index(deploy))
|
||||
installer = (ROOT / "install.sh").read_text(encoding="utf-8")
|
||||
self.assertNotIn('stop llama-dashboard portainer', manager)
|
||||
self.assertNotIn('stop llama-dashboard portainer', installer)
|
||||
self.assertNotIn('force-recreate llama-dashboard portainer', manager)
|
||||
|
||||
def test_gateway_owns_shared_ui_ports_and_portainer_backup(self) -> None:
|
||||
def test_gateway_proxies_stable_ui_services_and_portainer_backup(self) -> None:
|
||||
compose = (ROOT / "compose.yaml").read_text(encoding="utf-8")
|
||||
self.assertIn('"8099:8099"', compose)
|
||||
self.assertIn('"9443:9443"', compose)
|
||||
gateway = (ROOT / "platform/docker/wireguard-gateway/entrypoint.sh").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
self.assertNotIn('network_mode: "service:wireguard-gateway"', compose)
|
||||
self.assertNotIn('"8099:8099"', compose)
|
||||
self.assertNotIn('"9443:9443"', compose)
|
||||
self.assertIn('start_proxy 8099 llama-dashboard:8099', gateway)
|
||||
self.assertIn('start_proxy 9443 portainer:9443', gateway)
|
||||
self.assertIn('portainer-data:/backup/volumes/portainer-data:ro', compose)
|
||||
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ flowchart LR
|
||||
H --> X[Nginx-Proxy-Manager-MCP]
|
||||
U --> M[Media-Tools<br/>ffmpeg / ffprobe / yt-dlp]
|
||||
|
||||
W[WireGuard-Gateway<br/>Athena] --- R
|
||||
W --- B[Athena Dashboard :8099]
|
||||
W --- PRT[Portainer :9443<br/>optionale Docker-Ansicht]
|
||||
W --- O[Athena Operator]
|
||||
W[WireGuard-Gateway<br/>Athena] -->|DNS-Proxy| R
|
||||
W -->|DNS-Proxy :8099| B[Athena Dashboard<br/>internes Frontend-Netz]
|
||||
W -->|DNS-Proxy :9443| PRT[Portainer<br/>internes Frontend-Netz]
|
||||
W -->|DNS-Proxy| O[Athena Operator]
|
||||
K[Backup alle 5 Stunden] --> DATA[/data und /etc/mike-ai]
|
||||
```
|
||||
|
||||
@@ -34,6 +34,9 @@ flowchart LR
|
||||
- **MUA** verwaltet Unraid. **Athena Operator** bleibt auf den Athena-Host
|
||||
begrenzt.
|
||||
- Der Router ist die einzige Modelladresse, die Hermes kennen muss.
|
||||
- Dashboard und Portainer besitzen eigene Netzwerk-Namespaces. Das
|
||||
WireGuard-Gateway löst ihre stabilen Compose-Dienstnamen bei jeder
|
||||
Verbindung neu auf; seine konkrete Container-ID ist damit irrelevant.
|
||||
|
||||
## Dynamische Qwen-Profile
|
||||
|
||||
|
||||
@@ -517,7 +517,6 @@ build_and_start() {
|
||||
llama-fast llama-medium llama-beta1 llama-large llama-ultra llama-uncensored
|
||||
docker compose --env-file "$SECRETS_DIR/stack.env" --profile image create image-worker
|
||||
docker volume inspect portainer_data >/dev/null 2>&1 || docker volume create portainer_data >/dev/null
|
||||
docker compose --env-file "$SECRETS_DIR/stack.env" stop llama-dashboard portainer
|
||||
docker compose --env-file "$SECRETS_DIR/stack.env" up -d --build \
|
||||
wireguard-gateway qwen3-tts piper tts-gateway profile-controller router llama-dashboard portainer backup
|
||||
if [[ ${WIREGUARD_MODE:-container} == container ]]; then
|
||||
|
||||
@@ -51,24 +51,10 @@ case "$command" in
|
||||
shift
|
||||
[[ $# -eq 0 ]] || { echo "core akzeptiert keine weiteren Services" >&2; exit 2; }
|
||||
run "$ROOT_DIR/platform/mcp/install-tools.sh"
|
||||
# Release the old gateway namespace (and its fixed network addresses)
|
||||
# before replacing its owner. Otherwise Docker can strand the host with
|
||||
# the old namespace still held by these two consumers.
|
||||
run "${compose[@]}" stop llama-dashboard portainer
|
||||
run "${compose[@]}" up -d --build \
|
||||
wireguard-gateway piper xtts tts-gateway profile-controller router llama-dashboard portainer backup
|
||||
else
|
||||
rebind_gateway=false
|
||||
for service in "$@"; do
|
||||
[[ $service == wireguard-gateway ]] && rebind_gateway=true
|
||||
done
|
||||
if [[ $rebind_gateway == true ]]; then
|
||||
run "${compose[@]}" stop llama-dashboard portainer
|
||||
fi
|
||||
run "${compose[@]}" up -d --build --no-deps "$@"
|
||||
if [[ $rebind_gateway == true ]]; then
|
||||
run "${compose[@]}" up -d --no-deps --force-recreate llama-dashboard portainer
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
purge-legacy)
|
||||
|
||||
@@ -77,6 +77,8 @@ start_proxy 22 172.30.10.1:22
|
||||
start_proxy 8081 router:8081
|
||||
start_proxy 8085 tts-gateway:8085
|
||||
start_proxy 8091 piper:8085
|
||||
start_proxy 8099 llama-dashboard:8099
|
||||
start_proxy 8202 mcp-athena-operator:8000
|
||||
start_proxy 9443 portainer:9443
|
||||
|
||||
wait $(printf '%s\n' "$proxy_pids" | awk '{print $2}')
|
||||
|
||||
@@ -37,6 +37,13 @@ for name in \
|
||||
done
|
||||
pass "Athena-Kerndienste sind gesund"
|
||||
|
||||
for name in mike-ai-llama-dashboard mike-ai-portainer; do
|
||||
network_mode=$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$name" 2>/dev/null || true)
|
||||
[[ $network_mode != container:* ]] || \
|
||||
fail "$name teilt noch einen fluechtigen Container-Netzwerk-Namespace"
|
||||
done
|
||||
pass "Dashboard und Portainer besitzen stabile Netzwerk-Namespaces"
|
||||
|
||||
active_llama=$(docker ps --format '{{.Names}}' | \
|
||||
grep -Ec '^mike-ai-llama-(fast|medium|beta1|large|ultra|uncensored)$' || true)
|
||||
[[ $active_llama -eq 1 ]] || fail "$active_llama aktive llama-Profile (erwartet: 1)"
|
||||
|
||||
Reference in New Issue
Block a user