LDAP, Tailscale, and DNS

Feb 22, 2026

If you just want the technical details of how I set this up, jump to Technical Details


PHEW things have been busy at the spacefish homelab! It's been kind of an infrastructure-maintenance month for me. I had a disk fail on my main storage server, and though I had a hot spare I had to halt the array to online the disk (#UnraidThings), and because I'm a bit of a dum-dum I bungled the restart such that docker and qemu couldn't come back up while the array reinitialized with the new disk... which meant my primary only LDAP server and several of my docker services were offline for a day, which in turn meant no authentication into any of my hosted services was happening.

Reducing single-points-of-failure (specifically on my frankenNAS) has been an ongoing project of mine, so this really just served to accelerate some of my ongoing work, specifically around improving my LDAP reliability. I set off to set up an LDAP replica but ran smack-bang into a DNS misconfiguration from when I initially set up my LDAP environment that took some amount of pain to fix. I'm noting down the directions (and why the DNS bit was important) so as to warn off others from my wayward wanderings.

If you don't know what DNS is, or why it's tricky, unfurl this.

In university my friends and I had a running joke that every course had to start with an introduction to set theory. In my professional life I've come to realize much the same thing about tech blogs: it very often comes back to DNS.

I intend to break this out into its own post, but for now...

DNS is the protocol responsible for turning the name of a computer (e.g. some.website.com) into its IP address (1.2.3.4) so that you can find it on the network. It exists because humans generally remember names better than numbers, and technically speaking DNS can do a lot more than just map computer names to addresses, but we'll get to that.

In home-scale networks we tend not to think about domains or DNS very much. If you haven't taken steps to alter it, it's likely that everything on your network uses your local router as a DNS server, and your local router uses whatever your ISP tells it to use in turn.

Actually there's a lot of holes in this model nowadays; DNS is a deeply insecure protocol so it's becoming more and more common to tunnel it over an encrypted channel, bypassing your local network infrastructure. This is especially common in smartphones. However, the model is still largely correct and relevant to my ends.

Traditionally, DNS is something managed in a control panel on your router. You can say "Let's call IP 10.0.1.3 alice.house and 10.0.1.4 bob.house and 10.0.1.5 office_printer.house" and suddenly you don't have to remember individual IPs anymore. Of course, that won't work outside of your home network, but neither would those IP addresses, so it's a moot point.

To save effort and make everyone's life a bit easier the mDNS protocol does this automatically on a local network by mapping a machine's hostname to hostname.local. Notably, the mDNS protocol works entirely differently from actual DNS: it's basically just ARP, where DNS is more of a directory. For mDNS your machine shouts "which one of you has the hostname kitchen_speaker" onto the local network, and whichever device has that hostname responds with it's own IP, and bam you can now talk to kitchen_speaker.local, which is how Chromecasts and Airplay and printing from your phone all work.

In a corporate environment it's not a great idea to just have every machine constantly shout into the network for every name it wants to lookup, so instead they just integrated DNS to the directory provider, which was neat because it was already handling the names for everything on the network anyway. Now when Bob got his new laptop for his engineering job it could just auto-assign the hostname bob.engineering.company.net and now it's very easy to keep track of his machine on the network. Similarly you can assign the office printer to printer.lab.building5.company.net Simple, neat, and ties into the technology you're using to administrate your whole office.... So long as everything on the network uses the domain controller as the DNS server.

Wait, why are we using LDAP? And what's it have to do with DNS?

Problem #1: I have multiple adults using several shared computers in the same house. I want each adult to be able to sign into each computer with their own username and password. I don't want to have to manually create each user on each machine, and I need the passwords to stay in sync.

Solution #1: Use the technology that corporations, universities, and other large organizations have been using to solve this problem for decades, otherwise known as Active Directory.


Problem #2: Active Directory is primarily a Microsoft technology. I want to use Linux for my workstations.

Solution #2: Red Hat Enterprise Linux / Fedora have native support for LDAP login, and they ship an integrated server as well.


Problem #3: Several of the PCs I want to use LDAP on are laptops, and won't always be on the house network. I also don't want to expose my LDAP server to the internet.

Solution #3: Put everything on Tailscale and get point-to-point encrypted tunnels for everything.


Problem #4: I need a domain for everything on my network to make LDAP happy.

'Solution'' #5: Use the provided 'magic' Tailnet domain as the LDAP domain

Don't do this. The Tailscale server won't properly forward TXT requests to your LDAP and autodiscovery and replication won't work properly.

Actual Solution #5: Use `something.internal` as your LDAP domain name

You can't have "public" .internal domains, so they're perfect for, uh, internal networks: either on a VPN or behind a corporate router or similar.

LDAP DNS specificity

For various reasons LDAP servers have lots of expectations about the DNS structure of the domain they're "controlling." Stuff like:

  1. That every machine on the network has a fully-qualified hostname on that domain. If the LDAP servers are for the domain spacefish.house then they expect the machines on the network to have full hostnames like fish-laptop.spacefish.house, partner-desktop.spacefish.house, printer.office.spacefish.house.
  2. That the LDAP server(s) is/are the authoritative DNS server for that domain
  3. That everything on the network uses the LDAP server(s) for DNS

(1) is easy enough to provide: before attaching a machine to the LDAP server I just had to set its hostname to be fully qualified.

(2) I did not understand at the time, and ignored it. I didn't really care about LDAP managing my DNS, I had Tailscale which could do that for me via MagicDNS (which basically just makes it easy to find everything on the tailnet from a machine connected to said tailnet).

(3) Again, I did not understand this, and ignored it.

Configuring my LDAP server was no problem as I followed this very this extremely helpful (though grammatically suspect) workshop. The workshop expected me to use their provided Vagrant file to get VMs up and running, but it was easy enough to substitute a Fedora Server instance and just install the packages I needed.

Configuring your LDAP client is supposed to be extremely easy, assuming you've held to (2) and (3) above. As part of the install your client figures out what it's domain is (usually just by looking at its hostname, e.g. bob.spacefish.house -> spacefish.house is your domain), then queries for a TXT DNS record named _ldap._tcp.spacefish.house, which is supposed to give it the name of the LDAP servers running on the network, which can then be used to complete setup. Bonus, if you have multiple servers and the one initially used goes offline for whatever reason (maintenance, power outage, cousin spilled water on it) the client can query that record again to get any other servers on the network as a fallback.

However, if, for whatever reason, some other DNS server is being used on the network (e.g., Tailscale's magic DNS), it probably doesn't know anything about LDAP, so it'll ignore any TXT requests you send trying to find an LDAP server. You can (and I did) get around this by manually pointing each LDAP client at a specific LDAP server, but then your automatic failover won't work properly and it's harder to bring replicas online and is just generally not a good time.

The correct way to do this is to set your LDAP domain to either be a domain you control (e.g., if you own spacefish.house), or a domain that nobody could ever control (e.g., whatever.internal, since .internal is reserved by ICANN). If you still want to use Tailscale (or any other DNS provider, e.g. Adguard), you can define a split route and say all DNS queries for spacefish.house ought to go to your domain controller, and everything else can go to your normal DNS.

Technical details

I am not an IT specialist, I only know enough to be really dangerous. Take everything I say with a grain of salt and please read the docs before you do any of this in a production environment. I isolate my servers (ESPECIALLY my authentication providers) on my tailnet because if you screw those up it's really bad for everything on your network and everything that uses your auth servers. Tailscale/Yggdrasil/etc are all really cool and powerful for small scale homelabs.

If you want to set up your own LDAP'd fleet over tailscale, here's some quick notes

LDAP Server

I recommend reading the FreeIPA quickstart docs. Failing that, here's my notes:

  • Start with a Fedora Server instance
  • Make sure the hostname is fully qualified. If you didn't do that in startup (it's fine, I forgot to) override it with sudo hostnamectl set-hostname --static your.new.domain.internal
  • Install tailscale
  • Allow LDAP traffic through the firewall (or just... disable it)
    • firewall-cmd --add-service=freeipa-ldap --add-service=freeipa-4 --permanent
    • for some reason the Fedora firewall service felt way more annoying to me than past system firewalls I've had to interact with. I don't know why, but if you're running into connection issues consider disabling the firewall and see if the problem goes away.
  • Install freeipa-server
    • dnf install freeipa-server freeipa-server-dns
  • Invoke the server install script
    • ipa-server-install
  • Set up Tailscale to split-DNS the LDAP domain to the LDAP server
    • the Tailscale DNS config panel, showing my tailnet name routing to 100.100.100.100 and my internal LDAP domain routing to a tailnet IP, and a global DNS server routing to another tailnet IP
      My tailnet DNS config, where my LDAP domain is LTHS.internal with my primary LDAP server as the DNS and my Adguard server as the 'global'.
  • Ensure you can get a Kerberos ticket as the admin
    • kinit admin
  • Set up new users etc. in the web interface (which should be reachable behind port 443 on your server)
    • there's CLIs too, I'm just lazy
    • For your own user (which should not be the directory admin) you likely want to add the User Administrator and Enrollment Administrator roles; the former lets you admin users and the latter lets you onboard new machines to the LDAP
    • Also also consider setting up the sudo rule (docs) so your LDAP user can have sudo authority on all the machines you onboard
  • Set your Tailnet to split-dns your LDAP domain to your LDAP server
  • Test your DNS: run nslookup -q=SRV _ldap._tcp.your.ldap.domain from any machine on the tailnet that can also access the LDAP server (that only matters if you're using Tailscale ACLs). The output should look something like this:
1nslookup -q=SRV _ldap._tcp.lths.internal
2Server: 127.0.0.53
3Address: 127.0.0.53#53
4
5Non-authoritative answer:
6_ldap._tcp.lths.internal service = 0 100 389 ldap-alpha.lths.internal.
7
8Authoritative answers can be found from:
9ldap-alpha.lths.internal internet address = 100.113.107.60
10ldap-alpha.lths.internal internet address = 192.168.11.171
11ldap-alpha.lths.internal has AAAA address fd7a:115c:a1e0::ce39:6b3c
  • The important bit is that _ldap._tcp.etc is resolving to the domain name of the LDAP server itself, and that authoritative answers are being directed to that server as well.

LDAP client

  • Set up your client OS (for my systems I used Fedora Workstations)
    • I recommend adding a non-LDAP "local" user, in case something goes horribly wrong: then you have a recovery path to fixing the system.
    • Same deal with the hostnames, should be fully qualified. Fix it with sudo hostnamectl set-hostname --static your.new.domain.internal if you forgot
  • Install Tailscale
    • If you're using ACLs (which you should be), ensure the client can reach the server
My ACL looks like this. Providers can talk to other providers to enable replication.
1 "grants": [
2 {
3 "src": ["tag:ldap-access", "tag:ldap-provider"],
4 "dst": ["tag:ldap-provider"],
5
6 "ip": [
7 "tcp:389",
8 "tcp:636",
9 "udp:389",
10 "udp:636",
11 "tcp:3268",
12 "udp:3268",
13 "udp:3269",
14 "tcp:3269",
15 "udp:53",
16 ],
17 },
  • Install the IPA client
    • dnf install freeipa-client
  • Invoke the automatic script
    • ipa-client-install
    • Follow the prompts

If your server is not automatically detected, SOMETHING IS WRONG WITH YOUR DNS! While you CAN proceed with the install by manually specifying the desired domain and the LDAP server address you should probably fix the DNS problem.

  • ta da, you should be able to sign in with LDAP usernames and passwords now! You may have to click the "Other..." button in your signin manager. My machine with a Gnome login manager correctly displays the LDAP users, but my Plasma login managers seem none the wiser. YMMV.
https://hnr.spacefish.net/posts/feed.xml