{"record":{"id":"bacda77be3773427","repo":"juanfont/headscale","slug":"server-url-cannot-be-part-of-base-domain-in-a-way","errorCode":null,"errorMessage":"server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable","messagePattern":"server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable","errorType":"validation","errorClass":"errServerURLSuffix","httpStatus":null,"severity":"error","filePath":"hscontrol/types/config.go","lineNumber":39,"sourceCode":"\t\"tailscale.com/net/tsaddr\"\n\t\"tailscale.com/tailcfg\"\n\t\"tailscale.com/types/dnstype\"\n\t\"tailscale.com/util/set\"\n)\n\nconst (\n\tPKCEMethodPlain string = \"plain\"\n\tPKCEMethodS256  string = \"S256\"\n\n\tdefaultNodeStoreBatchSize = 100\n)\n\nvar (\n\terrOidcMutuallyExclusive     = errors.New(\"oidc_client_secret and oidc_client_secret_path are mutually exclusive\")\n\terrOIDCIssuerInvalid         = errors.New(\"oidc.issuer must be a valid http(s) URL\")\n\terrOIDCClientIDRequired      = errors.New(\"oidc.client_id is required when oidc.issuer is set\")\n\terrOIDCClientSecretRequired  = errors.New(\"oidc.client_secret or oidc.client_secret_path is required when oidc.issuer is set\")\n\terrServerURLSuffix           = errors.New(\"server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable\")\n\terrServerURLSame             = errors.New(\"server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable\")\n\terrInvalidPKCEMethod         = errors.New(\"pkce.method must be either 'plain' or 'S256'\")\n\terrTrustedProxyZeroRange     = errors.New(\"0.0.0.0/0 and ::/0 are not allowed\")\n\tErrNoPrefixConfigured        = errors.New(\"no IPv4 or IPv6 prefix configured, minimum one prefix is required\")\n\tErrInvalidAllocationStrategy = errors.New(\"invalid prefix allocation strategy\")\n)\n\ntype IPAllocationStrategy string\n\nconst (\n\tIPAllocationStrategySequential IPAllocationStrategy = \"sequential\"\n\tIPAllocationStrategyRandom     IPAllocationStrategy = \"random\"\n)\n\ntype PolicyMode string\n\nconst (\n\tPolicyModeDB   = \"database\"","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/types/config.go#L21-L57","documentation":"errServerURLSuffix is an unexported config validation error in hscontrol/types/config.go:39 returned by isSafeServerURL (config.go:1342) when the server_url hostname ends with '.'+base_domain (e.g. server_url https://hs.example.com with base_domain example.com). MagicDNS makes the tailnet authoritative for base_domain, so a server_url inside it would make the control plane and DERP unreachable once Tailscale takes over the domain.","triggerScenarios":"Setting dns.base_domain to the same registrable domain that hosts the headscale server; e.g. base_domain example.com with server_url https://headscale.example.com; covered by config_test.go cases (lines 167, 549-590).","commonSituations":"Operators wanting MagicDNS names like machine.example.com on their public domain; small deployments using one domain for everything; following tutorials that suggest putting headscale under the same domain as the tailnet.","solutions":["Move server_url to a domain outside base_domain (e.g. serve headscale on headscale.example.net while base_domain is example.com)","Or change base_domain to a dedicated subdomain zone (e.g. tail.example.com hosts only the tailnet)","Keep DERP hostnames likewise outside base_domain","Restart headscale and verify nodes can still resolve and reach the control plane"],"exampleFix":"# before\nserver_url: https://headscale.example.com\ndns:\n  base_domain: example.com\n\n# after\nserver_url: https://headscale.example.net\ndns:\n  base_domain: example.com","handlingStrategy":"validation","validationCode":"host := urlHostname(cfg.ServerURL)\nif strings.HasSuffix(host, \".\"+cfg.BaseDomain) {\n    return errors.New(\"server_url inside base_domain is unsafe\")\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Host headscale and DERP on domains outside dns.base_domain","Reserve a dedicated zone (subdomain) exclusively for MagicDNS host names"],"tags":["headscale","config","dns","magicdns","networking"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}