blumeops/docs/reference/kubernetes/tailscale-operator.md
Erich Blume e6cf7e47e0
All checks were successful
Deploy Fly.io Proxy / deploy (push) Successful in 1m8s
Restrict flyio-proxy ACLs to dedicated tag:flyio-target endpoints (#126)
## Summary
- Introduce `tag:flyio-target` so services must explicitly opt in to be reachable by the fly.io proxy
- Replace broad `tag:k8s` and `tag:homelab` grants with the new tag in the ACL rule and test
- Add `tailscale.com/tags: "tag:k8s,tag:flyio-target"` annotation to docs, loki, and prometheus Ingresses
- Switch Alloy push endpoints from `*.ops.eblu.me` (Caddy) to `*.tail8d86e.ts.net` (Tailscale Ingress)
- Update docs: flyio-proxy, caddy, tailscale, forgejo (future public access + security checklist), expose-service-publicly

## Manual step (not in PR)
Update the k8s operator OAuth client in the Tailscale admin console to include `tag:flyio-target` in its scope. Without this, the operator cannot assign the new tag to Ingress proxy nodes.

## Deployment order
1. **Pulumi ACLs** — `mise run tailnet-preview && mise run tailnet-up`
2. **OAuth client** — Manual update in Tailscale admin console
3. **K8s Ingresses** — `argocd app sync apps && argocd app sync docs loki prometheus`
4. **Fly.io proxy** — `mise run fly-deploy`
5. **Verify** — `mise run services-check`, check Grafana dashboards

## Test plan
- [ ] `mise run tailnet-preview` shows clean diff
- [ ] `argocd app diff docs`, `argocd app diff loki`, `argocd app diff prometheus` show only annotation additions
- [ ] After deploy: Grafana dashboards show continued log/metric flow
- [ ] `curl -sf https://docs.eblu.me` returns 200
- [ ] `mise run services-check` passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/126
2026-02-08 21:54:18 -08:00

1.4 KiB

title tags
Tailscale Operator
kubernetes
tailscale

Tailscale Kubernetes Operator

The Tailscale operator enables Kubernetes services to be exposed directly on the Tailscale network via Ingress resources.

Quick Reference

Property Value
Namespace tailscale
Helm Chart tailscale/tailscale-operator
ArgoCD App tailscale-operator

How It Works

Ingresses use a shared ProxyGroup (ingress) rather than per-service Tailscale nodes. When you create an Ingress with ingressClassName: tailscale:

  1. Operator configures the shared ProxyGroup pods to serve the new Ingress
  2. Service gets a VIP (Virtual IP) address on the tailnet
  3. Service becomes accessible at <hostname>.tail8d86e.ts.net
  4. TLS is handled automatically via Tailscale

Tailnet clients must have --accept-routes enabled to route to VIP addresses.

Services can be individually tagged (e.g., tag:flyio-target) via Ingress annotations to control which ACL grants apply. See expose-service-publicly for the tagging workflow.

Limitations

Services exposed via Tailscale Ingress are not accessible from:

  • Other Kubernetes pods (they're not Tailscale clients)
  • Docker containers on indri

For pod-to-service communication, use routing (*.ops.eblu.me) instead.