Skip to content

Wire-pod (Anki Vector)

Self-hosted replacement for the defunct Digital Dream Labs cloud, enabling full offline operation of an Anki Vector robot. Runs in the home namespace alongside a companion mDNS broadcaster in infra.

  • Sourceghcr.io/kercre123/wire-pod
  • Robot server IP192.168.71.244 (Cilium L2 LoadBalancer)
  • Web UIwirepod.hdhomelab.com
  • Namespacehome (wire-pod) · infra (avahi)
  • Flux manifestsflux/apps/noah/home/wire-pod/ · flux/infrastructure/noah/avahi.yaml

Architecture

graph TB
    subgraph home["L2 home network (192.168.68.0/22)"]
        VEC[Anki Vector\nrobot]
    end

    subgraph infra["Namespace: infra"]
        AV[wire-pod-avahi\nhostNetwork: true\navahi-publish escapepod.local]
    end

    subgraph homeNs["Namespace: home (worker-1b)"]
        WP[wire-pod\nghcr.io/kercre123/wire-pod:main]
        SVC_UI[wire-pod-ui\nClusterIP :8080]
        SVC_ROBOT[wire-pod-robot\nLoadBalancer 192.168.71.244\n:80 :443 :8080 :8084]
        PVC_DATA[wire-pod-data\n5Gi local-path /data]
        PVC_IMG[wire-pod-images\n2Gi local-path /images]
    end

    subgraph gw["Gateway (infra)"]
        HR[HTTPRoute\nwirepod.hdhomelab.com]
    end

    VEC -->|mDNS: escapepod.local?| AV
    AV -->|mDNS reply: 192.168.71.244| VEC
    VEC -->|443 TLS robot protocol| SVC_ROBOT
    VEC -->|80 HTTP| SVC_ROBOT
    VEC -->|8084 SDK| SVC_ROBOT
    HR -->|proxy| SVC_UI
    WP --> PVC_DATA
    WP --> PVC_IMG
Hold "Alt" / "Option" to enable pan & zoom

The mDNS problem

Vector uses mDNS, not DNS

Vector resolves escapepod.local via mDNS (Bonjour/Avahi), not regular DNS. Pi-hole DNS overrides and router-level DNS overrides do nothing — the robot never queries them for .local names.

Wire-pod broadcasting escapepod.local from inside a K8s pod doesn't work because mDNS multicast is confined to the pod network and never reaches the home L2.

Fix: A separate Deployment in the infra namespace runs avahi-daemon + avahi-publish with hostNetwork: true. This uses the node's physical NIC, putting the mDNS announcement directly onto the home L2 where Vector can hear it.

Why it works Detail
hostNetwork: true Pod uses node NIC, bypasses CNI overlay
infra namespace Has enforce: privileged PodSecurity — required for hostNetwork + NET_ADMIN
Fixed announced IP Always 192.168.71.244 regardless of which node runs the pod
Talos compatible hostNetwork is a K8s/container feature, not OS-level

Avahi startup sequence

The container must start services in the correct order — avahi-publish is a D-Bus client and fails silently if the daemon isn't ready:

dbus-uuidgen → dbus-daemon → sleep 1 → avahi-daemon → sleep 1 → avahi-publish

--no-drop-root is required for avahi-daemon since the container runs as root.

Verifying mDNS

From any home network device:

dns-sd -G v4 escapepod.local
# Should return only 192.168.71.244
avahi-resolve -4 -n escapepod.local
# Should return 192.168.71.244

Stale Mac record

If you previously ran wire-pod locally on a Mac, macOS may still broadcast the old escapepod.local record even after stopping the app. Flush with:

sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

Storage

Both PVCs use local-path and the main pod is pinned to worker-1b via nodeSelector.

PVC Size Mount Purpose
wire-pod-data 5Gi /data Config, TLS certs, VOSK STT models (~1.8 GB)
wire-pod-images 2Gi /images OTA firmware images for robot flashing

Mount path

Wire-pod expects data at /data, set via WIREPOD_DATA_DIR=/data. Using /wire-pod/data (a common mistake) causes config to write to ephemeral container storage and wipe on every restart.

Services

Service Type Ports Purpose
wire-pod-ui ClusterIP 8080 Web UI — proxied via HTTPRoute
wire-pod-robot LoadBalancer 192.168.71.244 80, 443, 8080, 8084 Robot protocol + SDK

Port 8080 is exposed on the LoadBalancer as well as ClusterIP so wpsetup.keriganc.com can reach the wire-pod API at escapepod.local:8080 during the robot authentication flow.

First-run setup

  1. Open wirepod.hdhomelab.com → complete the setup wizard
  2. Choose VOSK as the STT engine (offline, no API key needed)
  3. Wire-pod downloads the VOSK model on first run (~1.8 GB into the PVC)

Connecting Vector

  1. Verify mDNS: dns-sd -G v4 escapepod.local → should return 192.168.71.244
  2. Go to wpsetup.keriganc.com on a Bluetooth-capable device
  3. Select Escape Pod connection method
  4. Put Vector in recovery mode (hold back button ~15 s until recovery screen)
  5. Complete authentication — wire-pod generates TLS certs and pushes config to Vector
  6. Vector connects to escapepod.local:443 → resolves via mDNS → 192.168.71.244

LLM integration (optional)

Wire-pod can route "Hey Vector, what is…" queries to a local LLM. Ollama runs on the NAS at 192.168.68.50:11434.

  1. Open wirepod.hdhomelab.comSettings → Knowledge Graph
  2. Provider: OpenAI
  3. Base URL: http://192.168.68.50:11434/v1
  4. API key: ollama
  5. Model: any pulled model (e.g. llama3.2)
  6. Enable Intent Graph for natural conversation without requiring a trigger phrase