{"slug":"control-access-to-proxygroup-resources","title":"Control access to ProxyGroup resources","tags":["tailscale","access-control","containers"],"agent_summary":"Last validated: Mar 9, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Control access to ProxyGroup resources\r\n\r\nLast validated: Mar 9, 2026\r\n\r\nKubernetes Operator ProxyGroupPolicy resourcesare currently [in alpha](https://tailscale.com/docs/reference/tailscale-release-stages#alpha). To try it, follow the steps below to enable it for your network using Tailscale v1.96 or later.\r\n\r\nWhen managing a multi-tenant Kubernetes cluster, you may wish to limit access to your deployed `ProxyGroup` resources,\r\nespecially when those `ProxyGroup` instances use different tailnets. For operator versions 1.96, and later you can now\r\nuse the `ProxyGroupPolicy` resource that lets cluster administrators limit usage of the `tailscale.com/proxy-group`\r\nannotation on `Service` and `Ingress` resources within individual namespaces.\r\n\r\n`ProxyGroupPolicy` resources let you specify whether a namespace can use a given `ProxyGroup` for ingress or egress.\r\nShould a user attempt to create an `Ingress` or `Service` that specifies a `ProxyGroup`'s name that is not within\r\nthe allow list, it will be rejected by the Kubernetes API server.\r\n\r\n## [Prerequisites](https://tailscale.com/docs/features/kubernetes-operator/how-to/proxy-group-policy\\#prerequisites)\r\n\r\n- [Set up the Kubernetes Operator](https://tailscale.com/docs/features/kubernetes-operator#setup).\r\n\r\nA namespace that contains no `ProxyGroupPolicy` resource is effectively\r\nconsidered an \"allow-all\". When applying a `ProxyGroupPolicy` to a namespace that\r\nalready contains `Service` or `Ingress` resources using the\r\n`tailscale.com/proxy-group` annotation, these resources will not be evaluated until they are\r\nnext modified.\r\n\r\nBelow is an example of a `ProxyGroupPolicy` that limits access to all `ProxyGroup` resources, effectively a \"deny-all\"\r\npolicy:\r\n\r\n```yaml\r\napiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: deny-all\r\n  namespace: example\r\nspec:\r\n  ingress: []\r\n  egress: []\r\n```\r\n\r\nThe above `ProxyGroupPolicy` will be transformed into native `ValidatingAdmissionPolicy` and `ValidatingAdmissionPolicyBinding`\r\nresources that evaluate the contents of the `tailscale.com/proxy-group` annotation on `Ingress` and `Service` resources\r\nwithin the same namespace.\r\n\r\nIf a namespace contains multiple `ProxyGroupPolicy` resources, they will be\r\nmerged into a single `ValidatingAdmissionPolicy` resource.\r\n\r\n## [Multi-tenant example](https://tailscale.com/docs/features/kubernetes-operator/how-to/proxy-group-policy\\#multi-tenant-example)\r\n\r\nImagine a multi-tenant Kubernetes cluster in which teams use separate tailnets for their services and each team is granted\r\na namespace within the cluster for their own personal workloads.\r\n\r\nTo set up access to their respective tailnets a `ProxyGroup` resource is created for each team pointing to their personal\r\ntailnets. To ensure ingress or egress is not allowed to any other tailnets from those namespaces, a `ProxyGroupPolicy`\r\ncan be specified for each namespace:\r\n\r\n```yaml\r\napiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: billing\r\n  namespace: team-billing\r\nspec:\r\n  ingress:\r\n    - billing-ingress\r\n  egress:\r\n    - billing-egress\r\n---\r\napiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: customer-engineering\r\n  namespace: team-customer-engineering\r\nspec:\r\n  ingress:\r\n    - customer-engineering-ingress\r\n  egress:\r\n    - customer-engineering-egress\r\n```\r\n\r\nThis then only lets `Service` and `Ingress` resources within the `team-billing` namespace use the `billing-ingress`\r\nand `billing-egress``tailscale.com/proxy-group` annotations. The following `Ingress` resource would then be rejected by\r\nthe Kubernetes API server:\r\n\r\n```yaml\r\napiVersion: networking.k8s.io/v1\r\nkind: Ingress\r\nmetadata:\r\n  name: example-ingress\r\n  namespace: team-billing\r\n  annotations:\r\n    tailscale.com/proxy-group: customer-engineering-egress\r\nspec:\r\n  defaultBackend:\r\n    service:\r\n      name: example\r\n      port:\r\n        number: 80\r\n  ingressClassName: tailscale\r\n  tls:\r\n    - hosts:\r\n        - example\r\n```\r\n\r\nThe same will also occur for any other ingress/egress methods the operator supports that rely on `ProxyGroup` resources.\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Control access to ProxyGroup resources</h1>\n<p>Last validated: Mar 9, 2026</p>\n<p>Kubernetes Operator ProxyGroupPolicy resourcesare currently <a href=\"https://tailscale.com/docs/reference/tailscale-release-stages#alpha\">in alpha</a>. To try it, follow the steps below to enable it for your network using Tailscale v1.96 or later.</p>\n<p>When managing a multi-tenant Kubernetes cluster, you may wish to limit access to your deployed <code>ProxyGroup</code> resources,\r\nespecially when those <code>ProxyGroup</code> instances use different tailnets. For operator versions 1.96, and later you can now\r\nuse the <code>ProxyGroupPolicy</code> resource that lets cluster administrators limit usage of the <code>tailscale.com/proxy-group</code>\r\nannotation on <code>Service</code> and <code>Ingress</code> resources within individual namespaces.</p>\n<p><code>ProxyGroupPolicy</code> resources let you specify whether a namespace can use a given <code>ProxyGroup</code> for ingress or egress.\r\nShould a user attempt to create an <code>Ingress</code> or <code>Service</code> that specifies a <code>ProxyGroup</code>'s name that is not within\r\nthe allow list, it will be rejected by the Kubernetes API server.</p>\n<h2><a href=\"https://tailscale.com/docs/features/kubernetes-operator/how-to/proxy-group-policy#prerequisites\">Prerequisites</a></h2>\n<ul>\n<li><a href=\"https://tailscale.com/docs/features/kubernetes-operator#setup\">Set up the Kubernetes Operator</a>.</li>\n</ul>\n<p>A namespace that contains no <code>ProxyGroupPolicy</code> resource is effectively\r\nconsidered an \"allow-all\". When applying a <code>ProxyGroupPolicy</code> to a namespace that\r\nalready contains <code>Service</code> or <code>Ingress</code> resources using the\r\n<code>tailscale.com/proxy-group</code> annotation, these resources will not be evaluated until they are\r\nnext modified.</p>\n<p>Below is an example of a <code>ProxyGroupPolicy</code> that limits access to all <code>ProxyGroup</code> resources, effectively a \"deny-all\"\r\npolicy:</p>\n<pre><code class=\"language-yaml\">apiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: deny-all\r\n  namespace: example\r\nspec:\r\n  ingress: []\r\n  egress: []\n</code></pre>\n<p>The above <code>ProxyGroupPolicy</code> will be transformed into native <code>ValidatingAdmissionPolicy</code> and <code>ValidatingAdmissionPolicyBinding</code>\r\nresources that evaluate the contents of the <code>tailscale.com/proxy-group</code> annotation on <code>Ingress</code> and <code>Service</code> resources\r\nwithin the same namespace.</p>\n<p>If a namespace contains multiple <code>ProxyGroupPolicy</code> resources, they will be\r\nmerged into a single <code>ValidatingAdmissionPolicy</code> resource.</p>\n<h2><a href=\"https://tailscale.com/docs/features/kubernetes-operator/how-to/proxy-group-policy#multi-tenant-example\">Multi-tenant example</a></h2>\n<p>Imagine a multi-tenant Kubernetes cluster in which teams use separate tailnets for their services and each team is granted\r\na namespace within the cluster for their own personal workloads.</p>\n<p>To set up access to their respective tailnets a <code>ProxyGroup</code> resource is created for each team pointing to their personal\r\ntailnets. To ensure ingress or egress is not allowed to any other tailnets from those namespaces, a <code>ProxyGroupPolicy</code>\r\ncan be specified for each namespace:</p>\n<pre><code class=\"language-yaml\">apiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: billing\r\n  namespace: team-billing\r\nspec:\r\n  ingress:\r\n    - billing-ingress\r\n  egress:\r\n    - billing-egress\r\n---\r\napiVersion: tailscale.com/v1alpha1\r\nkind: ProxyGroupPolicy\r\nmetadata:\r\n  name: customer-engineering\r\n  namespace: team-customer-engineering\r\nspec:\r\n  ingress:\r\n    - customer-engineering-ingress\r\n  egress:\r\n    - customer-engineering-egress\n</code></pre>\n<p>This then only lets <code>Service</code> and <code>Ingress</code> resources within the <code>team-billing</code> namespace use the <code>billing-ingress</code>\r\nand <code>billing-egress``tailscale.com/proxy-group</code> annotations. The following <code>Ingress</code> resource would then be rejected by\r\nthe Kubernetes API server:</p>\n<pre><code class=\"language-yaml\">apiVersion: networking.k8s.io/v1\r\nkind: Ingress\r\nmetadata:\r\n  name: example-ingress\r\n  namespace: team-billing\r\n  annotations:\r\n    tailscale.com/proxy-group: customer-engineering-egress\r\nspec:\r\n  defaultBackend:\r\n    service:\r\n      name: example\r\n      port:\r\n        number: 80\r\n  ingressClassName: tailscale\r\n  tls:\r\n    - hosts:\r\n        - example\n</code></pre>\n<p>The same will also occur for any other ingress/egress methods the operator supports that rely on <code>ProxyGroup</code> resources.</p>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}