From 61ca1ca3054e548edf240ceec70a6a3a11ebc9ab Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Thu, 19 Feb 2026 09:33:05 -0800 Subject: [PATCH] Deploy Tailscale operator on ringtail k3s cluster (#215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Extract shared Tailscale operator resources (CRDs, RBAC, Deployment, ProxyClass, DNSConfig) into `tailscale-operator-base/` so both clusters reference the same manifests - Add `tailscale-operator-ringtail/` overlay with 1-replica ProxyGroup and ExternalSecret for the shared OAuth client - Add ArgoCD Application targeting `ringtail.tail8d86e.ts.net:6443` - Update `.yamllint.yaml` ignore path for the moved `operator.yaml` ## Deployment and Testing - [ ] Sync `apps` app to pick up the new Application definition - [ ] `argocd app sync tailscale-operator-ringtail` - [ ] Verify ExternalSecret syncs: `kubectl --context=k3s-ringtail -n tailscale get externalsecret` - [ ] Verify operator pod runs: `kubectl --context=k3s-ringtail -n tailscale get pods` - [ ] Verify ProxyGroup ready: `kubectl --context=k3s-ringtail -n tailscale get proxygroups` - [ ] Verify indri operator still works: `argocd app diff tailscale-operator` - [ ] Check Tailscale admin for new operator device with `tag:k8s-operator` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/215 --- .yamllint.yaml | 2 +- argocd/apps/tailscale-operator-ringtail.yaml | 27 ++++++++++++++++ .../dnsconfig.yaml | 0 .../kustomization.yaml | 10 ++++++ .../operator.yaml | 0 .../proxyclass.yaml | 0 .../external-secret.yaml | 32 +++++++++++++++++++ .../kustomization.yaml | 10 ++++++ .../proxygroup-ingress.yaml | 11 +++++++ .../tailscale-operator/kustomization.yaml | 5 ++- .../tailscale-operator-ringtail.infra.md | 1 + pulumi/tailscale/policy.hujson | 2 +- 12 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 argocd/apps/tailscale-operator-ringtail.yaml rename argocd/manifests/{tailscale-operator => tailscale-operator-base}/dnsconfig.yaml (100%) create mode 100644 argocd/manifests/tailscale-operator-base/kustomization.yaml rename argocd/manifests/{tailscale-operator => tailscale-operator-base}/operator.yaml (100%) rename argocd/manifests/{tailscale-operator => tailscale-operator-base}/proxyclass.yaml (100%) create mode 100644 argocd/manifests/tailscale-operator-ringtail/external-secret.yaml create mode 100644 argocd/manifests/tailscale-operator-ringtail/kustomization.yaml create mode 100644 argocd/manifests/tailscale-operator-ringtail/proxygroup-ingress.yaml create mode 100644 docs/changelog.d/tailscale-operator-ringtail.infra.md diff --git a/.yamllint.yaml b/.yamllint.yaml index 15b4de5..452c7fe 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -28,4 +28,4 @@ ignore: - .venv/ - pulumi/.venv/ # Third-party k8s manifest with non-standard formatting - - argocd/manifests/tailscale-operator/operator.yaml + - argocd/manifests/tailscale-operator-base/operator.yaml diff --git a/argocd/apps/tailscale-operator-ringtail.yaml b/argocd/apps/tailscale-operator-ringtail.yaml new file mode 100644 index 0000000..a261354 --- /dev/null +++ b/argocd/apps/tailscale-operator-ringtail.yaml @@ -0,0 +1,27 @@ +--- +# ArgoCD Application for Tailscale Kubernetes Operator on ringtail +# Shares operator.yaml, proxyclass, and dnsconfig with indri; ringtail-specific +# ProxyGroup (1 replica) and ExternalSecret live in the overlay directory. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: tailscale-operator-ringtail + namespace: argocd +spec: + project: default + # Tailscale operator mutates externalName from "placeholder" to actual proxy service + ignoreDifferences: + - group: "" + kind: Service + jsonPointers: + - /spec/externalName + source: + repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git + targetRevision: main + path: argocd/manifests/tailscale-operator-ringtail + destination: + server: https://ringtail.tail8d86e.ts.net:6443 + namespace: tailscale + syncPolicy: + syncOptions: + - CreateNamespace=true diff --git a/argocd/manifests/tailscale-operator/dnsconfig.yaml b/argocd/manifests/tailscale-operator-base/dnsconfig.yaml similarity index 100% rename from argocd/manifests/tailscale-operator/dnsconfig.yaml rename to argocd/manifests/tailscale-operator-base/dnsconfig.yaml diff --git a/argocd/manifests/tailscale-operator-base/kustomization.yaml b/argocd/manifests/tailscale-operator-base/kustomization.yaml new file mode 100644 index 0000000..980b8e3 --- /dev/null +++ b/argocd/manifests/tailscale-operator-base/kustomization.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: tailscale + +resources: + - operator.yaml + - proxyclass.yaml + - dnsconfig.yaml diff --git a/argocd/manifests/tailscale-operator/operator.yaml b/argocd/manifests/tailscale-operator-base/operator.yaml similarity index 100% rename from argocd/manifests/tailscale-operator/operator.yaml rename to argocd/manifests/tailscale-operator-base/operator.yaml diff --git a/argocd/manifests/tailscale-operator/proxyclass.yaml b/argocd/manifests/tailscale-operator-base/proxyclass.yaml similarity index 100% rename from argocd/manifests/tailscale-operator/proxyclass.yaml rename to argocd/manifests/tailscale-operator-base/proxyclass.yaml diff --git a/argocd/manifests/tailscale-operator-ringtail/external-secret.yaml b/argocd/manifests/tailscale-operator-ringtail/external-secret.yaml new file mode 100644 index 0000000..0776420 --- /dev/null +++ b/argocd/manifests/tailscale-operator-ringtail/external-secret.yaml @@ -0,0 +1,32 @@ +--- +# ExternalSecret for Tailscale Operator OAuth credentials +# +# Shares the same 1Password item as indri's operator (same OAuth client). +# Multiple operator instances can share one OAuth client; each registers +# as its own device. +# +# 1Password item: "Tailscale K8s Operator OAuth" in blumeops vault +# Fields: "client-id", "client-secret" +# +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: operator-oauth + namespace: tailscale +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: operator-oauth + creationPolicy: Owner + data: + - secretKey: client_id + remoteRef: + key: Tailscale K8s Operator OAuth + property: client-id + - secretKey: client_secret + remoteRef: + key: Tailscale K8s Operator OAuth + property: client-secret diff --git a/argocd/manifests/tailscale-operator-ringtail/kustomization.yaml b/argocd/manifests/tailscale-operator-ringtail/kustomization.yaml new file mode 100644 index 0000000..a14ca81 --- /dev/null +++ b/argocd/manifests/tailscale-operator-ringtail/kustomization.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: tailscale + +resources: + - ../tailscale-operator-base + - proxygroup-ingress.yaml + - external-secret.yaml diff --git a/argocd/manifests/tailscale-operator-ringtail/proxygroup-ingress.yaml b/argocd/manifests/tailscale-operator-ringtail/proxygroup-ingress.yaml new file mode 100644 index 0000000..9433da9 --- /dev/null +++ b/argocd/manifests/tailscale-operator-ringtail/proxygroup-ingress.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: tailscale.com/v1alpha1 +kind: ProxyGroup +metadata: + name: ingress +spec: + type: ingress + replicas: 1 + proxyClass: default + tags: + - tag:k8s diff --git a/argocd/manifests/tailscale-operator/kustomization.yaml b/argocd/manifests/tailscale-operator/kustomization.yaml index dec1bbc..09fa1b8 100644 --- a/argocd/manifests/tailscale-operator/kustomization.yaml +++ b/argocd/manifests/tailscale-operator/kustomization.yaml @@ -1,12 +1,11 @@ +--- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: tailscale resources: - - operator.yaml - - proxyclass.yaml + - ../tailscale-operator-base - proxygroup-ingress.yaml - - dnsconfig.yaml - egress-forge.yaml - external-secret.yaml diff --git a/docs/changelog.d/tailscale-operator-ringtail.infra.md b/docs/changelog.d/tailscale-operator-ringtail.infra.md new file mode 100644 index 0000000..c5442dc --- /dev/null +++ b/docs/changelog.d/tailscale-operator-ringtail.infra.md @@ -0,0 +1 @@ +Deploy Tailscale operator on ringtail k3s cluster diff --git a/pulumi/tailscale/policy.hujson b/pulumi/tailscale/policy.hujson index e24ca48..e6ddb85 100644 --- a/pulumi/tailscale/policy.hujson +++ b/pulumi/tailscale/policy.hujson @@ -158,7 +158,7 @@ "tag:feed": ["autogroup:admin", "tag:blumeops"], "tag:registry": ["autogroup:admin", "tag:blumeops"], "tag:k8s-api": ["autogroup:admin", "tag:blumeops"], - "tag:k8s-operator": ["autogroup:admin", "tag:blumeops"], + "tag:k8s-operator": ["autogroup:admin", "tag:blumeops", "tag:k8s-operator"], "tag:k8s": ["autogroup:admin", "tag:blumeops", "tag:k8s-operator"], "tag:ci-gateway": ["autogroup:admin", "tag:blumeops"], "tag:flyio-proxy": ["autogroup:admin", "tag:blumeops"],