diff --git a/cmd/k8s-nameserver/main.go b/cmd/k8s-nameserver/main.go
index ca4b449358083..cc1e226a79591 100644
--- a/cmd/k8s-nameserver/main.go
+++ b/cmd/k8s-nameserver/main.go
@@ -11,6 +11,7 @@ package main
import (
"context"
"encoding/json"
+ "flag"
"fmt"
"log"
"net"
@@ -26,9 +27,12 @@ import (
"tailscale.com/util/dnsname"
)
+var (
+ // domain is the DNS domain that this nameserver has registered a handler for.
+ domain = flag.String("domain", "ts.net", "the DNS domain to serve records for")
+)
+
const (
- // tsNetDomain is the domain that this DNS nameserver has registered a handler for.
- tsNetDomain = "ts.net"
// addr is the the address that the UDP and TCP listeners will listen on.
addr = ":1053"
@@ -40,7 +44,7 @@ const (
)
// nameserver is a simple nameserver that responds to DNS queries for A records
-// for ts.net domain names over UDP or TCP. It serves DNS responses from
+// for the names of the given domain over UDP or TCP. It serves DNS responses from
// in-memory IPv4 host records. It is intended to be deployed on Kubernetes with
// a ConfigMap mounted at /config that should contain the host records. It
// dynamically reconfigures its in-memory mappings as the contents of the
@@ -78,11 +82,11 @@ func main() {
// reset when the configuration changes.
ns.runRecordsReconciler(ctx)
- // Register a DNS server handle for ts.net domain names. Not having a
+ // Register a DNS server handle for names of the domain. Not having a
// handle registered for any other domain names is how we enforce that
- // this nameserver can only be used for ts.net domains - querying any
+ // this nameserver can only be used for the given domain - querying any
// other domain names returns Rcode Refused.
- dns.HandleFunc(tsNetDomain, ns.handleFunc())
+ dns.HandleFunc(*domain, ns.handleFunc())
// Listen for DNS queries over UDP and TCP.
udpSig := make(chan os.Signal)
diff --git a/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml
index 13aee9b9e9ebf..fd6093b00d8a3 100644
--- a/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml
+++ b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml
@@ -80,6 +80,11 @@ spec:
required:
- nameserver
properties:
+ domain:
+ description: |-
+ Domain is the domain for which DNS entries will be resolved. If left
+ empty, the default of the k8s-nameserver will be used.
+ type: string
nameserver:
description: |-
Configuration for a nameserver that can resolve ts.net DNS names
diff --git a/cmd/k8s-operator/deploy/manifests/operator.yaml b/cmd/k8s-operator/deploy/manifests/operator.yaml
index 1a812b7362757..9777d328502ed 100644
--- a/cmd/k8s-operator/deploy/manifests/operator.yaml
+++ b/cmd/k8s-operator/deploy/manifests/operator.yaml
@@ -325,6 +325,11 @@ spec:
More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
properties:
+ domain:
+ description: |-
+ Domain is the domain for which DNS entries will be resolved. If left
+ empty, the default of the k8s-nameserver will be used.
+ type: string
nameserver:
description: |-
Configuration for a nameserver that can resolve ts.net DNS names
diff --git a/cmd/k8s-operator/nameserver.go b/cmd/k8s-operator/nameserver.go
index 52577c929acea..02f5912a15e4e 100644
--- a/cmd/k8s-operator/nameserver.go
+++ b/cmd/k8s-operator/nameserver.go
@@ -177,6 +177,9 @@ func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsa
if tsDNSCfg.Spec.Nameserver.Image != nil && tsDNSCfg.Spec.Nameserver.Image.Tag != "" {
dCfg.imageTag = tsDNSCfg.Spec.Nameserver.Image.Tag
}
+ if tsDNSCfg.Spec.Domain != "" {
+ dCfg.domain = tsDNSCfg.Spec.Domain
+ }
for _, deployable := range []deployable{saDeployable, deployDeployable, svcDeployable, cmDeployable} {
if err := deployable.updateObj(ctx, dCfg, a.Client); err != nil {
return fmt.Errorf("error reconciling %s: %w", deployable.kind, err)
@@ -207,6 +210,7 @@ type deployConfig struct {
labels map[string]string
ownerRefs []metav1.OwnerReference
namespace string
+ domain string
}
var (
@@ -227,6 +231,9 @@ var (
return fmt.Errorf("error unmarshalling Deployment yaml: %w", err)
}
d.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag)
+ if cfg.domain != "" {
+ d.Spec.Template.Spec.Containers[0].Args = []string{"-domain", cfg.domain}
+ }
d.ObjectMeta.Namespace = cfg.namespace
d.ObjectMeta.Labels = cfg.labels
d.ObjectMeta.OwnerReferences = cfg.ownerRefs
diff --git a/k8s-operator/api.md b/k8s-operator/api.md
index e8a6e248a2934..913d5b9bf9fe4 100644
--- a/k8s-operator/api.md
+++ b/k8s-operator/api.md
@@ -211,6 +211,7 @@ _Appears in:_
| Field | Description | Default | Validation |
| --- | --- | --- | --- |
| `nameserver` _[Nameserver](#nameserver)_ | Configuration for a nameserver that can resolve ts.net DNS names
associated with in-cluster proxies for Tailscale egress Services and
Tailscale Ingresses. The operator will always deploy this nameserver
when a DNSConfig is applied. | | |
+| `domain` _string_ | Domain is the domain for which DNS entries will be resolved. If left
empty, the default of the k8s-nameserver will be used. | | |
#### DNSConfigStatus
diff --git a/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go
index 60d212279f4f5..d58214511b7d7 100644
--- a/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go
+++ b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go
@@ -75,6 +75,10 @@ type DNSConfigSpec struct {
// Tailscale Ingresses. The operator will always deploy this nameserver
// when a DNSConfig is applied.
Nameserver *Nameserver `json:"nameserver"`
+ // Domain is the domain for which DNS entries will be resolved. If left
+ // empty, the default of the k8s-nameserver will be used.
+ // +optional
+ Domain string `json:"domain"`
}
type Nameserver struct {