Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale 1.0.0-dev.7

This is a prerelease version of Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale.
dotnet add package Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale --version 1.0.0-dev.7
                    
NuGet\Install-Package Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale -Version 1.0.0-dev.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale" Version="1.0.0-dev.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale" Version="1.0.0-dev.7" />
                    
Directory.Packages.props
<PackageReference Include="Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale --version 1.0.0-dev.7
                    
#r "nuget: Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale, 1.0.0-dev.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale@1.0.0-dev.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale&version=1.0.0-dev.7&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale&version=1.0.0-dev.7&prerelease
                    
Install as a Cake Tool

Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale

NuGet License

.NET Aspire hosting extensions for publishing Tailscale Kubernetes Operator resources. This package adds resource-local Tailscale service intent and Kubernetes environment resource-definition helpers.

Installation

dotnet add package Arkanis.Aspire.Hosting.Extensions.Kubernetes.Tailscale

Quick Start

Configure the tailnet once when generated Tailscale Ingress hosts should use the default <tailnet>.ts.net MagicDNS suffix. With the resource name web, the following example emits an Ingress host of web-staging.my-tailnet.ts.net.

using Aspire.Hosting;
using Aspire.Hosting.Extensions.Kubernetes;
using Aspire.Hosting.Extensions.Kubernetes.Tailscale;

var builder = DistributedApplication.CreateBuilder(args);

var web = builder.AddProject<Projects.Web>("web");
var kubernetes = builder.AddKubernetesEnvironment("kubernetes");

kubernetes.AddTailscale(tailscale => tailscale
    .WithTailnet("my-tailnet")
    .WithHostnameSuffix("staging")
    .ForResource(web, resource => resource.ExposeIngress("web-tailscale", ingress => ingress
        .WithProxyGroup("staging-k8s-ingress-proxies")
        .ToGeneratedService("http"))));

builder.Build().Run();

Hostnames

HostnamePrefix and HostnameSuffix decorate the generated short MagicDNS name. By default, the generated short name is based on the Aspire resource name, so citizenid-dashboard with HostnameSuffix set to staging becomes citizenid-dashboard-staging. Ingress resource names are not included in the generated hostname.

WithHostnameBase("dashboard") replaces only the resource-name part of the generated short MagicDNS name. HostnamePrefix and HostnameSuffix still apply, so WithHostnameSuffix("staging") plus WithHostnameBase("dashboard") becomes dashboard-staging. Use this when a Service or Ingress needs a shorter stable base while still sharing the environment naming convention.

WithTailnet("my-tailnet") expands generated Ingress MagicDNS names to fully qualified hosts under my-tailnet.ts.net. The same setting accepts my-tailnet.ts.net when configuration already stores the full DNS suffix. For citizenid-dashboard with HostnameSuffix set to staging, the generated Ingress host becomes citizenid-dashboard-staging.my-tailnet.ts.net.

WithMagicDnsName("dashboard") overrides only the short MagicDNS name. For Ingress exposure, the configured tailnet still expands it to dashboard.my-tailnet.ts.net. For Service exposure, the value remains the short name written to tailscale.com/hostname.

WithHostname("dashboard.internal.example.com") is an exact override. It is emitted unchanged and never receives the configured tailnet suffix. Use it when the final Kubernetes host is already known or must not be a Tailscale MagicDNS name.

Hostname resolution precedence is exact Hostname, then exact-short MagicDnsName, then generated HostnamePrefix plus HostnameBase or resource name plus HostnameSuffix.

Dedicated Service

Use a dedicated Service when only one port should be reachable through Tailscale. The tailnet setting does not append .ts.net to Service hostnames because Tailscale Service annotations request a machine name.

kubernetes.AddTailscale(tailscale => tailscale
    .WithHostnameSuffix("staging")
    .ForResource(new ResourceName("citizenid-dashboard"), resource => resource.ExposeService(service => service
        .AsStandalone()
        .WithHostnameBase("dashboard")
        .EmitDedicatedService("dashboard-ingress-tailscale", dedicated => dedicated
            .WithAspireResourceSelector(new ResourceName("citizenid-dashboard"))
            .WithPort(80, 18888)))));

Ingress

Use a Tailscale Ingress when the workload should be exposed through Kubernetes Ingress resources. When a tailnet is configured, the same fully qualified host is emitted into spec.rules[0].host and spec.tls[0].hosts[0]. secretName is always emitted and defaults to {ingressName}-tls, although Tailscale manages the certificate itself.

kubernetes.AddTailscale(tailscale => tailscale
    .WithTailnet("my-tailnet")
    .WithHostnameSuffix("staging")
    .ForResource(web, resource => resource.ExposeIngress("web-tailscale", ingress => ingress
        .WithHostnameBase("web")
        .WithProxyGroup("staging-k8s-ingress-proxies")
        .WithFunnel()
        .WithInClusterMagicDnsForwarding()
        .ToGeneratedService("http"))));

This produces the important Ingress shape below.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-tailscale
  annotations:
    tailscale.com/proxy-group: staging-k8s-ingress-proxies
    tailscale.com/funnel: "true"
    tailscale.com/experimental-forward-cluster-traffic-via-ingress: "true"
spec:
  ingressClassName: tailscale
  rules:
  - host: web-staging.my-tailnet.ts.net
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              name: http
  tls:
  - hosts:
    - web-staging.my-tailnet.ts.net
    secretName: web-tailscale-tls

Use WithTlsSecretName("custom-tls") when a chart convention needs a different placeholder Secret name.

Configuration

Configuration can provide tailnet, hostnames, tags, ProxyGroups, Ingress options, and shared defaults while code supplies missing selectors or port safety.

kubernetes.AddTailscale(
    builder.Configuration,
    tailscale => tailscale.ForResource(web, resource => resource.ExposeService(service => service
        .EmitDedicatedService("web-tailscale", dedicated => dedicated
            .WithPort(80, 8080)))));
{
  "Kubernetes": {
    "Tailscale": {
      "Tailnet": "my-tailnet",
      "HostnameSuffix": "staging",
      "Resources": {
        "web": {
          "Ingresses": {
            "web-tailscale": {
              "Enabled": true,
              "ProxyGroup": "staging-k8s-ingress-proxies",
              "HostnameBase": "web-admin",
              "Funnel": true,
              "ForwardClusterTrafficViaIngress": true,
              "TlsSecretName": "web-admin-tailscale-tls"
            }
          },
          "Service": {
            "Enabled": true,
            "HostnameBase": "web-service",
            "DedicatedService": {
              "Enabled": true,
              "ServiceName": "web-tailscale"
            }
          }
        }
      }
    }
  }
}

In this configuration, the Ingress host is web-admin-staging.my-tailnet.ts.net. The Service hostname annotation is web-service-staging.

Scope

This package emits Tailscale Kubernetes Operator resource intent during Aspire publish. It does not install the operator, create OAuth credentials, create or configure tailnets, or apply generated manifests to a live cluster.

Dependency

This package references Arkanis.Aspire.Hosting.Extensions.Kubernetes.

Repository

Source, issues, and release workflow details are available at https://github.com/ArkanisCorporation/Aspire.Hosting.Extensions.Kubernetes.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-dev.7 81 7/5/2026
1.0.0-dev.6 52 7/5/2026
1.0.0-dev.5 72 7/4/2026
1.0.0-dev.4 70 7/3/2026
1.0.0-dev.3 57 7/2/2026
1.0.0-dev.2 247 6/16/2026
1.0.0-dev.1 80 6/11/2026