Stack ai-cluster (openclaw, codex/planner/service-ops workery, redis, mosquitto) biega na VPS spoza GitOps, z /home/dockeruser/docker/ai-cluster/. Branch feat/vps-service-migration (862c04a) probowal wciagnac go do GitOps *w miejscu*, na VPS. Ten etap pomijamy: workloady sa compute'owe, VPS ma 4 GiB bez swapu i rolę ingressu, SOLARIA ma 64 GiB i GPU. Migrujemy od razu na SOLARIA, VPS zostaje samym NPM-em proxujacym po Tailscale. Zero deployu. Kontenery na VPS nietkniete — recon byl read-only (katalog nalezy do dockeruser, odczyt przez efemeryczny kontener z mountem :ro, bez dotykania dzialajacych kontenerow). Plan przelaczenia: services/ai-cluster/CUTOVER.md. Zrodla wciagniete do services/ai-cluster/src/ (openclaw, worker, mosquitto). Pominiete: .env i mosquitto/passwd (sekrety), start-codex.sh* (smiec spoza stacku), __pycache__. Ustalenia z reconu, ktore zmienily manifest z862c04a: - codex-worker/ na VPS to NIE osobny build context ani duplikat worker/ — to martwy 609-bajtowy prototyp na `requests` (biblioteka nie wystepuje w zadnym requirements.txt), bez Dockerfile'a i bez referencji w compose. Realny codex-worker buduje sie z ./worker (Dockerfile default). Nie przenoszony. - image: ai-cluster-* -> build: z src/openclaw i src/worker (3 Dockerfile'e nad jednym kontekstem: default/planner/service-ops). - openclaw: usuniete publish 0.0.0.0:8000 -> "100.100.231.104:8000:8000"; usunieta siec npm_default (nie istnieje na SOLARIA). - mosquitto: bind 100.95.58.48 -> 100.100.231.104. - mem_limity urealnione (256m workery/openclaw, 64m redis/mosquitto) i przeniesione do hosts/solaria/runtime/. Zmierzone RSS na VPS: workery 7-10 MiB, openclaw 24.6 MiB, redis 4.8, mosquitto 4.2 — limity to zapas ~10x, nie reakcja na presje. - healthcheck zostaje na python/urllib: obraz openclaw (python:3.12-slim) nie ma ani wget, ani curl — sprawdzone na zywym obrazie. - GATEWAY_BASE_URL http://piha:8080 -> http://100.108.208.3:8080. Tailscale DNS jest WYLACZONY na SOLARIA (`tailscale dns status` -> disabled), wiec zadna nazwa MagicDNS sie nie rozwiazuje. Na VPS bare `piha` tez nie rozwiazuje sie (rc=2), czyli ten default byl martwy juz tam. - telegram-bot nie przenoszony (na VPS nie biega zaden kontener). telegram_bot.py zostaje w src/, bo openclaw/Dockerfile go COPY-uje — bez niego build sie wywala. - sekrety wylacznie przez env_file /opt/homelab/config/ai-cluster/.env, zero interpolacji ${VAR:?} — stack nie zalezy od cwd deployu. service-ops-worker montuje ten katalog pod ta sama sciezka absolutna, bo compose waliduje env_file na etapie parsowania i inaczej `docker compose ps` w tym kontenerze padnie. - AGENT_ID zostaja `vps-*`: to cele routingu MQTT, nie hostnamey. Zmiana nazw lamie producentow adresujacych konkretnego agenta — osobne, skoordynowane zadanie. Konsumenci mosquitto do aktualizacji: w repo BRAK. chelsty (z2m, frigate, stability-agent) uzywaja wlasnego, host-networkowego brokera i musza zostac offline-first. Lista i sposob potwierdzenia klientow spoza repo — CUTOVER.md krok 5. DoD (docker build + smoke + pytest) swiadomie odroczone: zadanie zabrania budowania obrazow. Pokrywaja to kroki 1-3 CUTOVER.md, do wykonania w sesji cutoveru. Zweryfikowane tutaj: `docker compose config` z overrideem (rc=0, bindy host_ip, mem_limity, merge volumes), skladnia YAML, `bash -n healthcheck.sh`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
3.3 KiB
YAML
69 lines
3.3 KiB
YAML
service:
|
|
name: ai-cluster
|
|
owner_node: solaria
|
|
exposure: tailscale-internal
|
|
dependencies:
|
|
- mosquitto
|
|
- redis
|
|
ports:
|
|
- container: 8000
|
|
host: 8000
|
|
protocol: tcp
|
|
bind: 100.100.231.104 # SOLARIA Tailscale IP — NPM@VPS proxies here
|
|
service: openclaw
|
|
- container: 1883
|
|
host: 1883
|
|
protocol: tcp
|
|
bind: 100.100.231.104 # SOLARIA Tailscale IP
|
|
service: mosquitto
|
|
healthcheck:
|
|
type: http
|
|
endpoint: http://100.100.231.104:8000/health
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
restart_policy: unless-stopped
|
|
persistence:
|
|
paths:
|
|
- /opt/homelab/config/ai-cluster/mosquitto # mosquitto.conf + acl + passwd (passwd is node-local)
|
|
- volume:redis_data
|
|
runtime:
|
|
env_file: /opt/homelab/config/ai-cluster/.env
|
|
env_vars:
|
|
- MQTT_USERNAME
|
|
- MQTT_PASSWORD
|
|
- GATEWAY_BASE_URL
|
|
notes:
|
|
- "Target node is SOLARIA. The stack still runs on the VPS at
|
|
/home/dockeruser/docker/ai-cluster/ outside GitOps; this manifest is the
|
|
authored target, cutover is NOT done. See CUTOVER.md."
|
|
- "Images are built on the node from src/ — nothing is pulled from a registry.
|
|
Build contexts: src/openclaw (openclaw), src/worker (codex-worker,
|
|
planner-worker, service-ops-worker via three Dockerfiles)."
|
|
- "The VPS directory also contains codex-worker/worker.py — a 609-byte prototype
|
|
using `requests` (not in any requirements.txt), with no Dockerfile and no
|
|
compose reference. It is dead code, not a second build context, and was
|
|
deliberately not carried into src/. The real codex-worker builds from
|
|
src/worker/Dockerfile."
|
|
- "telegram-bot is NOT part of this stack: the service exists in the VPS compose
|
|
file but no container runs. src/openclaw/telegram_bot.py is still shipped
|
|
because openclaw/Dockerfile COPYs it into the openclaw image (the build
|
|
fails without it); Dockerfile.telegram + requirements-telegram.txt are kept
|
|
so the service can be re-enabled later without another recon round."
|
|
- "GATEWAY_BASE_URL must be an IP, not `piha`. Tailscale DNS is disabled on
|
|
SOLARIA (`tailscale dns status` → 'Tailscale DNS: disabled'), so neither
|
|
`piha` nor `piha.tailedf7b1.ts.net` resolves. Verified 2026-07-27 that bare
|
|
`piha` does not resolve on the VPS either — the original default
|
|
http://piha:8080 was already dead there. Default is now
|
|
http://100.108.208.3:8080 (port confirmed open from SOLARIA)."
|
|
- "AGENT_ID values stay `vps-dev-1` / `vps-planner-1` / `vps-service-ops-1` after
|
|
the move. They are MQTT routing targets, not hostnames — renaming them breaks
|
|
any producer addressing a specific agent. Rename is a separate coordinated change."
|
|
- "service-ops-worker mounts /var/run/docker.sock read-write. On SOLARIA that means
|
|
it can restart any container on the node, including ollama and other GPU
|
|
workloads — a wider blast radius than on the VPS. Its allowlist
|
|
(is_allowed_command) limits it to ps/inspect/logs/restart, but this is worth a
|
|
security review before cutover."
|
|
- "mem_limits live in hosts/solaria/runtime/ai-cluster/docker-compose.override.yml,
|
|
sized from measured RSS on the VPS (workers 7-10 MiB, openclaw 25 MiB)."
|