#2152·DnsServer

DNS Server reports "started successfully" and systemd shows the service healthy when all DNS endpoint binds have failed

Author: sproggitCreated Sep 15, 2026Updated Sep 16, 2026

Hello,

Today I stumbled across a bit of a weird error. I appreciate that I'm reporting this against v14.3, but if the architecture is the same for the 15.x branch, this might benefit from a look. A couple of bits of relevant context for what follows:-

I wanted to run a "UAT" upgrade from 14.3 to 15.4, so I just created a pair of clean installations [Primary/Secondary] with the intent of giving them test configurations and then running the update process. I sat down to do the setup this afternoon and decided to start with a "sudo apt-get update"/"sudo apt-get upgrade" on each host. This failed - and it turns out that it failed because I had Technitium configured incorrectly.

I've now fixed that error - but in the process of working through that with Claude Opus, we spotted another possibly significant issue with the configuration of the systemd service files for the DNS. When we got to the end of the triage process and tested a working fix, I asked Claude to draft up an Issue Report - that's what you'll find below.

I think Claude's report is likely a lot more direct than anything I could produce!

Version: 14.3.0.0 Platform: Raspberry Pi 4B (arm64), Raspberry Pi OS / Debian trixie Install method: official Linux installer script

Summary

When DNS Server Local End Points is configured with a specific IP address that is not yet present on an interface at service start, the UDP and TCP binds for port 53 both fail. The failure is logged, but the server then logs DNS Server was started successfully. and continues running. systemd reports the unit as active (running).

The result is a DNS server that is up, healthy by every normal check, and serving nothing at all — indefinitely, and across reboots.

Environment / configuration

The host uses a virtual IP for the DNS service, configured as a secondary address on eth0, so that the service can be moved between hosts without reconfiguring clients:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    inet 172.16.120.1/16 brd 172.16.255.255 scope global noprefixroute eth0
    inet 172.16.220.1/16 brd 172.16.255.255 scope global secondary noprefixroute eth0

DNS Server Local End Points is set to 172.16.220.1:53.

Steps to reproduce

  1. Configure a secondary IPv4 address on an interface, managed by NetworkManager.
  2. Set DNS Server Local End Points to that secondary address.
  3. Reboot.

Actual behaviour

From /etc/dns/logs/:

[2026-09-15 14:31:29 UTC] [[::]:5380] [HTTP] Web Service was bound successfully.
[2026-09-15 14:31:34 UTC] [172.16.220.1:53] [UDP] DNS Server failed to bind.
System.Net.Sockets.SocketException (99): Cannot assign requested address
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at DnsServerCore.Dns.DnsServer.StartAsync(Boolean throwIfBindFails) in DnsServerCore/Dns/DnsServer.cs:line 6172
[2026-09-15 14:31:34 UTC] [172.16.220.1:53] [TCP] DNS Server failed to bind.
System.Net.Sockets.SocketException (99): Cannot assign requested address
   ...DnsServerCore/Dns/DnsServer.cs:line 6248
[2026-09-15 14:31:34 UTC] DNS Server (v14.3.0.0) was started successfully.

systemctl status dns.service afterwards:

Active: active (running) since Tue 2026-09-15 15:31:27 BST
Sep 15 15:31:34 abbott dns-server[635]: Technitium DNS Server was started successfully.

ss -lntup | grep ':53' returns nothing for the DNS server. The address is present on the interface by the time the system is up — only the bind attempt was too early. Nothing retries it, so the server stays in this state until manually restarted.

The bind is not a race that is sometimes won: the shipped dns.service unit has no After= or Wants= ordering with respect to the network, so it starts before addresses are configured on every boot.

Why this is easy to miss

Three things combine to hide it:

  1. The server logs started successfully immediately after logging that every DNS endpoint failed to bind.
  2. systemd shows the unit as healthy, because the process does not exit — so Restart=always in the shipped unit never fires.
  3. The web service behaves differently from the DNS service: when its configured bind fails it falls back to the default [::]:5380, so the admin console remains reachable and the server looks fine from the UI.

The presenting symptom was Temporary failure resolving from apt-get update on the host itself, which points a user toward client-side DNS configuration rather than toward the server.

Expected behaviour

Any of the following would be a significant improvement:

  1. Exit non-zero when all configured DNS endpoints fail to bind. The shipped unit already has Restart=always and RestartSec=10, so the service would recover automatically once the address appears, with no user action required. This looks like the smallest change with the largest benefit.
  2. Retry failed endpoint binds periodically in the background, rather than attempting once at startup only.
  3. Do not log started successfully when no DNS endpoint bound, and surface a persistent warning on the dashboard while any configured endpoint is unbound.
  4. Add After=network-online.target / Wants=network-online.target to the shipped unit file. Worth doing, though on its own it is not sufficient — that target can be reached before a secondary address has been attached to an interface.

Current workaround

A systemd drop-in that waits for the address before starting the service:

ini
# /etc/systemd/system/dns.service.d/override.conf
[Unit]
After=network-online.target
Wants=network-online.target

[Service]
ExecStartPre=/usr/bin/timeout 30 /bin/bash -c 'until ip -4 -o addr show | grep -q "inet 172.16.220.1/"; do sleep 1; done'

Source: TechnitiumSoftware/DnsServer