Fix UI networking across gateway recreation
This commit is contained in:
1 parent
5e18b7776b
commit
eeebbd06eb
8 files changed
+40
-38
No files matched your search
@@ -31,10 +31,14 @@ werden keine zweiten Instanzen dieser Dienste angelegt.
|
|||||||
| `/etc/mike-ai` | lokale Konfiguration und Secrets, niemals Git |
|
| `/etc/mike-ai` | lokale Konfiguration und Secrets, niemals Git |
|
||||||
|
|
||||||
Portainer läuft als separater, optionaler Verwaltungscontainer
|
Portainer läuft als separater, optionaler Verwaltungscontainer
|
||||||
`mike-ai-portainer`, teilt den Netzwerk-Namespace des WireGuard-Gateways und
|
`mike-ai-portainer` im internen Frontend-Netz und ist ausschließlich über den
|
||||||
ist unter `https://192.168.1.212:9443` erreichbar. Seine Einstellungen liegen
|
namensbasierten Proxy des WireGuard-Gateways unter
|
||||||
im Docker-Volume `portainer_data`, das vom Athena-Backup mitgesichert wird.
|
`https://192.168.1.212:9443` erreichbar. Das Dashboard verwendet denselben
|
||||||
Portainer beobachtet beziehungsweise
|
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.
|
verwaltet Docker, ist aber keine Abhängigkeit des Inferenz-Stacks.
|
||||||
|
|
||||||
## Standardbefehle
|
## Standardbefehle
|
||||||
|
|||||||
+2
-7
@@ -50,11 +50,6 @@ services:
|
|||||||
- /tmp:size=16m,mode=1777
|
- /tmp:size=16m,mode=1777
|
||||||
volumes:
|
volumes:
|
||||||
- "${WIREGUARD_CONFIG_FILE:-/etc/mike-ai/wireguard/fritz-athena.conf}:/run/secrets/fritz-athena.conf:ro"
|
- "${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:
|
networks:
|
||||||
frontend:
|
frontend:
|
||||||
ipv4_address: 172.30.10.254
|
ipv4_address: 172.30.10.254
|
||||||
@@ -843,7 +838,7 @@ services:
|
|||||||
image: mike-ai/llama-dashboard:local
|
image: mike-ai/llama-dashboard:local
|
||||||
container_name: mike-ai-llama-dashboard
|
container_name: mike-ai-llama-dashboard
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
network_mode: "service:wireguard-gateway"
|
networks: [frontend]
|
||||||
gpus: all
|
gpus: all
|
||||||
read_only: true
|
read_only: true
|
||||||
tmpfs:
|
tmpfs:
|
||||||
@@ -884,7 +879,7 @@ services:
|
|||||||
image: ${PORTAINER_IMAGE:-portainer/portainer-ce@sha256:511f3f06c96fe3b993ebeaafde311c1959cae73a7ef825dba6397d51b450dffa}
|
image: ${PORTAINER_IMAGE:-portainer/portainer-ce@sha256:511f3f06c96fe3b993ebeaafde311c1959cae73a7ef825dba6397d51b450dffa}
|
||||||
container_name: mike-ai-portainer
|
container_name: mike-ai-portainer
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
network_mode: "service:wireguard-gateway"
|
networks: [frontend]
|
||||||
command: [--no-setup-token]
|
command: [--no-setup-token]
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /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"):
|
for profile in ("fast", "medium", "large", "ultra", "uncensored"):
|
||||||
self.assertIn(f"llama-{profile}", installer)
|
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")
|
manager = (ROOT / "manage.sh").read_text(encoding="utf-8")
|
||||||
stop = 'stop llama-dashboard portainer'
|
installer = (ROOT / "install.sh").read_text(encoding="utf-8")
|
||||||
deploy = 'up -d --build'
|
self.assertNotIn('stop llama-dashboard portainer', manager)
|
||||||
self.assertIn(stop, manager)
|
self.assertNotIn('stop llama-dashboard portainer', installer)
|
||||||
self.assertLess(manager.index(stop), manager.index(deploy))
|
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")
|
compose = (ROOT / "compose.yaml").read_text(encoding="utf-8")
|
||||||
self.assertIn('"8099:8099"', compose)
|
gateway = (ROOT / "platform/docker/wireguard-gateway/entrypoint.sh").read_text(
|
||||||
self.assertIn('"9443:9443"', compose)
|
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)
|
self.assertIn('portainer-data:/backup/volumes/portainer-data:ro', compose)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ flowchart LR
|
|||||||
H --> X[Nginx-Proxy-Manager-MCP]
|
H --> X[Nginx-Proxy-Manager-MCP]
|
||||||
U --> M[Media-Tools<br/>ffmpeg / ffprobe / yt-dlp]
|
U --> M[Media-Tools<br/>ffmpeg / ffprobe / yt-dlp]
|
||||||
|
|
||||||
W[WireGuard-Gateway<br/>Athena] --- R
|
W[WireGuard-Gateway<br/>Athena] -->|DNS-Proxy| R
|
||||||
W --- B[Athena Dashboard :8099]
|
W -->|DNS-Proxy :8099| B[Athena Dashboard<br/>internes Frontend-Netz]
|
||||||
W --- PRT[Portainer :9443<br/>optionale Docker-Ansicht]
|
W -->|DNS-Proxy :9443| PRT[Portainer<br/>internes Frontend-Netz]
|
||||||
W --- O[Athena Operator]
|
W -->|DNS-Proxy| O[Athena Operator]
|
||||||
K[Backup alle 5 Stunden] --> DATA[/data und /etc/mike-ai]
|
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
|
- **MUA** verwaltet Unraid. **Athena Operator** bleibt auf den Athena-Host
|
||||||
begrenzt.
|
begrenzt.
|
||||||
- Der Router ist die einzige Modelladresse, die Hermes kennen muss.
|
- 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
|
## Dynamische Qwen-Profile
|
||||||
|
|
||||||
|
|||||||
@@ -517,7 +517,6 @@ build_and_start() {
|
|||||||
llama-fast llama-medium llama-beta1 llama-large llama-ultra llama-uncensored
|
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 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 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 \
|
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
|
wireguard-gateway qwen3-tts piper tts-gateway profile-controller router llama-dashboard portainer backup
|
||||||
if [[ ${WIREGUARD_MODE:-container} == container ]]; then
|
if [[ ${WIREGUARD_MODE:-container} == container ]]; then
|
||||||
|
|||||||
@@ -51,24 +51,10 @@ case "$command" in
|
|||||||
shift
|
shift
|
||||||
[[ $# -eq 0 ]] || { echo "core akzeptiert keine weiteren Services" >&2; exit 2; }
|
[[ $# -eq 0 ]] || { echo "core akzeptiert keine weiteren Services" >&2; exit 2; }
|
||||||
run "$ROOT_DIR/platform/mcp/install-tools.sh"
|
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 \
|
run "${compose[@]}" up -d --build \
|
||||||
wireguard-gateway piper xtts tts-gateway profile-controller router llama-dashboard portainer backup
|
wireguard-gateway piper xtts tts-gateway profile-controller router llama-dashboard portainer backup
|
||||||
else
|
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 "$@"
|
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
|
fi
|
||||||
;;
|
;;
|
||||||
purge-legacy)
|
purge-legacy)
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ start_proxy 22 172.30.10.1:22
|
|||||||
start_proxy 8081 router:8081
|
start_proxy 8081 router:8081
|
||||||
start_proxy 8085 tts-gateway:8085
|
start_proxy 8085 tts-gateway:8085
|
||||||
start_proxy 8091 piper:8085
|
start_proxy 8091 piper:8085
|
||||||
|
start_proxy 8099 llama-dashboard:8099
|
||||||
start_proxy 8202 mcp-athena-operator:8000
|
start_proxy 8202 mcp-athena-operator:8000
|
||||||
|
start_proxy 9443 portainer:9443
|
||||||
|
|
||||||
wait $(printf '%s\n' "$proxy_pids" | awk '{print $2}')
|
wait $(printf '%s\n' "$proxy_pids" | awk '{print $2}')
|
||||||
@@ -37,6 +37,13 @@ for name in \
|
|||||||
done
|
done
|
||||||
pass "Athena-Kerndienste sind gesund"
|
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}}' | \
|
active_llama=$(docker ps --format '{{.Names}}' | \
|
||||||
grep -Ec '^mike-ai-llama-(fast|medium|beta1|large|ultra|uncensored)$' || true)
|
grep -Ec '^mike-ai-llama-(fast|medium|beta1|large|ultra|uncensored)$' || true)
|
||||||
[[ $active_llama -eq 1 ]] || fail "$active_llama aktive llama-Profile (erwartet: 1)"
|
[[ $active_llama -eq 1 ]] || fail "$active_llama aktive llama-Profile (erwartet: 1)"
|
||||||
|
|||||||
Reference in new issue
Block a user