infra: hf-pdocker-01 Phase 2 migration — all services returned from failover

Node hf-pdocker-01 hardware fully repaired and rebuilt (2026-03-08). This
commit captures the completed Phase 2 migration where all failover services
are returned from hf-pdocker-02/bart back to hf-pdocker-01 as their permanent
home.

New compose stacks for hf-pdocker-01:
- adguard: AdGuard Home DNS/ad-blocking (:3000, :53)
- traefik: Reverse proxy with TLS (:80/:443/:8090), .env.example included
- monitoring: Grafana, Prometheus, Alertmanager, InfluxDB, Blackbox, matrix-receiver
- smarthome: Home Assistant (:8123), ESPHome (:6052), Mosquitto (:1883/:8883)
- matrix: Synapse homeserver (:8008) + synapse-db + well-known (:8010)
- guacamole: Guacamole (:8199) + guacd + guacamole-db (local MySQL)
- farm-manager: Farm Manager API (:8888)

Updated compose stacks for hf-pdocker-01:
- frigate-notify: MQTT/Matrix hosts reverted from bart (.167) to hf-pdocker-01 (.192)

Documentation:
- docs/plans/2026-03-08-hf-pdocker-01-phase2-migration.md (new)
- CLAUDE.md: Full service distribution update — failover labels removed,
  hf-pdocker-02/bart cleaned up to reflect only permanent services,
  NetClaw/Aaron added to hf-pdocker-02, DNSStubListener fix noted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 19:57:03 -05:00
parent 26d559feb5
commit cd37bb9858
10 changed files with 555 additions and 37 deletions
+31 -35
View File
@@ -10,7 +10,7 @@ This repository manages a **homelab infrastructure** with self-hosted services r
**Nodes:** **Nodes:**
- **hf-pdocker-01** (192.168.86.192) - Swarm Manager, core infrastructure + Frigate NVR - **RESTORED (2026-03-08)** - **hf-pdocker-01** (192.168.86.192) - Swarm Manager, core infrastructure + Frigate NVR - **RESTORED (2026-03-08)**
- **hf-pdocker-02** (192.168.86.100) - Standalone Compose services (dev tools, utilities) + **FAILOVER: Traefik, Monitoring, AdGuard** - **hf-pdocker-02** (192.168.86.100) - Standalone Compose services (dev tools, utilities)
- **bart** (192.168.86.167) - Standalone Compose services (media stack, OpenVAS) - **bart** (192.168.86.167) - Standalone Compose services (media stack, OpenVAS)
**Synology NAS** (192.168.86.30) - Centralized NFS storage for all service data **Synology NAS** (192.168.86.30) - Centralized NFS storage for all service data
@@ -23,53 +23,39 @@ This repository manages a **homelab infrastructure** with self-hosted services r
hf-pdocker-01 (Manager, 23GB RAM, i7-7700T, NVMe, HD 630 GPU) -- RESTORED (2026-03-08, hardware repaired) hf-pdocker-01 (Manager, 23GB RAM, i7-7700T, NVMe, HD 630 GPU) -- RESTORED (2026-03-08, hardware repaired)
├── [COMPOSE] Frigate NVR (:5000) -- OpenVINO GPU detector, 13 cameras active ├── [COMPOSE] Frigate NVR (:5000) -- OpenVINO GPU detector, 13 cameras active
├── [COMPOSE] Frigate-Notify v2 (:5199) -- MQTT->AI->Matrix notifications ├── [COMPOSE] Frigate-Notify v2 (:5199) -- MQTT->AI->Matrix notifications
├── [COMPOSE] Home Assistant (:8123) -- MIGRATED BACK 2026-03-08 ├── [COMPOSE] Home Assistant (:8123)
├── [COMPOSE] ESPHome (:6052) -- MIGRATED BACK 2026-03-08 ├── [COMPOSE] ESPHome (:6052)
├── [COMPOSE] Mosquitto (:1883, :8883) -- MIGRATED BACK 2026-03-08 ├── [COMPOSE] Mosquitto (:1883, :8883)
├── [COMPOSE] Farm Agent (:8889) -- image built locally from Gitea ├── [COMPOSE] Synapse/Matrix (:8008) + synapse-db (postgres) + wellknown (:8010)
├── [COMPOSE] Guacamole (:8199) + guacd + guacamole-db (mysql, LOCAL /var/lib/guacamole-db)
├── [COMPOSE] AI Agents (margaret:18790, spirit:18791, clippy:18792, bob:18800)
├── [COMPOSE] Traefik (reverse proxy, ports 80/443/8090)
├── [COMPOSE] AdGuard Home (:3000, :53)
├── [COMPOSE] Monitoring (Grafana :3001, Prometheus :9095, Alertmanager :9093, InfluxDB :8086, Blackbox :9115, matrix-receiver :9094)
├── [COMPOSE] Farm Manager API (:8888) -- dashboard + API server
├── [COMPOSE] Farm Agent (:8889)
├── [SWARM] Telegraf (global), Node-exporter (global) ├── [SWARM] Telegraf (global), Node-exporter (global)
├── [CRON] sync-frigate-to-nas (daily 2am), cleanup-frigate-media (weekly Sun 3am) ├── [CRON] sync-frigate-to-nas (daily 2am), cleanup-frigate-media (weekly Sun 3am)
├── 5TB USB disk at /mnt/frigate-recordings (Frigate recordings storage) ├── 5TB USB disk at /mnt/frigate-recordings (Frigate recordings storage)
[Failover services remain on hf-pdocker-02/bart until Phase 2]
bart (Worker, 15GB RAM, i5-4570T, HDD) -- ALSO HOSTING FAILOVER SERVICES bart (Worker, 15GB RAM, i5-4570T, HDD)
├── [COMPOSE] Media Stack (Jellyfin, Sonarr, Radarr, SABnzbd, NZBHydra2, Jellyseerr) ├── [COMPOSE] Media Stack (Jellyfin, Sonarr, Radarr, SABnzbd, NZBHydra2, Jellyseerr)
├── [COMPOSE] OpenVAS (vulnerability scanner) ├── [COMPOSE] OpenVAS (vulnerability scanner)
├── [COMPOSE] Farm Agent (:8889) ├── [COMPOSE] Farm Agent (:8889)
├── [COMPOSE] Watchtower ├── [COMPOSE] Watchtower
├── [SWARM] Telegraf (global), Node-exporter (global) ├── [SWARM] Telegraf (global), Node-exporter (global)
├── [COMPOSE] Synapse/Matrix (:8008) + synapse-db (postgres) + wellknown (:8010) -- FAILOVER from hf-pdocker-01
├── [COMPOSE] Guacamole (:8199) + guacd + guacamole-db (mysql, LOCAL /var/lib/guacamole-db) -- FAILOVER from hf-pdocker-01
├── [COMPOSE] AI Agents (margaret, spirit, bob, clippy) -- FAILOVER from hf-pdocker-01 (2026-03-07)
hf-pdocker-02 (Worker, 7.6GB RAM, i7-6700T, HDD) -- PRIMARY NODE DURING FAILOVER hf-pdocker-02 (Worker, 7.6GB RAM, i7-6700T, HDD)
├── [COMPOSE] Traefik (reverse proxy, ports 80/443/8090) -- FAILOVER from hf-pdocker-01
├── [COMPOSE] Monitoring (Grafana :3001, Prometheus :9095, Alertmanager :9093, InfluxDB :8086, Blackbox :9115, matrix-receiver :9094) -- FAILOVER
├── [COMPOSE] AdGuard Home (:3000, :53) -- FAILOVER
├── [COMPOSE] Unifi + unifi-db (MongoDB) ├── [COMPOSE] Unifi + unifi-db (MongoDB)
├── [COMPOSE] Gitea + gitea-db (PostgreSQL) ├── [COMPOSE] Gitea + gitea-db (PostgreSQL)
├── [COMPOSE] Semaphore + semaphore-db (MySQL) ├── [COMPOSE] Semaphore + semaphore-db (MySQL)
├── [COMPOSE] Wiki.js + wikijs-db (PostgreSQL) ├── [COMPOSE] Wiki.js + wikijs-db (PostgreSQL)
├── [COMPOSE] Vaultwarden, Actual Budget, MCPO, Trivy ├── [COMPOSE] Vaultwarden, Actual Budget, MCPO, Trivy
├── [COMPOSE] NetClaw/Aaron (:1179) -- AI network agent
├── [COMPOSE] Farm Agent (:8889) ├── [COMPOSE] Farm Agent (:8889)
├── [COMPOSE] Watchtower ├── [COMPOSE] Watchtower
├── [SWARM] Telegraf (global), Node-exporter (global), Portainer ├── [SWARM] Telegraf (global), Node-exporter (global)
Services restored to hf-pdocker-01 (post-recovery):
- Frigate NVR (:5000) -- back on hf-pdocker-01 with GPU
- Frigate-Notify v2 (:5199) -- deployed 2026-03-08
- Farm Agent (:8889)
- Mosquitto MQTT (:1883, :8883) -- migrated back 2026-03-08
- Home Assistant (:8123) -- migrated back 2026-03-08
- ESPHome (:6052) -- migrated back 2026-03-08
Services still on failover nodes (not yet returned):
- Matrix/Synapse -- still on bart
- Guacamole -- still on bart
- AI Agents -- still on bart
- Traefik -- still on hf-pdocker-02
- Monitoring stack -- still on hf-pdocker-02
- AdGuard Home -- still on hf-pdocker-02
- Farm Manager API (not yet migrated back)
``` ```
## Working with This Repository ## Working with This Repository
@@ -91,8 +77,8 @@ All service data lives on the **Synology NAS** via NFS, mounted at `/mnt/docker-
├── media/ # Frigate recordings ├── media/ # Frigate recordings
├── traefik/ # Let's Encrypt certs ├── traefik/ # Let's Encrypt certs
└── compose/ # Standalone compose files per node └── compose/ # Standalone compose files per node
├── hf-pdocker-01/{frigate,frigate-notify}/ ├── hf-pdocker-01/{frigate,frigate-notify,matrix,smarthome,guacamole,ai-agents,traefik,adguard}/
├── hf-pdocker-02/{unifi,gitea,semaphore,wikijs,vaultwarden,actual-budget,mcpo,trivy,watchtower}/ ├── hf-pdocker-02/{unifi,gitea,semaphore,wikijs,vaultwarden,actual-budget,mcpo,trivy,netclaw,watchtower}/
└── bart/{media,openvas,watchtower}/ └── bart/{media,openvas,watchtower}/
``` ```
@@ -163,9 +149,18 @@ compose/ # Standalone Compose definitions (deployed per-node)
- Home Assistant: :8123 - Home Assistant: :8123
- ESPHome: :6052 - ESPHome: :6052
- Mosquitto: :1883 - Mosquitto: :1883
- Matrix/Synapse: :8008
- Well-known (Matrix federation): :8010
- Guacamole: :8199
- AdGuard Home: :3000 (DNS: :53)
- Traefik Dashboard: :8090 (HTTP: :80, HTTPS: :443)
- Grafana: :3001 - Grafana: :3001
- AdGuard: :3000 - Prometheus: :9095
- Traefik Dashboard: :8090 - Alertmanager: :9093
- InfluxDB: :8086
- Blackbox Exporter: :9115
- matrix-alertmanager-receiver: :9094
- AI Agents (margaret :18790, spirit :18791, clippy :18792, bob :18800) -- loopback only
- Farm Manager: :8888 (dashboard + API) - Farm Manager: :8888 (dashboard + API)
- Farm Agent: :8889 - Farm Agent: :8889
@@ -179,6 +174,7 @@ compose/ # Standalone Compose definitions (deployed per-node)
- Actual Budget: :5006 - Actual Budget: :5006
- MCPO: :8001 - MCPO: :8001
- Trivy: :4954 - Trivy: :4954
- NetClaw/Aaron: :1179 (internal only)
**bart (192.168.86.167):** **bart (192.168.86.167):**
- Farm Agent: :8889 - Farm Agent: :8889
@@ -189,7 +185,6 @@ compose/ # Standalone Compose definitions (deployed per-node)
- NZBHydra2: :5076 - NZBHydra2: :5076
- Jellyseerr: :5055 - Jellyseerr: :5055
- OpenVAS: :9392 - OpenVAS: :9392
- AI Agents (margaret :18790, spirit :18791, clippy :18792, bob :18800) -- loopback only, failover from hf-pdocker-01
**GPU Machine (192.168.86.196, RTX 3090):** **GPU Machine (192.168.86.196, RTX 3090):**
- Ollama: :11434 (vision LLM, llava:13b) - Ollama: :11434 (vision LLM, llava:13b)
@@ -305,3 +300,4 @@ All persistent data on NAS at `/mnt/docker-data/`:
4. **InfluxDB Connection**: Telegraf may show timeout errors if InfluxDB is not running 4. **InfluxDB Connection**: Telegraf may show timeout errors if InfluxDB is not running
5. **Frigate cameras**: Cameras on 192.168.44.x subnet may show RTSP timeouts (check camera network) 5. **Frigate cameras**: Cameras on 192.168.44.x subnet may show RTSP timeouts (check camera network)
6. **Registry container**: Stopped on hf-pdocker-01 to free port 5000 for Frigate 6. **Registry container**: Stopped on hf-pdocker-01 to free port 5000 for Frigate
7. **systemd-resolved DNSStubListener**: Must be disabled on any node running AdGuard Home (port 53 conflict). Fix: `/etc/systemd/resolved.conf.d/nostub.conf` with `DNSStubListener=no`, then `systemctl restart systemd-resolved`. Applied on hf-pdocker-01 and hf-pdocker-02.
@@ -0,0 +1,26 @@
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
volumes:
- /mnt/docker-data/configs/adguardhome/work:/opt/adguardhome/work
- /mnt/docker-data/configs/adguardhome/conf:/opt/adguardhome/conf
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000/tcp"
- "853:853/tcp"
mem_limit: 256M
memswap_limit: 256M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
@@ -0,0 +1,25 @@
services:
farm-manager:
image: farm-manager:latest
container_name: farm-manager
restart: unless-stopped
ports:
- "8888:8888"
environment:
- CONFIG_PATH=/app/config.json
- GROUPS_PATH=/data/groups.json
volumes:
- /mnt/docker-data/configs/farm-manager:/data
mem_limit: 256M
memswap_limit: 256M
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8888/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
@@ -9,9 +9,9 @@ services:
environment: environment:
- TZ=America/Chicago - TZ=America/Chicago
- FRIGATE_URL=http://localhost:5000 - FRIGATE_URL=http://localhost:5000
- MQTT_HOST=192.168.86.167 - MQTT_HOST=192.168.86.192
- MQTT_PORT=1883 - MQTT_PORT=1883
- MATRIX_HOMESERVER=http://192.168.86.167:8008 - MATRIX_HOMESERVER=http://192.168.86.192:8008
- CLIP_SERVICE_URL=http://192.168.86.196:5200 - CLIP_SERVICE_URL=http://192.168.86.196:5200
- OLLAMA_URL=http://192.168.86.196:11434 - OLLAMA_URL=http://192.168.86.196:11434
- OLLAMA_MODEL=llava:13b - OLLAMA_MODEL=llava:13b
@@ -0,0 +1,82 @@
services:
guacamole:
image: guacamole/guacamole:latest
container_name: guacamole
restart: unless-stopped
environment:
- GUACD_HOSTNAME=guacd
- MYSQL_HOSTNAME=guacamole-db
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
- MYSQL_PASSWORD=guacamole_pass
ports:
- "8199:8080"
networks:
- guacamole-internal
depends_on:
guacamole-db:
condition: service_healthy
mem_limit: 512M
memswap_limit: 512M
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/guacamole/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
guacd:
image: guacamole/guacd:latest
container_name: guacd
restart: unless-stopped
networks:
- guacamole-internal
mem_limit: 512M
memswap_limit: 512M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
guacamole-db:
image: mysql:8.0
container_name: guacamole-db
user: "1024:100"
restart: unless-stopped
command: --innodb-use-native-aio=0 --innodb-buffer-pool-size=128M
environment:
- MYSQL_ROOT_PASSWORD=guacamole_root
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
- MYSQL_PASSWORD=guacamole_pass
volumes:
# NFS cannot be used for MySQL due to persistent NLM lock issues (ibdata1, dblwr files)
# guacamole-db uses LOCAL storage on hf-pdocker-01
- /var/lib/guacamole-db:/var/lib/mysql
networks:
- guacamole-internal
mem_limit: 512M
memswap_limit: 512M
labels:
- "com.centurylinklabs.watchtower.enable=false"
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 --silent"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
networks:
guacamole-internal:
driver: bridge
@@ -0,0 +1,86 @@
services:
synapse:
image: matrixdotorg/synapse:latest
container_name: synapse
restart: unless-stopped
environment:
- SYNAPSE_SERVER_NAME=mess.hobbs.farm
- SYNAPSE_REPORT_STATS=no
volumes:
- /mnt/docker-data/configs/matrix/data:/data
ports:
- "8008:8008"
networks:
- matrix-internal
depends_on:
synapse-db:
condition: service_healthy
mem_limit: 1G
memswap_limit: 1G
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
wellknown:
image: nginx:alpine
container_name: matrix-wellknown
restart: unless-stopped
volumes:
- /mnt/docker-data/configs/matrix/wellknown:/usr/share/nginx/html/.well-known/matrix:ro
ports:
- "8010:80"
mem_limit: 64M
memswap_limit: 64M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:80/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
synapse-db:
image: postgres:15-alpine
container_name: synapse-db
user: "1024:100"
restart: unless-stopped
environment:
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=synapse
- POSTGRES_DB=synapse
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- /mnt/docker-data/databases/matrix-db:/var/lib/postgresql/data
networks:
- matrix-internal
mem_limit: 256M
memswap_limit: 256M
labels:
- "com.centurylinklabs.watchtower.enable=false"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U synapse -d synapse"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
networks:
matrix-internal:
driver: bridge
@@ -0,0 +1,153 @@
networks:
monitoring-net:
name: monitoring-net
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
user: "104"
networks:
- monitoring-net
ports:
- "3001:3000"
volumes:
- /mnt/docker-data/configs/grafana:/var/lib/grafana
mem_limit: 512M
memswap_limit: 512M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/api/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
networks:
- monitoring-net
ports:
- "9095:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
- '--web.enable-lifecycle'
volumes:
- /mnt/docker-data/configs/prometheus:/etc/prometheus
mem_limit: 512M
memswap_limit: 512M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:9090/-/healthy || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
restart: unless-stopped
networks:
- monitoring-net
ports:
- "9093:9093"
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
volumes:
- /mnt/docker-data/configs/alertmanager:/etc/alertmanager
- alertmanager-data:/alertmanager
mem_limit: 256M
memswap_limit: 256M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:9093/-/healthy || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
influxdb:
image: influxdb:1.8-alpine
container_name: influxdb
restart: unless-stopped
networks:
- monitoring-net
ports:
- "8086:8086"
volumes:
- /mnt/docker-data/configs/influxdb:/var/lib/influxdb
mem_limit: 1G
memswap_limit: 1G
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:8086/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
matrix-alertmanager-receiver:
image: metio/matrix-alertmanager-receiver:2026.2.25
container_name: matrix-alertmanager-receiver
restart: unless-stopped
networks:
- monitoring-net
ports:
- "9094:9094"
volumes:
- /mnt/docker-data/configs/alertmanager/matrix-receiver-config.yml:/config/config.yml:ro
command: ["--config-path", "/config/config.yml"]
mem_limit: 128M
memswap_limit: 128M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
blackbox-exporter:
image: prom/blackbox-exporter:latest
container_name: blackbox-exporter
restart: unless-stopped
networks:
- monitoring-net
ports:
- "9115:9115"
command:
- '--config.file=/config/blackbox.yml'
volumes:
- /mnt/docker-data/configs/blackbox:/config:ro
mem_limit: 128M
memswap_limit: 128M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
volumes:
alertmanager-data:
@@ -0,0 +1,3 @@
# Cloudflare DNS API token for Let's Encrypt DNS challenge
# Actual value stored in Vaultwarden as "Traefik CF_DNS_API_TOKEN"
CF_DNS_API_TOKEN=your-cloudflare-api-token-here
@@ -0,0 +1,39 @@
services:
traefik:
image: traefik:v3.6
container_name: traefik
restart: unless-stopped
command:
- "--api.insecure=true"
- "--providers.file.directory=/config/dynamic"
- "--providers.file.watch=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.letsencrypt.acme.email=jeremydanielhobbs@gmail.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
environment:
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
ports:
- "80:80"
- "443:443"
- "8090:8080"
volumes:
- /mnt/docker-data/traefik/letsencrypt:/letsencrypt
- /mnt/docker-data/traefik/dynamic:/config/dynamic:ro
mem_limit: 512M
memswap_limit: 512M
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:8080/api/overview || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
@@ -0,0 +1,108 @@
# hf-pdocker-01 Phase 2 — Service Migration Back
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Migrate all failover services back to hf-pdocker-01 from hf-pdocker-02 and bart.
**Architecture:** Stop services on failover nodes, start on hf-pdocker-01, update IP references and routing. Order matters due to dependencies.
**Dependency Chain:**
- Mosquitto must be up before Home Assistant and Frigate MQTT config update
- Matrix/Synapse must be up before AI Agents
- Traefik must be up before external routing works
- AdGuard is DNS — move carefully to minimize resolution downtime
---
### Task 1: Migrate Mosquitto (bart → hf-pdocker-01)
MQTT broker — Home Assistant and Frigate depend on it.
1. Deploy Mosquitto on hf-pdocker-01 using compose from `/mnt/docker-data/compose/bart/smarthome/` (extract mosquitto service) or create standalone compose
2. Verify MQTT is listening on hf-pdocker-01:1883
3. Update Frigate config MQTT host back to 192.168.86.192 (localhost)
4. Restart Frigate to pick up new MQTT
5. Stop Mosquitto on bart
### Task 2: Migrate Home Assistant + ESPHome (bart → hf-pdocker-01)
Smart home services — depend on Mosquitto.
1. Deploy HA + ESPHome on hf-pdocker-01
2. Update HA config: MQTT broker IP back to 192.168.86.192
3. Verify HA web UI on :8123, ESPHome on :6052
4. Stop HA + ESPHome on bart
### Task 3: Migrate Matrix/Synapse (bart → hf-pdocker-01)
Matrix homeserver — AI agents and alertbot depend on it.
1. Deploy Synapse + synapse-db + wellknown on hf-pdocker-01
2. Verify Matrix federation and client API on :8008
3. Update matrix-alertmanager-receiver config to point to new Synapse
4. Stop Synapse stack on bart
### Task 4: Migrate Guacamole (bart → hf-pdocker-01)
Remote desktop gateway — has local MySQL DB on bart (NFS lock workaround).
1. Copy guacamole-db data from bart:/var/lib/guacamole-db to hf-pdocker-01 local storage
2. Deploy Guacamole + guacd + guacamole-db on hf-pdocker-01
3. Verify web UI on :8199
4. Stop Guacamole stack on bart
### Task 5: Migrate AI Agents (bart → hf-pdocker-01)
margaret, spirit, bob, clippy — depend on Matrix/Synapse.
1. Build margaret-openclaw:latest image on hf-pdocker-01
2. Update agent configs: Matrix homeserver URL back to 192.168.86.192:8008
3. Rename Matrix account state dirs
4. Deploy all 4 agents on hf-pdocker-01
5. Verify Matrix connectivity
6. Stop agents on bart
### Task 6: Migrate AdGuard Home (hf-pdocker-02 → hf-pdocker-01)
DNS server — brief downtime expected during switchover.
1. Deploy AdGuard on hf-pdocker-01 using NAS config
2. Verify DNS resolution on :53 and web UI on :3000
3. Stop AdGuard on hf-pdocker-02
### Task 7: Migrate Traefik (hf-pdocker-02 → hf-pdocker-01)
Reverse proxy — handles all external HTTPS routing.
1. Deploy Traefik on hf-pdocker-01 with NAS certs and dynamic configs
2. Update dynamic configs for new service IPs (services now on .192 instead of .167)
3. Verify HTTPS routing for mess/solo/yoda/vault/git.hobbs.farm
4. Stop Traefik on hf-pdocker-02
### Task 8: Migrate Monitoring Stack (hf-pdocker-02 → hf-pdocker-01)
Grafana, Prometheus, Alertmanager, InfluxDB, Blackbox, matrix-receiver.
1. Deploy full monitoring stack on hf-pdocker-01
2. Update Prometheus config with correct service IPs (most services now back on .192)
3. Update Telegraf configs on all nodes to point InfluxDB to .192
4. Verify Grafana on :3001, Prometheus on :9095
5. Stop monitoring stack on hf-pdocker-02
### Task 9: Migrate Farm Manager API (new deploy on hf-pdocker-01)
Was never failed over — needs fresh deploy.
1. Clone farm-manager from Gitea, build server image
2. Deploy Farm Manager API on :8888
3. Update config.json with correct node IPs
4. Verify dashboard and API
### Task 10: Cleanup + Final Verification
1. Remove stopped failover containers on bart and hf-pdocker-02
2. Update all Prometheus blackbox targets for final service locations
3. Hot-reload Prometheus
4. Update Traefik dynamic configs
5. Verify all services healthy
6. Update CLAUDE.md, MEMORY.md, wiki