Skip to content

Tailscale sidecar: userspace SOCKS5 and localhost HA proxy #74

Open

Description

@NinjaLikesCheez

Context

Preferred HA path (ADR 0008/0009, #43): Pixel on Azure joins the Pixelbar tailnet and talks to Home Assistant on the mesh. Nabu Casa is the fallback until that works.

Live pixel-dev (2026-10-09): Tailscale is off. One container (pixel) + init prepare-volume. Key Vault has no tailscale-auth-key. HOME_ASSISTANT_URL is a Nabu Casa *.ui.nabu.casa host; home-assistant-token is in the vault; inventory.yaml on the Azure Files share is Pixel-sized — the replica is connected to that HA. Infra does not enforce “dev must not control real doors” (#43). That stays devices.yaml / capabilities / /admin doors / a test HA.

Terraform stub (tailscale_enabled, off by default) is not enough to flip on:

  • Container Apps has no /dev/net/tun. Userspace (TS_USERSPACE=true) is required and already set.
  • Userspace does not install 100.x routes. Pixel cannot connect() to MagicDNS / 100.x even though it shares the replica netns. Need SOCKS5 on localhost plus a localhost forwarder (ha-proxy / socat) to HA:8123. Pixel’s HOME_ASSISTANT_URL must be http://127.0.0.1:8123, never *.ts.net (public DNS → 100.x → Azure blackhole).
  • ACA injects KUBERNETES_SERVICE_HOST. Official containerboot then dies looking for a service account (tailscale#18558). Stub does not clear it.
  • Stub sets TS_ACCEPT_DNS=true and --accept-routes. Wrong: DNS rewrite is only the sidecar’s resolv.conf; --accept-routes is a LAN blast-radius. Use --advertise-tags=tag:pixel-dev instead.
  • Do not persist Tailscale state on pixel-persist while Guarantee a single running instance per environment #11 is open (overlapping revisions would share a node key). Ephemeral / OAuth-minted nodes.
  • Do not ACA-probe Tailscale /healthz: an unhealthy sidecar restarts the whole replica and drops Discord. Pixel probes stay Discord-only. HA stays fail-closed in-app.

Do not add a VNet, extra replica, or public HA (Funnel, new port-forward) so Azure can reach it.

Goal

One replica joins the tailnet. Pixel reaches HA only via 127.0.0.1:8123 → SOCKS5 → mesh. Discord, SpaceAPI, Sentry, GHCR, Key Vault stay on ordinary Azure egress. Then drop Nabu Casa for Azure. Dev still must not move prod doors.

Scope

  • Fix the sidecar env (empty KUBERNETES_SERVICE_HOST / TS_KUBE_SECRET, TS_SOCKS5_SERVER=127.0.0.1:1055, drop accept-dns/accept-routes, advertise tags).
  • Add a pinned ha-proxy (socat) on the same replica, gated on tailscale_enabled.
  • When enabled, force HOME_ASSISTANT_URL=http://127.0.0.1:8123. One URL — no automatic fallback to Nabu Casa (that would fail-open to the internet).
  • Key Vault tailscale-auth-key: tagged OAuth client (or reusable tagged ephemeral preauthorized key). Never in Terraform state. UAMI stays Key Vault Secrets User.
  • Keep min=max replicas = 1. Extra containers on that replica are fine; extra replicas are not (two Discord sessions and two tailnet nodes).
  • Tailnet ACL: Pixel tags may open tcp:8123 to the HA tag only.
  • Dev: test HA or HA off — do not grant tag:pixel-dev → prod tag:ha “because the mesh is up.”
  • Cost: README ~€15/month for the 0.25 vCPU sidecar; ha-proxy is noise. Leave it off until this issue is done.

Application code should not need a change if socat is acceptable.

Acceptance criteria

  • tailscale_enabled = true in gitignored tfvars only, after the vault secret exists
  • /readyz stays Discord-only through the rollout; HA down does not bounce the replica
  • /admin status shows HA connected over the mesh path (127.0.0.1), not Nabu Casa
  • Pixel cannot reach other LAN ports; no Funnel/Serve; no --accept-routes
  • dev cannot act on prod doors (separate HA or no grant)
  • Nabu Casa is removed from Azure env once the mesh path is the one URL
  • Stub comments / example tfvars no longer suggest flipping the current block on as-is

Do not

  • VNet / TUN / privileged sidecar / bake Tailscale into the Pixel image
  • ALL_PROXY on the Pixel container
  • Persist Tailscale state on Azure Files until Guarantee a single running instance per environment #11
  • Public ingress on the Container App
  • Use Tailscale identity to authorise Discord users

References

Activity

  1. added
    infrastructureTerraform, Azure, CI/CD, operations
    securityAuth, access control, privacy, secrets — needs human review
    on Oct 9, 2026
  2. NinjaLikesCheez commented on Oct 9, 2026

    @NinjaLikesCheez
    ContributorAuthor

    Part of #43. Live pixel-dev already has HA token + Nabu Casa URL; this issue is the mesh path. Do not flip tailscale_enabled until the stub is fixed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    infrastructureTerraform, Azure, CI/CD, operationssecurityAuth, access control, privacy, secrets — needs human review

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions